这次我们主要讲Struts2的拦截器;过滤器;上传;下载;Ognl表达式;值栈等. 其中这些都是比较重要的,希望大家认真学习,好好了解。
Struts2的应用总结(四)
一、Struts2的拦截器
原理
* 拦截器就是AOP(Aspect-Oriented Programming)的一种实现。
* 过滤器:过滤从客服端发送到服务器端请求的.
* 拦截器:拦截对目标Action中的某些方法进行拦截.
* 拦截器不能拦截JSP.
* 拦截到Action中某些方法.
拦截器和过滤器的区别
1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
2)过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器
3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
4)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
* 拦截器 采用 责任链 模式
> 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
> 责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行
* 在struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 )
Struts2的自定义拦截器
编写拦截器
需要实现Interceptor接口,实现接口中的三个方法。
* interceptor接口有很多的实现类,编写最简单的方式就是继承AbstractInterceptor实现类。
* 代码例如:
public String intercept(ActionInvocation invocation) throws Exception {
User user = (User) ServletActionContext.getRequest().getSession().getAttribute("existUser");
if(user == null){
ActionSupport as = (ActionSupport) invocation.getAction();
as.addActionError("您没有登陆!");
return as.LOGIN;
}else{
// 放行
return invocation.invoke();
}
}
需要在struts.xml中进行拦截器的配置
配置一共有两种方式
第一种方式
在<package>包中定义拦截器,出现在<package>包的上方
<interceptors><interceptor name="loginInterceptor" class="cn.zlq.interceptor.LoginInterceptor"></interceptor>
</interceptors>
在某个action中引入拦截器
<interceptor-ref name="loginInterceptor"></interceptor-ref>
第二种方式
在<package>包中定义拦截器的时候,自己直接定义一个拦截器栈
<interceptors>
<interceptor name="loginInterceptor" class="cn.zlq.interceptor.LoginInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
在Action包中引入自己定义的拦截器栈
<action name="book_*" class="cn.zlq.action.BookAction" method="{1}">
<interceptor-ref name="myStack"/>
</action>
二、Struts2的文件上传
Struts2框架的使用拦截器完成了文件上传
底层使用也是FileUpload开源的组件。
* 提供FileUpload拦截器,用于解析multipart/form-data编码格式请求,解析上传文件的内容
* fileUpload拦截器 默认在 defaultStack 栈中, 默认会执行的
* 在Action中编写文件上传,需要定义三个属性
文件类型File ,属性名与表单中file的name属性名一致.
字符串类型String , 属性名:前段是name属性名一致 +ContentType;
字符串类型String , 属性名:前段是name属性名一致+FileName;
最后需要为上述的三个属性提供set方法。
可以通过FileUtils提供 copyFile 进行文件复制,将上传文件 保存到服务器端
文件上传中存在的问题
* 先配置input逻辑视图
* 在页面中显示错误信息
* 文件上传的总大小默认值是2M,如果超过了2M,程序会报出异常。可以使用<s:actionError>来查看具体信息!
> 解决总大小的设置,找到常量
* struts.multipart.parser=jakarta -- 默认文件上传解析器,就是FileUpload组件
* struts.multipart.saveDir= -- 文件上传的临时文件存储目录
* struts.multipart.maxSize=2097152 -- 文件上传的最大值(总大小),默认是2M
> 可以在struts.xml中设置常量,修改文件上传的默认总大小!!!
<constant name="struts.multipart.maxSize" value="5000000"></constant>
通过拦截器来设置文件上传的一些属性
先在<action>标签中引入文件上传的拦截器
<interceptor-ref name="defaultStack"><!-- 设置单个上传文件的大小 -->
<param name="fileUpload.maximumSize">2097152</param>
<!-- 设置扩展名 -->
<param name="fileUpload.allowedExtensions">.txt</param>
</interceptor-ref>
多文件上传
* 在Action中还是编写三个属性
> 属性需要是数组或者List集合,这样就可以完成多文件上传了。
> 注意:是数组或者List集合
private File [] upload; // 代表上传的文件
private String [] uploadContentType; // 代表文件的类型
private String [] uploadFileName; // 上传文件的名称
提供属性的set方法
三、Struts2的文件下载
Action类必须要有返回结果,并且返回结果中必须要依赖stream结果类型。
* 在<action>标签中配置stream的结果类型。
* 可以通过<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>源码发现有一些需要设置的属性。
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${downFileName}</param>
<param name="inputName"></param>
</result>
上面的代码的${contentType}这种写法需要Action类提供对应的方法,对应的方法如下
// 获取文件的MIME类型
public String getContentType(){
return ServletActionContext.getServletContext().getMimeType(filename);
}
// 设置文件的输入流
public InputStream getInputStream(){
return ServletActionContext.getServletContext().getResourceAsStream("/download/"+filename);
}
// 设置Content-Disposition属性
public String getDownFilename() throws IOException{
String agent = ServletActionContext.getRequest().getHeader("User-Agent");
return this.encodeDownloadFilename(filename, agent);
}
解决下载文件中文乱码的问题
public String encodeDownloadFilename(String filename, String agent) throws IOException{
if(agent.contains("Firefox")){ // 火狐浏览器
filename = "=?UTF-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8"))+"?=";
}else{ // IE及其他浏览器
filename = URLEncoder.encode(filename,"utf-8");
}
return filename;
}
下一章节:Struts2的知识整理总结 (五)——值栈与OGNL表达式
上一章节:Struts2的知识整理总结(三)—— 数据封装和类型转换