8.1 理解拦截器
拦截器是Struts 2的核心,Struts 2的大部分功能都是由拦截器实现的。
在执行Action的execute方法之前,Struts 2会首先执行在struts.xml中引用的拦截器,在执行完所有引用的拦截器intercept方法后,会执行Action的execute方法。
8.1.1 拦截器的实现原理
当请求Action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个的调用列表中的拦截器。
ServletDispatcher初始化一个ActionProxy实例,并调用execute方法→拦截器首先拦截用户请求,然后交给Action处理→Action处理完毕,返回给用户一个逻辑视图
类似此功能的类:
TokenInterceptor
TokenSessionStoreInterceptor
DefaultWorkflowInterceptor
ValidationInterceptor
8.1.2 实现一个简单拦截器
用户自定义拦截器,三步:
1、自定义拦截器类(必须实现Interceptor接口或继承AbstractInterceptor抽象类)
/** * 用户自定义的拦截器类必须实行interceptor接口或继承已实现了interceptor接口的抽象类AbstractInterceptor * 推荐使用抽象类AbstractInterceptor */ publicclass HelloInterceptor extends AbstractInterceptor{ ** * intercept方法:实现拦截器动作,参数ActionInvocation是被拦截Action的一个引用, * 可以调用该参数的invoke()方法,将控制器传给下一个拦截器或Action的execute方法。 */ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { System.out.println("拦截器开始运行。。。。"); String result = actionInvocation.invoke(); System.out.println("!拦截器结束了。。。。"); return result; }} |
2、在struts.xml中定义自定义的拦截器
在<interceptor>中定义拦截器
3、在struts.xml的<action>中使用拦截器
在<interceptor-ref>中使用拦截器
<packagename="helloInterceptor"extends="struts-default"> <!-- interceptor标记:用来定义一个具体的拦截器 --> <interceptors> <interceptor name="helloInterceptor" class="com.inter.HelloInterceptor"></interceptor> </interceptors> <!-- 拦截器使用:在一个具体的Action中,interceptor-ref标记就是使用已在interceptor标记中定义好的拦截器 --> <actionname="helloAction"class="com.action.HelloAction"> <resultname="success">/success.jsp</result> <resultname="input">/reg.jsp</result> <!--拦截器使用 --> <interceptor-refname="defaultStack"></interceptor-ref> <interceptor-refname="helloInterceptor"> </interceptor-ref> </action> </package> |
8.2 拦截器配置初步
8.2.1 struts-default.xml中拦截器的定义:
<interceptors> <interceptorname="conversionError"class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptorname="exception"class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptorname="actionMappingParams"class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptorname="prepare"class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptorname="checkbox"class="org.apache.struts2.interceptor.CheckboxInterceptor"/> <!-- Basic stack --> <interceptor-stackname="basicStack"> <interceptor-refname="exception"/> <interceptor-refname="servletConfig"/> <interceptor-refname="prepare"/> <interceptor-refname="checkbox"/> <interceptor-refname="multiselect"/> <interceptor-refname="actionMappingParams"/> <interceptor-refname="params"> <paramname="excludeParams">dojo\..*,^struts\..*</param> </interceptor-ref> <interceptor-refname="conversionError"/> </interceptor-stack> </interceptors> |
8.2.2 使用拦截器
只需在struts.xml的<action>中添加<interceptor-ref>标记中配置已定义好的拦截器。
<actionname="helloAction"class="com.action.HelloAction"> <interceptor-refname="defaultStack"></interceptor-ref> <interceptor-refname="helloInterceptor"></interceptor-ref> </action> |
当用户使用了一个自定义的拦截器后,系统默认的拦截器defaultStack就会失效。所以必须添加上默认拦截器的配置代码:
<interceptor-refname="defaultStack"></interceptor-ref>
8.2.3 使用拦截器的过滤方法特性
如何实现对Action的部分方法进行拦截?
Struts 2为了实现方法过滤功能,定义了MethodFilterInterceptor类,该类继承了AbstractInterceptor类。该类重写了AbstractInterceptor类的intercept方法,提供了一个doIntercept的抽象方法,自定义拦截逻辑。
(1)在Action中进行配置:
publicclass FilterHelloInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation arg0) throws Exception { System.out.println("逻辑实现过程是一样的,只是方法名不同而已。"); String res = arg0.invoke(); return res;} * MethodFilterInterceptor类中两个重要的方法可用于方法的过滤: * setExcludeMethods(排除过滤)和setIncludeMethods(要过滤), * 冲突时,以setIncludeMethods为准 * 这两个方法灵活性不够,所以可以在struts.xml中进行方法是否过滤的配置 @Override publicvoid setExcludeMethods(String excludeMethods) { super.setExcludeMethods(excludeMethods); } @Override publicvoid setIncludeMethods(String includeMethods) { super.setIncludeMethods(includeMethods); }} |
(2)struts.xml中配置
<packagename="filterHelloInterceptor"extends="struts-default"> <interceptors> <interceptorname="filterHelloInterceptor"class="com.inter.FilterHelloInterceptor"></interceptor> </interceptors> <actionname="sayHello"class="com.action.SayHelloAction"> <result>success.jsp</result> <!--name="excludeMethods"表示要添加排除过滤的方法,当前配置要排除的拦截方法是execute--> <interceptor-refname="filterHelloInterceptor"> <paramname="excludeMethods">execute</param> </interceptor-ref> </action> </package> |
8.3 Struts 2内建的拦截器
8.4 使用拦截器进行权限控制
检测用户是否登录,通常是跟踪用户的session来完成的。通过ActionContext访问session中的属性。
拦截器代码:
publicclass CheckInterceptor extends AbstractInterceptor{ /** * 用intercept方法对session中是否存在admin用户作了验证,若用户名为admin,则 为合法用户,可跳转到success.jsp页面,否则留在登录界面,并给出错误提示。 */ @Override public String intercept(ActionInvocation arg0) throws Exception { ActionContext ac = arg0.getInvocationContext(); Map<?, ?> sessionMap = ac.getSession(); String user = (String) sessionMap.get("name");//从sessionMap中得到用户实例 if(user!=null&&user.equals("admin")){ return arg0.invoke(); } ac.put("tip","请先登录!"); return Action.LOGIN; }} |
ActionContext中的tip在JSP页面中取出:${requestScope.tip }