Struts2拦截器Interceptor的原理与配置实例详解
|
一、Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的 拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。 比如:应用要求用户登陆,且必须为指定用户名才可以查看系统中某个视图资源;否则,系统直接转入登陆页面。对于上面的需求,可以在每个Action的执行实际处理逻辑之前,先执行权限检查逻辑,但这种做法不利于代码复用。因为大部分Action里的权限检查代码都大同小异,故将这些权限检查的逻辑放在拦截器中进行将会更加优雅。 PS: 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。 二、Struts2 拦截器接口实现: Struts2规定用户自定义拦截器必须实现 void init(); void destroy(); String intercept(ActionInvocation invocation) throws Exception; 1:所有拦截器都使用接口Interceptor,Action去实现这个接口;
public String intercept(ActionInvocation invocation) throws xception {
System.out.println("interceptor!!");
String result=invocation.invoke();
return result;
}
其中intercept方法是拦截器的核心方法,所有安装的拦截器都会调用之个方法。在Struts2中已经在struts-default.xml中预定义了一些自带的拦截器,如timer、params等。如果在<package>标签中继承struts-default,则当前package就会自动拥有struts-default.xml中的所有配置。
二、Struts2 拦截器详细配置: 默认拦截器是在不设置任何拦截器的时候,给予默认设置的,当只要设置任何一个拦截器就会覆盖掉默认拦截器,故此,我们需要手动设置 一旦实现了检查拦截器,就可以在所有需要实现权限控制的Action中复用上面的拦截器。 为了使用该拦截器,首先在struts.xml文件中定义拦截器,定义拦截器的配置片段如下: <!-- 用户拦截器定义在该元素下 --> <interceptors> <!-- 定义了一个名为authority的拦截器 --> <interceptor name="authority" class="lee.AuthorityInterceptor"/> </interceptors> 定义了该拦截器之后,可以在Action中应用该拦截器,应用该拦截器的配置片段如下: <!-- 定义一个名为viewBook的Action,其实现类为ActionSupport --> <action name="viewBook"> <!-- 返回success视图名时,转入/WEB-INF/jsp/viewBook.jsp页面 --> <result>/WEB-INF/jsp/viewBook.jsp</result> <!-- 拦截器一般配置在result元素之后! --> <interceptor-ref name="defaultStack"/> <!-- 应用自定义拦截器 --> <interceptor-ref name="authority"/> </action> 上面名为viewBook的Action,没有指定class属性,默认使用ActionSupport类,配置该Action时,只是指定了一个Result,指定返回success字符串时,系统将转入/WEBINF/jsp/viewBook.jsp页面。但并为未配置login视图对应的JSP页面。 考虑到这个拦截器的重复使用,可能在多个Action都需要跳转到login逻辑试图,故将login Result定义成一个全局Result。 下面是配置login Result的配置片段: <!-- 定义全局Result --> <global-results> <!-- 当返回login视图名时,转入/login.jsp页面 --> <result name="login">/login.jsp</result> </global-results> 经过上面的配置,如果浏览者在浏览器中直接发送viewBook请求,将会转入如图所示的页面。 这种通过拦截器进行权限控制的方式,显然具有更好的代码复用。 如果为了简化struts.xml文件的配置,避免在每个Action中重复配置该拦截器,可以将该拦截器配置成一个默认拦截器栈(这个默认拦截器栈应该包括default-stack拦截器栈和权限检查拦截器)。 定义自己的默认拦截器栈的配置片段如下: <interceptors> <!-- 定义权限检查拦截器 --> <interceptor name="authority" class="lee.AuthorityInterceptor"/> <!-- 定义一个包含权限检查的拦截器栈 --> <interceptor-stack name="mydefault"> <!-- 定义拦截器栈包含default-stack拦截器栈 --> <interceptor-ref name="default-stack"/> <!-- 定义拦截器栈包含authority拦截器 --> <interceptor-ref name=" authority"/> </interceptor- stack > </interceptors> 一旦定义了上面的mydefault拦截器栈,这个拦截器栈包含了权限检查拦截器和系统默认的拦截器栈。如果将这个拦截器栈定义成默认拦截器,则可以避免在每个Action需要重复定义权限检查拦截器。 下面是定义默认拦截器的配置片段: <default-interceptor-ref name="mydefault"/> 一旦在某个包下定义了上面的默认拦截器栈,在该包下的所有Action都会自动增加权限检查功能。对于那些不需要使用权限控制的Action,将它们定义在另外的包中――这个包中依然使用系统原来的默认拦截器栈,将不会有权限控制功能。 PS:拦截器,拦截器栈和默认的拦截器之间的关系 1:拦截器和拦截器栈是一个级别的,也就是说一个拦截器栈中包括许多拦截器,一个拦截器栈中还可以包括许多拦截器栈,配置如下方式: <interceptors> <!-- 先定义拦截器 --> <interceptor name="myInterceptor" class="com.struts2.interceptor.MyInterceptor"> <!-- 指定系统初始化给拦截器的参数 --> <param name="hello">张--</param> </interceptor> <!-- 加到自己设置的拦截器栈里边去 --> <interceptor-stack name="myStack"> <interceptor-ref name="myInterceptor"> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> 拦截器的使用: 1.先定义; 2.在引用使用; <interceptor name="myInterceptor" class="com.struts2.interceptor.MyInterceptor"> <interceptor-ref name="myInterceptor"> </interceptor-ref> 2:struts2中有一个系统默认的拦截器栈是 defaultStack,如果你手动引用自己的拦截器,系统默认的拦截器栈将不起作用;这样必需手动引入系统的拦截器栈 <interceptor-ref name="defaultStack"> </interceptor-ref> 如果想改变系统默认的拦截器栈,可以这样配置: <default-interceptor-ref name="myStack"> </default-interceptor-ref> 其中myStack是自己定义的拦截器栈名字; 如果拦截器栈中有多个拦截器,在执行action之前的顺序跟配置拦截器的顺序一致,而在action之后执行的顺序是相反的; 过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符 拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。 拦截器与过滤器的区别 : 1、拦截器是基于java的反射机制的,而过滤器是基于函数回调。 2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。 3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。 4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。 5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 6、执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
