Struts2的文件上传
回顾文件的上传
原理:服务端需要接收文件类型、文件名、文件大小
- 客户端
<form>设置enctype编码类型(MIME类型)multipart/form-data
<form>设置method提交方式post
<input type="file">元素,必须提供name属性
- 服务器端
Apache commons-fileupload组件
jsp-smartupload组件
Servlet3.0以后API内置文件上传API
COS文件上传组件
Struts2 的文件上传机制
struts2内部文件上传,默认采用apache commons-fileupload
struts2默认导入文件上传的jar包
defaultStack默认拦截器栈,提供fileUpload的拦截器,用于实现文件上传
<interceptor-ref name="fileUpload"></interceptor-ref>
Struts2的文件上传的实现
【提示】上传的表单一定要添加enctype="multipart/form-data"这个值
编写upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>登录页面</h3>
<!-- <s:fielderror />用于显示错误信息的struts2标签 -->
<s:fielderror />
<form
action="${pageContext.request.contextPath}/interceptor/user_login.action"
method="post">
用户名:<input type="text" name="username"><br> 密码:<input
type="password" name="pwd"><br> <input type="submit"
value="提交">
</form>
</body>
</html>
编写UploadAction.java
package struts2_03.upload;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction extends ActionSupport{
//需要三个参数
//upload于jsp中input的name属性一致
private File upload;
private String uploadContentType;//upload+ContentType
private String uploadFileName;//upload+FileName
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
@Override
public String execute() throws Exception {
//一句话搞定文件上传
FileUtils.copyFile(upload, new File("/Users/chenjiafeng/eclipse-workspace/struts2_03/"+uploadFileName));
return SUCCESS;
}
}
配置struts.xml
<!-- 配置上传action -->
<action name="upload" class="struts_02.UploadAction">
<result>/upload.jsp</result>
</action>
测试结果(把桌面上的text.txt上传到项目struts2_03里
点击提交,刷新项目
文件上传的参数设置
默认只能上传2m
在struts2文件上传,存在一些限制参数,当违背参数,跳转input视图
- FileUpload拦截器负责处理文件的上传操作,它是默认的defaultStack拦截器栈的一员
- FileUpload拦截器有三个属性可以设置
maximumSize:上传文件的最大长度(以字节为单位),默认值为2MB
allowedTypes:允许上传文件的类型,各类型之间以逗号分隔
allowedExtensions:允许上传的文件扩展名,各扩展名之间以逗号分隔
可以在struts.xml文件中覆盖这3个属性
- 若用户上传的文件大小大于给定的最大长度或其内容类型没有被列在allowedTypes,allowedExtension参数里,将会显示一条出错消息,与文件上传有关的出错消息在struts-messages.properties文件里预定义。(org.apache.struts2包下)
- 可以在文件上传Action相对应的资源文件中重新定义错误消息,但需要在struts.xml文件中配置使用action的消息
【示例】通过在action配置拦截器栈中的fileIpload拦截器的参数,注意:该配置只影响当前的action的文件上传
更改struts.xml
<!-- 配置上传action -->
<action name="upload" class="struts_02.UploadAction">
<result name="input">/upload.jsp</result>
<!-- 设置拦截器参数 -->
<interceptor-ref name="defaultStack">
<!-- 设置允许上传的文件扩展名 -->
<param name="fileUpload.allowedExtensions">.txt</param>
</interceptor-ref>
</action>
测试结果
如果让错误信息显示成中文(国际化问题)
在/org/apache/struts2/struts-messages.properties配置里
覆盖默认的国际化提示信息
在src下新建文件夹messages.properties
把struts-messages.properties中的struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
更在为struts-messages.properties中的struts.messages.error.file.extension.not.allowed=请上传正确的文件类型: {0} "{1}" "{2}" {3}
注意:显示出来如下
struts.messages.error.file.extension.not.allowed=\u8BF7\u4E0A\u4F20\u6B63\u786E\u7684\u6587\u4EF6\u7C7B\u578B: {0} "{1}" "{2}" {3}
配置struts.xml
<!-- 配置读取国际化信息常量,放在包外 -->
<constant name="struts.custom.i18n.resources" value="messages"></constant>
再重新上传
在文件上传的过程中,会出现大小问题,这里我们进行大小设定struts有两个地方来限制文件上传大小的
- 核心配置文件中的常量(最常用最有效的方式)
<!-- 通过配置常量来限制上传文件的大小 -->
<constant name="struts.multipart.maxSize" value="10000000"></constant>
- 在action中配置:(第二种方式的大小其实受第一种方式限制)
<!-- 配置上传action -->
<action name="upload" class="struts_02.UploadAction">
<result name="input">/upload.jsp</result>
<!-- 设置拦截器参数 -->
<interceptor-ref name="defaultStack">
<!-- 设置允许上传的文件扩展名 -->
<param name="fileUpload.allowedExtensions">.txt</param>
<!-- 限制上传文件大小 -->
<param name="fileUpload.maximumSize">10000000</param>
</interceptor-ref>
</action>
两种访问的区别:
struts.multipart.maxSize和fileUpload.maximumSize属性分工不同
- struts.multipart.maxSize控制整个项目所上传文件的最大size。超过这个值后台报错。
- fileUpload.maximumSize属性必须小于struts.multipart.maxSize的值
- 当上传的文件在struts.multipart.maxSize和fileUpload.maximumSize之间时系统会有提示
- 当上传文件小于fileUpload.maximumSize时,上传成功
总结:所上传文件大小应<fileUpload.maximumSize<struts.multipart.maxSize
OGNL表达式
OGNL表达式是什么?
OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,是一个使用简单、功能强大的,开源的表达式语言,可以方便的操作任何的属性对象、方法等。
Struts2框架使用OGNL作为默认的表达式语言,主要用于页面的取值。它类似于EL表达式语言,但比EL语法强大很多。
EL(Expression Language)表达式语言,主要用来获取jsp页面四个域范围数据(page、request、session、application)
ONGL=EL+对象操作 ${name.toUpperCase()}
ONG表达式的三个要素
- 表达式--ONGL的表达式,编写表达式,ONGL负责解析表达式,从而存值和取值、
- Root对象--跟对象
- Context对象--ONGL的上下文对象,运行的环境
新建测试类增加方法
//访问对象的方法
@Test
public void testOGNL1() throws OgnlException {
//创建OGNLCOntext对象
OgnlContext context=new OgnlContext();
//获取对象的方法
Object object=Ognl.getValue("'helloword'.length()", context,context.getRoot());
System.out.println(object);
}
//获取ONGL上下文的对象。map集合
@Test
public void testOGNL2() throws OgnlException {
OgnlContext context=new OgnlContext();
context.put("name", "张艺兴");
//获取对象的方法
//使用#key方式录取
Object object=Ognl.getValue("#name",context,context.getRoot());
System.out.println(object);
}
新建Customer.java
public class Customer {
private String cust_name;
private int age;
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
在测试类中增加方法
//从root栈获值
@Test
public void testOGNL3() throws OgnlException {
OgnlContext context=new OgnlContext();
Customer customer=new Customer();
customer.setCust_name("王一博");
customer.setAge(22);
//把客户放入root栈
context.setRoot(customer);
//如果取root栈中的值,不需要加#
Object name=Ognl.getValue("cust_name",context,context.getRoot());
Object age=Ognl.getValue("age",context,context.getRoot());
System.out.println(name+"--"+age);
}
OGNL的用法详解
1.java对象的直接访问
<s:property value="'feng'"/>
2.实例方法调用访问对象的方法
语法:object.doSomething(),object是对象实例
<s:property value="'feng'.toUpperCase()"/>
3.静态方法调用(类的静态方法或静态变量的访问)
语法:@[类全名[包括包路径]]@[方法名|值名]
<s:property value="@java.lang.Math@Max(10,21)"/>
类的静态方法或静态变量的访问。
格式:@[类全名[包括包路径]]@[方法名|值名],如:@java.lang.Math@max[10,20]、@com.feng.MyConstant@APP_NAME
注意:必须通过配置struts2点常量来开启静态方法调用功能:
struts.ognl.allowStaticMethodAccess=true
4.赋值操作或表达式串联。--可以运算
<s:property value="1+2"/>
OGNL可以访问上下文(OGNL Context)和ActionContext。(值栈相关访问--重要)
创建ognl.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>访问Java对象</h3>
<s:property value="'feng'"/>
<h3>操作对象的属性</h3>
<s:property value="'feng'.toUpperCase()"/>
<h3>静态方法的访问,需要配置struts.xml</h3>
<h3>语法规则:@包名+类名@方法名(参数)</h3>
<s:property value="@java.lang.Math@max(10,21)"/>
<h3>类似EL表达式,进行数值运算</h3>
<s:property value="1+2"/>
</body>
</html>
配置struts.xml
<!-- 开启静态访问常量 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
测试结果