Struts2学习总结三
Struts2学习总结三
其实,写到这里,Struts2早已经被淘汰!虽然面试的时候还会面试有关于struts2的相关内容。不过开发已经不作为重点了。所以接下在几个点,就略略的概括掉一下就行了!
今天写这么几个点:
- OGNL表达式。
- 文件上传。
- 防止表单重复提交。
- Struts2的UI标签(这里我就直接放一个别人的博客了)
1、OGNL表达式
分几个点介绍一下:
- 什么是OGNL。
- OGNL投影。
- 支持普通方法调用
- 访问静态成员(方法,字段)
- 操作集合对象
- OGNL的功能。
- OGNL常用标签。
- OGNL其他标签。
1.1、什么是OGNL。
OGNL(Object-Graph Navigation Language,对象图导航语言),它是一个功能强大的表达式语言,用来获取和设置Java对象的属性以及调用对象的方法。它旨在提供一个更高的更抽象的层次来对Java对象图进行导航。
OGNL是Struts2的默认表达语言,OGNL表达式的计算是围绕OGNL上下文(Context)进行的,相当于一个Map对象,见下图的结构:
可以看到值栈是root
。
1.2、OGNL的3个符号。
OGNL中重要的3个符号:#、%、$
。
1.2.1、#符号
有以下三个功能:
- 访问非root对象(也就是非值栈)。
- 用于过滤和投影集合。
- 构造Map集合。
1.2.1.1、访问非root对象
例如:
<!-- 等同于${sessionScope.user} -->
<s:property value="#session.user"/>
<!-- 等同于${requestScope.user} -->
<s:property value="#request.user"/>
1.2.1.1、用于过滤和投影集合
例如(下面的那个标签类似于c:foreach):
<!--
三种表现形式:
1. ?#:满足条件的所有
2. ^#:满足条件的第一条
3. $#:满足条件的最后一条
-->
<!--
假设有一个List<User>的集合名为userList
并且User有一个age的属性
-->
<!-- value=""等价于c:foreach的items -->
<!-- OGNL过滤集合的语法为:collection.{?expression} -->
<s:iterator value="userList.{?#this.age>17}">
<!-- 筛选出大于17岁也就是大于等于18岁的人的用户集合 -->
</s:iterator>
<!-- 其他两个同理 -->
1.2.1.1、构造Map集合
例如:
<s:radio list="#{'male':'男','female':'女'}" />
1.3、OGNL的功能。
有下面几个功能:
- 支持普通方法调用
- 访问静态成员(方法,字段)
- 操作集合对象
1.3.1、支持普通方法调用
例如:
<s:property value="'hello'.length()"/>
1.3.2、访问静态成员(方法,字段)
在使用静态之前,需要在struts.xml文件中配置这个常量值:<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
。
1.3.2.1、访问静态属性
/* 访问静态属性表达式的格式为:@[类全名(包括包路径)]@[值名] */
<s:property value="@包路径.类名@字段名"/>
1.3.2.2、访问静态方法
/* 调用静态方法表达式的格式为:@[类全名(包括包路径)]@[方法名] */
<s:property value="@包路径.类名@方法名(参数...)"/>
1.3.2.3、调用Math静态
<s:property value="@@max(2, 3)" />
1.3.3、操作集合对象
<!-- 假设值栈中,存在一个List<User>的集合对象,名为userList -->
<s:property value="userList[0].username"/>
<s:property value="userList[1].username"/>
<!-- 或者值栈中还存在一个Map<String,String>的集合对象,名为map
其中有这样的键值对:"hello"-"world","struts1"-"struts2"
-->
<s:property value="map.struts1"/>
<s:property value="map.['hello']"/>
<!-- 访问map中所有的key和value -->
<s:property value="map.keys"/>
<s:property value="map.values"/>
1.4、OGNL常用标签
s:iterator标签
<!-- 迭代标签
假设值栈中有一个List<User>,名为userList。
-->
<s:iterator value="userList" var="user" status="s">
索引:<s:property value="#s.index"/>
数量:<s:property value="#s.count"/>
是否奇数:<s:property value="#s.odd"/>
是否偶数:<s:property value="#s.even"/>
用户名:<s:property value="#user.username"/>
</s:iterator>
s:if标签
<s:if test="userList[9]!=null">
值栈中的userList第10个元素不为空
</s:if>
<s:elseif test="userList!=null">
值栈中的userList不为空
</s:elseif>
<s:else>
值栈中的userList为空
</s:else>
1.5、不常用标签
- s:set标签
- s:action标签
- s:url标签
- s:a标签
- 等…
2、文件上传
分下面几点说明:
- 文件上传配置。
- 文件上传错误消息配置。
- 多文件上传。
- 文件下载。
2.1、文件上传配置
以下几步:
- 创建FileUploadAction类。
- 配置文件上传大小。
- 限制文件上传类型。
- 限制文件上传拓展名。
- 编写index.jsp。
2.1.1、创建FileUploadAction类
package com.csa.action;
import java.io.File;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport {
// 创建getter/setter方法,说明存入值栈中!
private String url;
// 下面三个字段都是upload.jar提供的,struts要求必须这样写!
// 上传的文件
private File img;
// 文件名,固定写法 文件变量名+FileName
private String imgFileName;
// 文件类型,固定写法 文件变量名+ContentType
private String imgFileContentType;
public String upload() {
// 1.存储路径
String dir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/files");
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();
}
// 2.存储
img.renameTo(new File(file, imgFileName));
url = dir + File.separator + imgFileName;
return SUCCESS;
}
public File getImg() {
return img;
}
public void setImg(File img) {
this.img = img;
}
public String getImgFileName() {
return imgFileName;
}
public void setImgFileName(String imgFileName) {
this.imgFileName = imgFileName;
}
public String getImgFileContentType() {
return imgFileContentType;
}
public void setImgFileContentType(String imgFileContentType) {
this.imgFileContentType = imgFileContentType;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
2.1.2、配置文件上传大小
在struts.xml中配置:<constant name="struts.multipart.maxsize" value="10485760"></constant>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开发模式 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 配置文件上传大小 -->
<!-- 10MB -->
<constant name="struts.multipart.maxsize" value="10485760"></constant>
<package name="upload" extends="struts-default" namespace="/">
<action name="*" class="com.csa.action.FileUploadAction" method="{1}">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
2.1.3、限制文件上传类型
这个还不太懂。
2.1.4、限制文件上传拓展名
这个也还不太懂。
2.1.5、编写index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<title>上传页面</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/upload.action" enctype="multipart/form-data">
上传文件:<input type="file" name="img"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
success.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>上传成功</title>
</head>
<body>
<h1>路径:${url}</h1>
</body>
</html>
2.1.6测试结果
2.2、文件上传错误消息配置
这个也不太懂。
2.3、多文件上传
修改两处地方:
- 修改FileUploadAction类。
- 修改index.jsp。
- 修改success.jsp。
- 测试
2.3.1、修改FileUploadAction类
package com.csa.action;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport {
// 创建getter/setter方法,说明存入值栈中!
private List<String> urlList;
// 下面三个字段都是upload.jar提供的,struts要求必须这样写!
// 上传的文件
private File[] img;
// 文件名,固定写法 文件变量名+FileName
private String[] imgFileName;
// 文件类型,固定写法 文件变量名+ContentType
private String[] imgFileContentType;
public String upload() {
// 1.存储路径
String dir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/files");
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();
}
urlList = new ArrayList<>();
// 2.存储
for (int i=0;i<img.length;i++) {
img[i].renameTo(new File(file, imgFileName[i]));
urlList.add(dir + File.separator + imgFileName[i]);
}
return SUCCESS;
}
public List<String> getUrlList() {
return urlList;
}
public void setUrlList(List<String> urlList) {
this.urlList = urlList;
}
public File[] getImg() {
return img;
}
public void setImg(File[] img) {
this.img = img;
}
public String[] getImgFileName() {
return imgFileName;
}
public void setImgFileName(String[] imgFileName) {
this.imgFileName = imgFileName;
}
public String[] getImgFileContentType() {
return imgFileContentType;
}
public void setImgFileContentType(String[] imgFileContentType) {
this.imgFileContentType = imgFileContentType;
}
}
2.3.2、修改index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<title>上传页面</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/upload.action" enctype="multipart/form-data">
上传文件1:<input type="file" name="img"/><br/>
上传文件2:<input type="file" name="img"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
2.3.3、修改success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<title>上传成功</title>
</head>
<body>
<s:iterator value="urlList" var="url">
<h1>路径:${url}</h1>
<!--
${url}与<s:property value="#url"/>是等价的!
-->
</s:iterator>
</body>
</html>
2.3.4、测试
2.4、文件下载
分下面几步:
- 编写DownloadAction类。
- 编写download.jsp。
- 编写struts.xml。
- 测试。
2.4.1、编写DownloadAction类
package com.csa.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownLoadAction extends ActionSupport {
// 文件名
private String fileName;
// 文件路径
private static String dir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/files");;
// 需要一个文件输入流
private InputStream fileInputStream;
public String download() throws Exception {
fileInputStream = new FileInputStream(new File(dir + File.separator + fileName));
return "success";
}
public String downloadPage() {
File file = new File(dir);
String[] listFiles = file.list();
ActionContext.getContext().getValueStack().set("listFiles", listFiles);
return "DLpage";
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public InputStream getFileInputStream() {
return fileInputStream;
}
public void setFileInputStream(InputStream fileInputStream) {
this.fileInputStream = fileInputStream;
}
}
2.4.2、编写download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<title>下载页面</title>
</head>
<body>
<s:iterator value="listFiles" var="file">
<a href='${pageContext.request.contextPath}/download.action?fileName=<s:property value="#file"/>'><s:property value="#file"/></a><br/>
</s:iterator>
</body>
</html>
2.4.3、编写struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开发模式 -->
<constant name="struts.devMode" value="true"></constant>
<package name="download" extends="struts-default" namespace="/">
<action name="*" class="com.csa.action.DownLoadAction" method="{1}">
<!-- 其实action中也可以依赖注入DI -->
<!-- <param name="某个拥有get/set的字段"></param> -->
<!-- 下载其实就是一个流 -->
<result name="success" type="stream">
<!-- 需要一个流对象 -->
<param name="inputName">fileInputStream</param>
<!-- 需要一个下载的文件名 -->
<!-- 这里可以使用特定的表达式,比如$或者OGNL -->
<param name="contentDisposition">attachment;filename=${fileName}</param>
<!-- 需要指定下载的类型 -->
<param name="contentType">application/octet-stream</param>
</result>
<result name="DLpage">/download.jsp</result>
</action>
</package>
</struts>
2.4.4、测试
3、防止表单重复提交
就只有一点(常用,方便):
- 在index.jsp的form表单中添加一个
<s:token/>
。 - 在struts.xml中添加一个
<intercptor-ref name="tokenSession"></intercptor-ref>
即可。
至此,所有的Struts2的基本内容总结完毕。那些国际化七七八八的就算了,现在很多企业都不用Struts2了,还管那些干啥= =!
参考
实验楼Struts2教程
黑马笔记。