基础
介绍
struts1和WebWork的发展
引入值栈的概念 # 一次请求的参数和处理数据放在一个map结构中
原理
基于拦截器, 解耦servlet, 再提供自己的拦截器(interceptor)操作数据, 反射调用业务类
FilterDispatcher通过配置文件来映射设置请求地址与处理类
ActionMapper判断请求是否struts处理
ActionProxy扩展实现方式(如web service)
ConfigurationManager对应struts.xml配置文件
ActionInvocation执行Action与拦截器
Action处理请求,封装数据
过滤器与拦截器
过滤器基于回调,拦截器基于反射
过滤器依赖servlet, 拦截器在struts中处理action
思想
Action类中的无侵入设计(新技术中不出现旧技术):map代替了作用域
ActionContext actionContext = actionContext.getContext()
actionContext.getApplication()
actionContext.getSession()
好处
map是java中的api,不出现旧技术
测试方便( servlet不能测试,只能发布测试)
注意:Action类中用到作用域map的方法也不能测试
结构
apps: 例子程序
docs:帮助文件
lib:程序包
src:源码
使用
要求
导入核心的8个包
struts2-core-2.3.1.1.jar # struts的过滤器
xwork-core-2.3.1.1.jar # 验证工具
freemarker-2.3.18.jar # 标签
javassist-3.11.0.GA.jar # 动态代理
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar # 文件处理
commons-lang-2.5.jar # 基础包
ognl-3.0.3.jar # 表达式语言
web.xml文件中配置过滤器
<filter> - <filter-name>struts</filter-name> - <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>struts</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - 写jsp页面,get或post路径为struts2的名称空间、扩展名,被配置的struts2过滤器处理
写Action类(继承ActionSupport类)
配置src/struts.xml文件与src/struts.properties文件,映射类、方法等到请求路径,映射返回字符串到任何方式
核心包:8个
struts2-core-2.3.1.1.jar # struts的过滤器
xwork-core-2.3.1.1.jar # 验证工具
freemarker-2.3.18.jar # 标签
javassist-3.11.0.GA.jar # 动态代理
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar # 文件处理
commons-lang-2.5.jar # 基础包
ognl-3.0.3.jar # 表达式语言
配置
原理流程
请求/qq.action -> StrutsPreparedAndExecuteFilter(核心过滤器)-> 匹配扩展名 -> 匹配命名空间
#( 全限定名:org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.class)
-> src/struts.xml -> name
class
method
-> name
type
内容
-> 响应
-> 拦截器 -> ConfigAction类
# 1.部署时读取src/struts.xml和src/struts.properties文件,形成JavaBean对象
# 两个文件同时存在时src/struts.properties文件为准
## 2.请求/*路径时,StrutsPreparedAndExecuteFilter过滤
## 3.获取JavaBean中的actionName ,actionClass, actionMethod, 执行方法
## 4.执行的返回值与resultName, resultType, resultContent进行比较
## 5.按resultType类型返回resultContent(路径和内容)
缺点
编码
struts2默认编码方式:utf-8
返回的图片相对路径中有中文时设置tomcat
tomcat/conf/server.xml
<Connector port=“8080” .. URIEncoding=“utf-8”/> - 这时点击下载的请求路径中有中文时在以post方式提交 ,struts自动转码。若以get方式提交,需要在Action类的相应的get方法中转换url编码(iso8859-1)到u8
原理
改了tomcat的内部编码以后,struts中的编码是u8,放在session 中,jsp支持u8,解释后发送的html中的编码没问题,查看没问题。
下载post发送请求,浏览器请求的是url编码的u8,struts中也是u8执行下载
如果不改编码,struts 中是u8,如果以List方式放入session的话,session存储的是u8
如果直接放入数据的话,session中存储的是8859-1,jsp取出数据需要转码为u8并设置自己的编码是u8,再发送给浏览器。
浏览器这时获取图片正常,post方式提交的是u8,经过tomcat转换为8859-1,struts中自动转换编码到u8
如果是以get方式提交请求,get中的中文在浏览器时进行url编码到8859-1,经过tomcat,再到struts,struts不对get方式的请自动进行转码
向action类中注入参数时是8859-1编码,需要手动在action类中的属性的get方法中进行8859-1到u8的转码操作
内置对象
struts中的6个内置对象
request请求进入struts中时创建,request请求结束时销毁。
requestMap
sessionMap
applicationMap
parameters
attr # page → request → session → application 的顺序查找
valueStack # 定义实例变量,直接放入valueStack的 list(栈) 中,map(值)很少向内存储数据
定义的实例变量必须提供相应的get方法,否则ognl标签中取其数据时没有方法调用,就得不到它的值
list 中的值优先访问 ,但是map 中的值起决定作用
map中存放着一个大map,其中注入了所有页面的请求信息
requestMap sessionMap applicationMap 并不是真正的域对象,但最后通过拦截器放入到域对象中
异常处理
配置src/strut.xml 文件
<global-results> 全局结果(用来跳转全局异常等) - <global-exception-mappings> 全局异常 - <exception-mapping result=“nullJsp” exception=“java.lang.NullPointerException” /> - <action>标签中的局部异常 - <action>捕获标签中的实例运行抛出的异常,然后改为 返回执行结果为”nullJsp”的字符串交给本<action>标签中相应的<result>标签来处理 - 处理机制
o→ 多个异常时走子异常,父异常被忽略
o→ 先处理小范围异常,大范围忽略
o→ 如果异常没有处理,抛出到web服务器处理,web.xml的
全局异常
xml文件中
<global-results> - <result name=“error”> - /error.jsp
</result> - </global-results> - <global-exception-mappings> - <exception-mapping result=“error” exception=“java.lang.Exception”/> - </global-exception-mappings> - error.jsp页面中
<%@ taglib prefix=“s” uri=“/struts-tags” %> - 异常信息:<s:property value=“exception.message”/>
详细信息:<s:property value=“exceptionStack”/>
转递方式
chain # action类之间转发
dispatcher # 转发到jsp
freemarker
httpheader
redirect # 重定向到页面
redirectAction # action 类之间重定向
stream # 返回 InputStream流
velocity
xslt
plainText
Action类
注意
1.所有Action类都要继承ActionSupport类,否则execute方法返回的字符串不会回到struts拦截器再根据xml文件的配置进行转发
2.action类是非单例的。 # 所有多实例的对象全部是因为有私有属性,否则全部应该是单例的
3.action类放在栈的顶端,用于注入数据
传统方式得到request,response,servletContext,pageContext
ServletActionContext.getPageContext()
HttpServletRequest request = ServletActionContext.getRequest()
ServletActionContext.getResponse()
ServletActionContext.getServletContext();
优势
验证
验证分类
前台验证:javascript等
后台验证:服务器
struts2验证
后台验证
1.代码式验证
2.声明式验证:xml文件
ActionContext类
调用方法
ActionContext actionContext = ActionContext.getContext();
得到内置对象 # 这几种得到作用域的方法均可以得到作用域中原有的值,也可以放入值
request
actionContext.put("","");
application
Map<String,Object> applicationMap = actionContext.getApplication();
session
Map<String,Object> sessionMap = actionContext.getSession();
或 actionContext.get(“session”)得到,因为actionContext中存储着大map
parameters
Map<String,Object> parametersMap = actionContext.getParameters();
valueStack
ValueStack valueStack = actionContext.getValueStack()
valueStack.getRoot() # 得到当前值栈的顺序
参数
1.action类中可以直接创建属性与其get方法得到客户端get方法或post表单请求的参数(由struts2自动注入)
2.action类中可以创建 JavaBean的属性来接收struts注入的参数,这时用户请求的参数名字要写成JavaBean名.JavaBean中的属性名(这样struts2会自动调用JavaBean的set方法来注入其中相应的参数 )
BaseAction
web.xml配置
<filter> - <filter-name>struts2</filter-name> - <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> - <init-param> - <param-name>struts.action.extension</param-name> - <param-value>do</param-value> - </init-param> - </filter> - <filter-mapping> - <filter-name>struts2</filter-name> - <url-pattern>*.json</url-pattern> - </filter-mapping> - 设置全局过滤器,并且修改过滤扩展名
default.properties
src/struts.properties配置文件
struts.custom.i18n.resources=struts # 使自己的普通配置生效。如:/org/apache/struts2/struts-messages.properties文件的
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} “{1}” “{2}” {3} 属性,“{1}” “{2}” “{3}“是显示消息的占位符
struts.action.extension=action,,可以不配置
由于只加载properties文件,所以省略.properties
=后面的是相对于src目录的文件
OGNL
strut.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
<constant name="" value=""></constant>
<include file=""></include>
<package name="">
<interceptors>
<interceptor name="" class=""></interceptor>
<interceptor-stack name="">
<interceptor-ref name=""></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name=""></default-interceptor-ref>
<global-results>
<result name=""></result>
</global-results>
<global-exception-mappings>
<exception-mapping result="" exception=""/>
</global-exception-mappings>
<action name="">
<param name=""></param>
<result></result>
<result name="input"></result>
<exception-mapping result="" exception=""/>
<interceptor-ref name=""></interceptor-ref>
</action>
</package>
</struts>
设置
<constant name="struts.devMode" value="true"/> # 开启debug模式
# debug模式,不用重启调试(添加新的方法要重启,方法中改代码不用重启)
<constant name="struts.i18n.encoding" value="utf-8"/>
# 配置struts的编码
<constant name="struts.configuration.xml.reload" value="true"/>
# 配置本属性,可以使得改动struts配置文件不用重启应用服务器
<constant name="struts.multipart.saveDir" value="/upload"/>
# 配置上传存储路径
<constant name="struts.action.extension" value="action,do" />
# 配置过滤路径
详细解释
o-> 存放路径src/
o-> 可以在struts-2.3.15.1的src\apps\blank\src\main\resources\struts.xml中参考配置文件
o-> <include file="struts2/cal/cal_struts.xml"/>标签包含其它路径的xml配置文件
# 被include的文件不能再include其它文件
o-> <constant name="struts.action.extension" value="do,,">
默认值
default.properties中配置了默扩展名:struts.action.extension=action,,
# 配置匹配到框架处理的扩展名,空逗号代表匹配没有扩展名
o-> <package name="xxPackage" extends="struts-default" namespace="/xx/">
默认值
namespace="/"
extends="struts-default" # 不可省略
# name是包的唯一标识,不可以写路径
## namespace 访问路径如/xx/a.do会匹配到该包执行其中的映射,按照域命名空间链的方式匹配,如:
/xx/yy/a.do也会匹配到该包,但是它优先匹配到/xx/yy的命名空间
/a.do 不会匹配到该包
注意:匹配/sys/*的名称空间是/sys 而非 /sys/
## struts的包有抽象包,普通包两种,通过继承可以加入包内容,相当于复制、粘贴
## 继承的包是struts-default,其路径是/struts-default.xml
## ,它定义了核心的bean和拦截器
o-> <interceptors>
<interceptor name="" class=""/>
<interceptor-stack name="">
<interceptor-ref name="/">
# 定义拦截器、定义拦截器栈(加入拦截器)
## 拦截器栈中可以加栈
o-> <default-interceptor-ref name=""> 默认拦截器(可以用于验证用户登录)
o-> <global-results> 全局结果(用来跳转全局异常等)
o-> <global-exception-mappings> 全局异常
o-> <action name="" class="" method="">
默认值
class="com.opensymphony.xwork2.ActionSupport"
method="execute"
# name="aa"时 .../aa.do的请求匹配到该方法执行
## class 是类字节码路径,method是其中的方法名
o-> <param name="aaa">bbb</param>
调用 <action>标签中对象的实例的方法:setAaa("bbb");
o-> <result name="" type="">/ok.jsp
默认值
name="success"
type="dispatcher"
# name="success"时,映射的method返回"success"时进入该result处理
## type是返回方式 ,如dispatcher redirect等
type的返回类型
dispatcher : 转发到jsp页面
redirect : 重定向到 jsp html 等页面
chain : Action 类之间的转发
redirectAction : Action 类之间的重定向
stream : 以 inputStream 的数据类型返回
stream的参数 # 可以从struts-default.xml文件中对应的stream参数对应的类的源码中查看其中的set方法找到要写参数的名称
<param name="contentType">image/pjpeg</param> # 下载文件的类型 另外如text/html; charset=utf-8返回给ajax异步数据
<param name="bufferSize">2048</param> # 缓冲byte[]的大小,单位字节
<param name="contentDisposition">attachment;filename=${uuidFileName}</param> # 设置下载响应头,只的下载时才设置。${uuidFileName}是一个OGNL表达式
<param name="inputName">imageStream</param> # 框架调用传递给result标签结果字符串的对象中的getImageStream()方法,来获取InputStream流对象
# 返回stream类型不指定返回的路径
## 标签间的内容:/ok.jsp 是响应的路径
o-> <result name="input" type="">/ok.jsp
type中的参数 # 可以从struts-default.xml配置文件中查到
dispatcher # 转发
redirect # 重定向
chain # Action类之间转发,需要加参数,参数的名字
## :struts-default.xml文件中找到"chain"对应的类,按快捷键ctrl + shift + T 关联类的源码文件,查找set方法改名即可
<param name="actionName">to</param>
# action标签的 name属性值
<param name="namespace">/</param>
# action的名称空间
redirectAction # Action类之间重定向
# 各种拦截器不通过时默认的返回input,同时向request作用域中加入了相关错误信息供struts2的jsp标签进行显示
## 处理 返回值是input的返回信息跳转,就是处理拦截器拦截后的信息跳转
o-> <exception-mapping result="nullJsp" exception="java.lang.NullPointerException" />
# <action>标签中的局部异常
## <action>捕获标签中的实例运行抛出的异常,然后改为 返回执行结果为"nullJsp"的字符串交给本<action>标签中相应的<result>标签来处理
o-> <interceptor-ref name="loginInterceptor"/>
默认值
name="defaultStack"
# 指定在本<action>标签中使用的拦截器或拦截器栈
## 当指定了拦截器或拦截器栈以后,默认的defaultStack将会没有,此时defaultStack中的18个拦截器将不再执行
使用:OGNL对象图导航语言对标签中的路径进行动态设置
验证
struts2验证
1.代码式: validate(),validateXxx()方法
单个验证与全部验证都存在时先单个验证,再全部验证,验证信息都加入验证信息集合
2.声明式: Action类名-validation.xml
Action类名-<action标签的name属性>-validation.xml
单个验证与全部验证都存在时先全部验证,再单个验证,验证信息都加入验证信息集合
先声明验证,后代码验证
参数驱动
1.属性驱动: action中用属性收集表单参数
2.模型驱动: javaBean收集参数
代码式(属性驱动):
步骤
1.需要验证的Action类 继承 ActionSupport 类
ActionSupport 类 实现了Validateable接口,该接口是验证接口
2.写验证方法
1> public void validate()
方法重写(通用验证方法,本类中的所有其它方法执行前都执行)
2> public void validateXxxMethod()
或者自定义专用验证方法 xxxMethod为要验证的方法名,首字母要大写
注意,通用、专用验证方法同时存在时,先执行专用验证方法,再执行通用验证方法,但是通用验证方法的错误消息无法加入到返回的错误集合中
3> this.addFieldError(“password”,“密码必填”);
验证方法中添加错误信息到错误信息集合
addFieldError("","")是从ActionSupport父类中继承的方法
3.jsp文件中通过验证标签:
<%@ taglib uri=“/struts-tags” prefix=“s”%> - <s:fielderror/> # 显示所有错误信息 - <s:fielderror fieldName=“password”/> - 显示验证出错信息
4.xml配置
<!— 验证错误信息处理 ⇒ - <result name=“input” type=“dispatcher”> - /error.jsp
</result> - 写在需要验证的方法对应的标签中,验证错误时验证方法会优先返回”input”字符串
声明式(属性驱动):
1.验证Action类继承ActionSupport
2.验证Action类目录下配置文件
Action类名-validation.xml
Action类名-<action标签的name属性>-validation.xml
放入此名字的配置文件就相当于加了验证,不需要做其它事情,相当于分别向Actioin类中加入了validate()validateXxx()方法进行了相应验证
文件内容
<?xml version=“1.0” encoding=“UTF-8”?> - <!DOCTYPE validators PUBLIC - ”-//Apache Struts//XWork Validator 1.0.3//EN”
“http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd”>
<validators> - <field name=“username”> # 要验证的属性 - <field-validator type=“requiredstring”> - <message>用户名必填</message> - </field-validator> - </field> - <field-validator type=“regex”> - <param name=“expression”>^[\u3447-\uFA29]+$</param> - <message>UserAction2-validation⇒ 必须写中文</message> - </field-validator> - </validators> - xml文件的头在 xwork-core-2.3.1.1.jar包的
- xwork-validator-1.0.3.dtd中复制
关联约束在
\struts-2.3.15.1\src\xwork-core\src\main\resources\xwork-validator-1.0.3.dtd文件
<field-validator type="">的约束类型在xwork-core-2.3.1.1.jar包的 - /com/opensymphony/xwork2/validator/validators/default.xml文件中
- 16个规则
- type=“regex”相当于调用了default.xml文件中配置的
- RegexFieldValidator类的 setExpression方法
3.jsp文件中通过验证标签(同上)
4.xml配置(同上)
出错信息
1.验证文件名写错,无提示,不验证
2.写错,有明显提示
2.写错,获取的salaryy为空。
声明式(模型驱动)
1.创建bean对象,bean对象中封装属性
2.验证Action类继承ActionSupport类,声明bean对象实例
3.action类同目录 中 :Action类名-<action标签的name属性>-validation.xml
<field-validator type=“visitor”> - bean类同目录中:bean类名-validation.xml配置验证文件
4.jsp文件请求参数改为:action类中bean对象名.bean对象封装的属性名。用<s:fielderror/>标签得到返回的错误信息
5.xml配置(同上)
原理
StrutsPreparedAndExecuteFilter
1.注入参数
setUsername()
setPassword()
2.验证方法:validate()或validateXxx()
验证配置文件中验证:Action类名-validation.xml
3.转发:根据验证成功或失败返回消息
验证集合无错误消息成功Action ⇒ execute或同签名的方法
验证集合有错误消息失败<result name = “input” type=“dispatcher”
过滤器
StrutsPrepareAndExecuteFilter
中查看Dispathcer类,从中找到配置struts-default.xml,struts-plugin.xml,struts.xml值的属性DEFAULT_CONFIGURATION_PATHS
查找引用该属性的方法为init_TraditionalXmlConfigurations
查看引用该方法的方法为init
回头看StrutsPrepareAndExecuteFilter中初始化dispatcher对象的方法initDispatcher
其中调用了dispatcher.init();方法来配置dispatcher
由此可以知道struts在启动时加载了struts-default.xml,struts-plugin.xml,struts.xml配置文件
拦截器
struts-core-2.3.1.1.jar包中的
struts-default.xml文件中
定义了32个interceptor(拦截器)
token # 表单重复提交
validation # 验证
params # 参数拦截器,向Action类中注入参数
cookie
interceptor-tack # 拦截栈
拦截栈中的拦截器的先后顺序有影响
basicStack
defaultStack # 每个http请求都会经过该拦截栈
原理
执行流程
拦截器构构造函数 → action构造函数 → 拦截器1 in → 拦截器2 in → demo → 拦截器2 out → 拦截器1 out
exception拦截器最先进,最后出
自定义拦截器
1.定义Action类,继承Interceptor接口,重写生命周期方法
public LoginInterceptor() {
}
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) {
}
2.配置struts.xml文件
1> 定义拦截器、拦截器栈
<interceptors> - <interceptor name=“loginInterceptor” class=“interceptor.LoginInterceptor”/> - <interceptor name=“roleInterceptor” class=“interceptor.RoleInterceptor”/> - <interceptor-stack name=“crmStack”> - <interceptor-ref name=“loginInterceptor”></interceptor-ref> - <interceptor-ref name=“roleInterceptor”></interceptor-ref> - </interceptor-stack> - </interceptors> - 2> 标签中声明用到的拦截器或拦截器栈
<interceptor-ref name=“loginInterceptor” /> # 此时默认的defaultStack拦截器栈会被替代掉 - 自定义方法过滤拦截器
MethodFilterInterceptor继承AbstractInterceptor继承Interceptor,前两个是struts自己实现的自己的包装类
原理:自己实现intercept方法,实现对方法名的过滤。如果符合通过条件,则执行自己的doIntercept方法。所以要求用户重写doIntercept方法实现业务逻辑
<interceptor name=“aloginInterceptor” class=“cn.it.shop.interceptor.AloginInterceptor”> - <param name=“excludeMethods”>$</param> # 除了 $匹配的方法都执行此拦截器 - includeMethods为包含匹配的方法执行拦截器
</interceptor> - 生命周期
部署时初始化,每次符合的请求时,执行拦截器
拦截器Action 类
o→ 继承Interceptor 接口
o→ 重写生命周期方法
String intercept(ActionInvocation invocation)方法中调用
invocation.invoke() 放行
invocation.getAction()得到当前的Action类
invocation.getStack()得到值栈中的栈
具体拦截器
struts-default.xml 文件中定义了32种拦截器
autowiring
chain
conversionError
cookie
clearSession
createSession
debugging
execAndWait
exception
fileUpload # 只用来验证已经注入的文件是否合格,合格则通过,不合格则不执行action类中对应请求的方法
i18n
logger
modelDriven # 用于检查action类是否实现ModelDriven接口,然后调用getModel()方法注入得到的对象到栈的项端。
scopedModelDriven
params # 注入参数用,包括注入文件(级联注入文件的ContentType与FileName)
actionMappingParams
prepare
staticParams
scope
servletConfig # 向自定义的实现RequestAware等接口的Action类(一般是BaseAction类)中注入request等相应的map对象
timer
token # 防止重复提交
tokenSession
validation # 验证
workflow
store
checkbox
profiling
roles
annotationWorkflow
multiselect
数据传递
o→ 拦截器不会向其它拦截器中注入参数,所以自定义拦截器中了参数要从request中获取
o→ 如果想 显式的引用了自己的拦截栈,默认的拦截栈就不引用了,要自己引用,其中的注入参数拦截器向action类中注入参数
技巧
<interceptor-stack name=“defaultStack”> # 对defaultStack进行替换,在它前面添加自定义的拦截器 - <interceptor-ref name=“aloginInterceptor”/> - <interceptor-ref name=“defaultStack”/> - 拦截器中的ActionInvocation对象
可以得到ActionContext
文件处理
上传
struts2文件上传步骤
1.编写jsp文件
2.创建Action类,不必继承任何类(但是如果不继承ActionSupport类的话,拦截器将不会返回提示消息)
1> 定义参数 # 如果不接收上传文件名字符串数组而从文件对象中获取文件名的话,得到的文件名将会是乱码
private File[] image; # 字段名
private String[] imageContentType; # 文件类型
private String[] imageFileName; # 文件名
private String uploadPath;
前三个参数可以不是数组,在 struts-default.xml配置文件fileUpload拦截器对应的源码中可以找到定义规则:
<li>[File Name] : File - the actual File</li> - <p/> <li>[FileName]ContentType : String - the content type of the file</li> - <p/><li>[File Name]FileName : String - the actual name of the file uploaded(not the HTML name)</li> - uploadPath是我们自定义的配置文件中注入过来的文件存储位置
2> 写execute方法保存文件到路径,返回成功消息
3.Action类的配置文件,include到src/struts.xml文件中
1> 标签中配置name=“input”的标签来返回出错消息
2> 标签中用param标签注入文件存储路径:uploadPath 底层执行setUploadPath()方法
3> 标签中通过标签对上传文件进行参数上的限定
1> 单个文件的最大尺寸(字节)
2> 文件扩展名
3> 文件实际类型,如image/jpeg,可从tomcat配置文件web.xml中查找
4.配置返回消息的信息
:src/struts.properties文件中
struts.custom.i18n.resources=struts # 解锁自/org/apache/struts2/default.properties总配置文件
加载自己,=后面是参照src/目录的相对路径 ,省略掉.properties扩展名
struts.multipart.maxSize=2097152 # 解锁自/org/apache/struts2/default.properties总配置文件
struts.messages.error.file.too.large=\u6587\u4EF6\u592A\u5927: {0} “{1}” “{2}” {3}
struts.messages.error.content.type.not.allowed=\u6587\u4EF6\u7C7B\u578B\u4E0D\u6B63\u786E: {0} “{1}” “{2}” {3}
struts.messages.error.file.extension.not.allowed=\u6269\u5C55\u540D\u4E0D\u6B63\u786E: {0} “{1}” “{2}” {3}
覆盖/org/apache/struts2/default.properties总配置文件的响应消息,=后面是中文的unicode编码的iso8859-1的表示形式,通过视图可以直接配置,也可以用java/bin目录下的native2ascii.exe工具进行转码
多文件上传
出现有多个文件共同上传时,文件拦截器会出现一错全错的情况,这时我们利用struts的一个
小bug---文件拦截不成功也调用action类的setXxx方法传入文件,从set函数中对文件进行筛选和转存
这时文件拦截器已经形同虚设,一点作用也不起了。
原理过程
1.上传请求经过struts2的过滤器匹配扩展名
2.按src/struts.xml文件中声明的配置包映射的名称空间映射到配置包
3.根据action标签的name属性匹配名称空间与扩展名之间的“文件名”,映射到该action标签
1> 经过多层拦截器
2> 用param标签注入文件存储路径
3> 通过标签对上传文件进行参数上的限定
2> 执行action标签对应类的方法,该方法返回的返回的字符串进行响应
默认配置
1.defaultStack拦截栈中的fileUpload拦截器进行处理
2.default.properties配置文件中 对multipart的上传方式进行了配置
struts.multipart.parser=jakarta # struts使用了第三方的jakerta来给上传文件解码
struts.multipart.saveDir= # 缓存文件的临时目录,不填默认是
work/catalina/localhost/web工程名/upload_…00000..tmp
struts.multipart.maxSize=2097152 # 默认支持的上传文件的大小 (字节,2m),是总大小
3.多数服务器自己删除缓存文件
下载
用传递类型为stream 来返回要下载的文件
写法
<result name=“success” type=“stream”> - <!— 下载文件的类型 ⇒ - <param name=“contentType”>image/pjpeg</param> - <!— byte[]的大小,单位字节 ⇒ - <param name=“bufferSize”>2048</param> - <!— 设置下载响应头,${uuidFileName}是一个OGNL表达式,不是EL表达式 ⇒ - <param name=“contentDisposition”>attachment;filename=${uuidFileName}</param> - <!— 框架调用getXxx()方法,来获取InputStream流对象 ⇒ - <param name=“inputName”>imageStream</param> - </result> - 与其它同样,要注入的参数从stream类型对应的类中可以进行查看
显示与下载的编码问题
o→ 设置tomcat/conf/server.xml
<Connector port=“8080” .. URIEncoding=“utf-8”/> - o→ 提交下载请求用post方式,struts框架自动给post请求编码解码