struts2(六)拦截器机制
来源:互联网 发布:大智慧软件好用吗 编辑:程序博客网 时间:2024/06/10 04:37
拦截器简述
拦截器是一组动态拦截Action调用的对象。拦截器的处理代码可以定义在action执行前或者执行后。同时,拦截器能够拦截一个Action的执行。拦截器可以将一些通用功能封装成可重用形式以供一个Action或多个 Actions使用。
拦截器必须是无状态的,原因是Struts 2不能保证为每一个请求或者Action创建一个实例,所以如果拦截器带有状态,会引发并发问题。不要使用在API提供的ActionInvocation之外的任何东西。
在概念上,interceptors相近于Servlet 的filters或者JDKs的Proxy类。可以把struts2理解成一个空容器,而大量的内建拦截器完成该框架的大部分操作。比如,params拦截器负责解析HTTP请求的参数,并设置Action的属性;servlet-config拦截器直接将HTTP请求中的HttpServletRequest实例和HttpServletResponse实例传给Action;fileUpload拦截器负责解析请求参数中的文件域,并将一个文件域设置为Action的三个属性等等。这些通用操作是通过struts2的内建拦截器完成的。
struts2拦截器是可插拔式的,如果需要使用某个拦截器,只需要在配置文件中应用该拦截器即可,如果不使用该拦截器只需要在配置文件中取消该拦截器,不用重新部署应用。
struts2拦截器由struts-default.xml、struts.xml等配置文件进行管理,开发者可以很容易地扩展自己的拦截器。
如前面所说开发中存在一些通用逻辑,如解析请求参数、类型转换、将请求参数封装成DTO(Data Transfer Object)、执行输入校验、解析文件上传表单中的文件域、防止表单的多次提交等。struts2把大部分核心控制器需要完成的工作功能分开定义,每个拦截器完成一个功能。这些拦截器可以自由选择,灵活组合(甚至不用struts2的任何拦截器),需要哪些拦截器只需在struts.xml文件中指定使用该拦截器即可。
在struts.xml文件中配置Action时,在package里继承struts-default包,包内的大量通用功能的拦截器就会起作用。
<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> </interceptors> <action name="login" class="tutorial.Login"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <result name="input">login.jsp</result> <result name="success" type="redirectAction">/secure/home</result> </action></package>
在web.xml文件中定义核心Filter。
<!-- 定义struts2核心Filter --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <!-- 让struts2的核心Filter拦截所有action请求 --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping>
当StrutsPrepareAndExecuteFilter拦截到用户请求后,大量拦截器将会对用户请求进行处理,然后才会调用用户开发的Action实例的方法处理请求。拦截器与Action之间的关系如下图所示。
struts2内建的拦截器
struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一表示;class指定了该拦截器的实现类,程序定义的package继承了struts2的默认struts-default包,就可以使用包内定义的拦截器,不用自己定义拦截器。
自定义拦截器
内建拦截器实现了struts2大部分功能,大部分Web应用的通用功能,都可以通过直接使用这些内建拦截器完成,但有一些系统逻辑相关的通用相关功能,要通过自定义拦截器来实现。
Interceptor接口
开发自定义拦截器类,要实现com.opensymphony.xwork2.interceptor.Interceptor接口,该接口的定义代码如下。
public interface Interceptor extends Serializable { //销毁该拦截器之前的回调方法 void destroy(); //初始化该拦截器的回调方法 void init(); //拦截器实现拦截的逻辑方法 String intercept(ActionInvocation invocation) throws Exception;}
init()方法在该拦截器被实例化之后,执行拦截之前被回调。每个拦截器的init()方法只执行一次。所以该方法体主要用于初始化资源,例如数据库连接等。
destroy()对应于init()方法,在拦截器实例被销毁之前,系统将回调该拦截器的destroy方法,用于销毁在init()方法里打开的资源。
inercept(ActionInvocation invocation)方法是用户需要实现的拦截动作,像Action的execute方法,intercept方法返回一个字符串作为逻辑视图。如果该方法直接返回一个字符串,系统会跳转到该逻辑视图对应的实际 视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action引用,可以通过调用该参数的invoke方法,将控制权转给下一个拦截器,或者转给Action的execute方法。
AbstractInterceptor类
AbstractInterceptor类实现了Interceptor接口。
AbstractInterceptor类提供了init()和destory()方法的空实现,如果实现的拦截器不需要打开资源则可以无需实现这两个方法。
定义和使用拦截器
自定义一个拦截器需要三步:
1. 自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
2. 在strutx.xml中注册上一步中定义的拦截器。
3. 在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
自定义拦截器
import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;import java.util.*;import com.afy.app.action.*;public class SimpleInterceptor extends AbstractInterceptor{ // 简单拦截器的名字 private String name; // 为该简单拦截器设置名字的setter方法 public void setName(String name){ this.name = name; } public String intercept(ActionInvocation invocation) throws Exception{ // 取得被拦截的Action实例 LoginAction action = (LoginAction)invocation.getAction(); // 打印执行开始的时间 System.out.println(name + " 拦截器的动作---------" + "开始执行登录Action的时间为:" + new Date()); // 取得开始执行Action的时间 long start = System.currentTimeMillis(); // 执行该拦截器的后一个拦截器 // 如果该拦截器后没有其他拦截器,则直接执行Action的被拦截方法 String result = invocation.invoke(); // 打印执行结束的时间 System.out.println(name + " 拦截器的动作-------" + "执行完登录Action的时间为:" + new Date()); long end = System.currentTimeMillis(); System.out.println(name + " 拦截器的动作---------" + "执行完该Action的时间为" + (end - start) + "毫秒"); return result; }}
在strutx.xml中注册上一步中定义的拦截器,在需要使用的Action中引用上述定义的拦截器。
<?xml version="1.0" encoding="GBK"?><!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.i18n.encoding" value="GBK"/> <!-- 配置本系统所使用的包 --> <package name="lee" extends="struts-default"> <!-- 应用所需使用的拦截器都在该元素下配置 --> <interceptors> <!-- 配置mySimple拦截器 --> <interceptor name="mySimple" class="org.crazyit.app.interceptor.SimpleInterceptor"> <!-- 为拦截器指定参数值 --> <param name="name">简单拦截器</param> </interceptor> </interceptors> <action name="login" class="org.crazyit.app.action.LoginAction"> <result name="error">/WEB-INF/content/error.jsp</result> <result>/WEB-INF/content/welcome.jsp</result> <!-- 配置系统的默认拦截器 --> <interceptor-ref name="defaultStack"/> <!-- 应用自定义的mySimple拦截器 --> <interceptor-ref name="mySimple"> <param name="name">改名后的拦截器</param> </interceptor-ref> </action> <action name="*"> <result>/WEB-INF/content/{1}.jsp</result> </action> </package></struts>
拦截器的实现原理
大部分时候,拦截器方法都是通过代理的方式来调用的。Struts 2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。
我们之所以能够如此灵活地使用拦截器,完全归功于“动态代理”的使用。动态代理是代理对象根据客户的需求做出不同的处理。对于客户来说,只要知道一个代理对象就行了。那Struts2中,拦截器是如何通过动态代理被调用的呢?当Action请求到来的时候,会由系统的代理生成一个Action的代理对象,由这个代理对象调用Action的execute()或指定的方法,并在struts.xml中查找与该Action对应的拦截器。如果有对应的拦截器,就在Action的方法执行前(后)调用这些拦截器;如果没有对应的拦截器则执行Action的方法。其中系统对于拦截器的调用,是通过ActionInvocation来实现的。
与过滤器的区别
过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。
1. 拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2. 过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3. 拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。
4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
5. 在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。
- struts2(六)拦截器机制
- struts2拦截器(六)
- (六)struts2之拦截器
- SSH学习(六)Struts2拦截器
- Struts2 拦截器机制
- Struts2的拦截器机制
- Struts2的拦截器机制
- Struts2的拦截器机制
- Struts2的拦截器机制
- Struts2的拦截器机制
- 详解Struts2拦截器机制
- 详解Struts2拦截器机制
- Struts2的拦截器、自定义拦截器、Struts2 验证机制
- struts2 18拦截器详解(六) --- PrepareInterceptor
- Struts2学习之拦截器机制
- Struts2拦截器实现异常处理机制
- Struts2拦截器实现异常处理机制
- Struts2拦截器实现异常处理机制
- Spark定制班第2课:通过案例对Spark Streaming透彻理解三板斧之二:解密Spark Streaming运行机制和架构
- uva129
- 学习 ef 6 的碰到的一些问题
- failed to create process
- PAT (Advanced Level) L1-6. 连续因子 for循环暴力
- struts2(六)拦截器机制
- POJ2352 Stars 树状数组 + 裸
- 00 Java入门摘要
- jQuery操作属性的相关方法
- 区间重叠的判断
- MyBatis 项目学习
- 01 Java语法
- uva1471 Defense Lines
- hive如何生成rowid