拦截器与过滤器的区别
一、filter基于filter接口中的doFilter回调函数,interceptor则基于Java本身的反射机制;
二、filter是依赖于servlet容器的,没有servlet容器就无法回调doFilter方法,而interceptor与servlet无关;
三、filter的过滤范围比interceptor大,filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而interceptor只能过滤请求,只对action起作用,在action之前开始,在action完成后结束(如被拦截,不执行action);
四、filter的过滤一般在加载的时候在init方法声明,而interceptor可以通过在xml声明是guest请求还是user请求来辨别是否过滤;
五、interceptor可以访问action上下文、值栈里的对象,而filter不能;
六、在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用一次。
Struts2 拦截器在访问某个 Action 方法之前或之后实施拦截,Struts2 拦截器是可插拔的(在系统运行的时候可以配置与删除), 拦截器是 AOP 的一种实现.
拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用
struts的执行原理
strutsPrepareAndExecuteFilter有两层含义(Prepare预处理, Execute执行)
Prepare操作由过滤器 init方法完成 -------- Dispacher类 init方法
* 加载struts配置文件,如果配置文件有错误,启动时就会报错
Execute操作由过滤器 doFilter方法完成 ------ Dispacher类serviceAction
ActionProxy proxy =config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method,extraContext, true, false);
为目标Action创建代理对象 ActionProxy
proxy.execute() ------ ActionInvocation.invoke ----
if (interceptors.hasNext()) {
resultCode =interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
--- ActionInvocation.invoke 重复调用下一个拦截器 ----- resultCode = invokeActionOnly();
Interceptor接口
每个拦截器都是实现了 com.opensymphony.xwork2.interceptor.Interceptor接口的 Java 类:
• init: 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化
• interecept: 每拦截一个动作请求, 该方法就会被调用一次.
• destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次.
l Struts 会依次调用程序员为某个 Action 而注册的每一个拦截器的 interecept 方法.
l 每次调用 interecept 方法时, Struts 会传递一个ActionInvocation 接口的实例.
l ActionInvocation: 代表一个给定动作的执行状态, 拦截器可以从该类的对象里获得与该动作相关联的 Action 对象和 Result 对象. 在完成拦截器自己的任务之后, 拦截器将调用 ActionInvocation对象的 invoke方法前进到 Action处理流程的下一个环节.
l 还可以调用ActionInvocation 对象的 addPreResultListener方法给 ActionInvocation 对象 “挂” 上一个或多个PreResultListener 监听器. 该监听器对象可以在动作执行完毕之后, 开始执行动作结果之前做些事情
l AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现
自定义拦截器
拦截器都必须实现 Interceptor 接口 , 必须实现 intercept 方法
java.lang.Stringintercept(ActionInvocation invocation)
* intercept 方法类似 Filter 中 doFilter ,执行拦截后 , 调用 invocation.invoke 方法
自定义拦截器 也可以继承AbstractInterceptor
写完拦截器后必须要进行配置
第一种配置(用的少)
<!-- 第一步 在struts.xml文件中注册权限控制拦截器 -->
<interceptors>
配置自己的拦截器,写上类名
<interceptorname="privilege"class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>
</interceptors>
<actionname="addEmployee" class="cn.itcast.action.AddEmployeeAction">
<result>/index.jsp</result>
<!-- 第二步,在Action访问中 配置拦截器
当Action 指定了使用拦截器后,默认拦截器会失效,因此先要先写上默认的拦截器栈
-->
<interceptor-refname="defaultStack"></interceptor-ref>
<interceptor-refname="privilege"></interceptor-ref>
</action>
第二种
<!-- 第一步 注册权限控制拦截器 -->
<interceptors>
<interceptorname="privilege"class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>
<!-- 定义了一个新的拦截器栈 -->
<interceptor-stackname="privilegeStack">
<interceptor-refname="defaultStack"></interceptor-ref>
<interceptor-refname="privilege"></interceptor-ref>
</interceptor-stack>
</interceptors>
<actionname="addEmployee"class="cn.itcast.action.AddEmployeeAction">
<result>/index.jsp</result>
<!-- 第二步,在Action访问中 配置拦截器 -->
<interceptor-refname="privilegeStack"></interceptor-ref>
</action>