一、概述
Interceptor:拦截器,拦截Action的作用(Struts2框架核心功能都是依赖拦截器实现的)
Filter:过滤器,过滤客户端向服务器发送的请求
Interceptor:拦截器,拦截客户端对Action的访问,可以拦截Action中具体的方法
二、Struts2的执行流程
客户端向服务器发送一个Action的请求,执行核心过滤器(StrutsPrepareAndersonExecuteFilter)的doFilter()方法,执行executeAction()方法,执行dispatcher.serviceAction()创建一个Action代理,最终执行的是Action代理中的execute(),execute方法中调用ActionInvocation的invoke方法。在这个方法内部递归执行一组拦截器(完成部分功能),执行完所有拦截器,就会执行目标Action,根据Action的返回的结果进行页面跳转。
三、自定义拦截器
①、搭建Struts2的环境(引入jar包、配置web.xml、编写Action、配置struts.xml)
②、编写拦截器类(类需要实现Interceptor接口或者继承AbstractInterceptor类)
public class InterceptorDemo1 extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("InterceptorDemo1执行"); String result=invocation.invoke(); System.out.println("InterceptorDemo1执行结束"); return result;//invocation.invoke(); } }
继承AbstractInterceptor类只需要重写intercept()方法,而要实现Interceptor接口的,就需要多写一些方法
③、配置拦截器
Ⅰ、直接引入自定义拦截器
<package name="interceptorDemo" extends="struts-default" namespace="/"> <!-- Ⅰ、定义拦截器 --> <interceptors> <interceptor name="interceptorDemo1" class="com.xxx.interceptor.InterceptorDemo1"/> <interceptor name="interceptorDemo2" class="com.xxx.interceptor.InterceptorDemo2"/> </interceptors> <action name="demo1" class="com.xxx.web.action.Demo1Action"> <result>/demo1/index.jsp</result> <!-- Ⅱ、引入拦截器(一旦引入自定义拦截器,默认拦截栈中的拦截器就不会执行了,需要手动引入默认拦截器栈) --> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="interceptorDemo1"></interceptor-ref> <interceptor-ref name="interceptorDemo2"></interceptor-ref> </action> </package>
Ⅱ、通过拦截器栈的方式
<package name="interceptorDemo" extends="struts-default" namespace="/"> <!-- Ⅰ、定义拦截器 并定义拦截器栈--> <interceptors> <interceptor name="interceptorDemo1" class="com.xxx.interceptor.InterceptorDemo1"/> <interceptor name="interceptorDemo2" class="com.xxx.interceptor.InterceptorDemo2"/> <!-- Ⅱ、定义拦截器栈 (一旦引入自定义拦截器,默认拦截栈中的拦截器就不会执行了,需要手动引入默认拦截器栈) --> <interceptor-stack name="custStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="interceptorDemo1"></interceptor-ref> <interceptor-ref name="interceptorDemo2"></interceptor-ref> </interceptor-stack> </interceptors> <action name="demo1" class="com.xxx.web.action.Demo1Action"> <result>/demo1/index.jsp</result> <!-- Ⅲ、引入自定义拦截器栈--> <interceptor-ref name="custStack"></interceptor-ref> </action> </package>
注意:定义拦截器和拦截器栈都是在<package>节点下,而真正使用的拦截器的Action需要在对应的<action>节点中引入的拦截器
四、拦截器中心思想
就是AOP思想,在不修改程序代码的情况下,对程序进行扩展
实例:权限拦截器
①、创建一个类型继承MethodFilterInterceptor类
public class PrivilegeInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation invocation) throws Exception { //判断session是否有用户数据 User existUser=(User) ServletActionContext.getRequest().getSession().getAttribute("existUser"); if(existUser==null) { //输出提示信息 ActionSupport actionSupport= (ActionSupport) invocation.getAction(); actionSupport.addActionError("没有登录,无法访问!"); //回到登录页面 return actionSupport.LOGIN; } //已经登录,继续执行 return invocation.invoke(); } }
为什么要继承MethodFilterInterceptor?
MethodFilterInterceptor中有两个属性:
excludeMethods(拦截器不会拦截器的方法集合)
includeMethods(拦截器需要拦截器的方法集合)
protected Set<String> excludeMethods = Collections.emptySet(); protected Set<String> includeMethods = Collections.emptySet();
actionSupport.addActionError()方法,设置输出信息,jsp页面代码如下:
<s:actionerror/>
②、配置拦截器
<package name="crm" extends="struts-default" namespace="/"> <!-- Ⅰ、定义拦截器 并定义拦截器栈--> <interceptors> <interceptor name="privilegeInterceptor" class="com.xxx.interceptor.PrivilegeInterceptor"/> </interceptors> <global-allowed-methods>regex:.*</global-allowed-methods> <!-- 每个action都需要login视图 --> <global-results> <result name="login">/login.jsp</result> </global-results> <action name="customer_*" class="com.xxx.web.action.CustomerAction" method="{1}"> <result name="findSuccess">/jsp/customer/list.jsp</result> <result name="savaUI">/jsp/customer/add.jsp</result> <result name="saveSuccess" type="redirectAction"> <param name="namespace">/xxxx</param> <param name="actionName">xxx_xxx</param> </result> <!-- 引入自定义拦截器,拦截此action中所有方法--> <interceptor-ref name="privilegeInterceptor"/> <interceptor-ref name="defaultStack"/> </action> <action name="user_*" class="com.xxx.web.action.UserAction" method="{1}"> <result type="redirect">/index.jsp</result> <!-- 引入自定义拦截器--> <interceptor-ref name="privilegeInterceptor"> <!-- 配置excludeMethods节点中的方法不拦截,配置多个方法时以逗号(,)隔开 --> <param name="excludeMethods">login,regist</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> </action> </package