【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【拦截器机制】

来源:互联网 发布:jquery.rotate.js api 编辑:程序博客网 时间:2024/05/21 17:20

【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【拦截器机制】
本文地址:http://blog.csdn.net/shanglianlm/article/details/50096113

详解 Struts 2 的拦截器机制

这里写图片描述

1 拦截器在 Struts 2 中的作用

Struts 2 框架的绝大部分功能都是通过拦截器来实现的,当 StrutsPrepareAndExecuteFilter 拦截到用户请求后,大量拦截器将会对用户请求进行处理,然后才会调用用户开发的 Action 实例的方法来处理请求。

拦截器与 Action 之间的关系:
这里写图片描述

2 Struts 2 内建的拦截器

这里写图片描述
这里写图片描述

3 配置拦截器

定义拦截器

<!-- 通过指定拦截器名和拦截器实现类来定义拦截器 --><interceptor name="拦截器名" class="拦截器实现类" />

定义拦截器和参数

<!-- 通过指定拦截器名和拦截器实现类来定义拦截器 --><interceptor name="拦截器名" class="拦截器实现类" />    <!-- 为拦截器指定参数值 -->    <param name="参数名">参数值</param></interceptor>

定义拦截器栈

<interceptor-stack name="拦截器栈名">   <interceptor-ref name="拦截器一" />   <interceptor-ref name="拦截器二" /></interceptor-stack>

拦截器栈里面也可以包含拦截器栈。

这里写图片描述

4 使用拦截器

在 Action 中使用拦截器,

<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="loginPro" class="org.crazyit.app.action.LoginAction">    <result name="error">/WEB-INF/content/error.jsp</result>    <result name="success">/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>

5 配置默认拦截器

这里写图片描述

<package name="包名">   <!-- 所有拦截器和拦截器栈都配置在该元素下 -->   <interceptors>      <!-- 定义拦截器 -->      <interceptor .../>      <!-- 定义拦截器栈 -->      <interceptor-stack ../>   </interceptors>   <!-- 配置该包下的默认拦截器 -->   <default-interceptor-ref name="拦截器名或拦截器栈名" />   或者   <default-interceptor-ref name="拦截器名或拦截器栈名" />      <param name="参数名">参数值</param>   </default-interceptor-ref>   <action ../></package>

这里写图片描述

在 Struts 2 的 struts-default.xml 文件中有

<struts>  <package name="struts-default">     <default-interceptor-ref name="defaultStack" />  </package></struts>

当我们定义的包继承 struts-default 包时,则 defaultStack 拦截器栈会自动生效。

这里写图片描述

6 实现拦截器类

如果用户要开发自己的拦截器类,应该实现 com.opensymphony.xwork2.interceptor.Interceptor 接口,该接口的类定义如下:

public interface Interceptor extends Serializable{  // 销毁该拦截器之前的回调方法  void destroy();  // 初始化该拦截器之前的回调方法  void init();   // 拦截器实现拦截的逻辑方法  String intercept(ActionInvocation invocation) throws Exception;}

这里写图片描述

这里写图片描述

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的execute方法        String result = invocation.invoke();        //打印执行结束的时间        System.out.println(name + " 拦截器的动作---------" +             "执行完登录Action的时间为:" + new Date());        long end = System.currentTimeMillis();        System.out.println(name + " 拦截器的动作---------" +             "执行完该Action的事件为" + (end - start) + "毫秒");        return result;    }}

7 使用拦截器

使用拦截器步骤:
1. 通过

<struts>    <!-- 通过常量配置Struts 2的国际化资源信息 -->    <constant name="struts.custom.i18n.resources" value="mess"/>    <!-- 通过常量配置Struts 2所使用的解码集-->    <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="loginPro" class="org.crazyit.app.action.LoginAction">            <result name="error">/WEB-INF/content/error.jsp</result>            <result name="success">/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>

8 拦截方法的拦截器

这里写图片描述

//拦截方法的拦截器,应该继承MethodFilterInterceptor抽象类public class MyFilterInterceptor    extends MethodFilterInterceptor{    //简单拦截器的名字    private String name;    //为该简单拦截器设置名字的setter方法    public void setName(String name)    {        this.name = name;    }    //重写doIntercept方法,实现对Action的拦截逻辑    public String doIntercept(ActionInvocation invocation)        throws Exception    {        //取得被拦截的Action实例        LoginAction action = (LoginAction)invocation.getAction();        //打印执行开始的时间        System.out.println(name + " 拦截器的动作---------"            + "开始执行登录Action的时间为:" + new Date());        //取得开始执行Action的时间        long start = System.currentTimeMillis();        //执行该拦截器的后一个拦截器,或者直接指定Action的execute方法        String result = invocation.invoke();        //打印执行结束的时间        System.out.println(name + " 拦截器的动作---------"             + "执行完登录Action的时间为:" + new Date());        long end = System.currentTimeMillis();        //打印执行该Action所花费的时间        System.out.println(name + " 拦截器的动作---------"            + "执行完该Action的事件为" + (end - start) + "毫秒");        return result;    }}

这里写图片描述

<struts>    <!-- 通过常量配置Struts 2的国际化资源信息 -->    <constant name="struts.custom.i18n.resources" value="mess"/>    <!-- 通过常量配置Struts 2所使用的解码集-->    <constant name="struts.i18n.encoding" value="GBK"/><!-- 配置本系统所使用的包 --><package name="lee" extends="struts-default">    <!-- 应用所需使用的拦截器都在该元素下配置 -->    <interceptors>        <!-- 配置mysimple拦截器 -->        <interceptor name="mysimple"        class="org.crazyit.app.interceptor.MyFilterInterceptor">            <!-- 为拦截器指定参数值 -->            <param name="name">拦截方法的拦截器</param>        </interceptor>    </interceptors>    <action name="loginPro" class="org.crazyit.app.action.LoginAction">        <result name="error">/WEB-INF/content/error.jsp</result>        <result name="success">/WEB-INF/content/welcome.jsp</result>         <!-- 配置系统的默认拦截器 -->        <interceptor-ref name="defaultStack"/>        <!-- 应用自定义的mysimple拦截器 -->        <interceptor-ref name="mysimple">            <!-- 重新指定name属性的属性值 -->            <param name="name">改名后的拦截方法过滤拦截器</param>            <!-- 指定execute方法不需要被拦截 -->            <param name="excludeMethods">execute</param>        </interceptor-ref>    </action>    <action name="*">        <result>/WEB-INF/content/{1}.jsp</result>    </action></package></struts>

这里写图片描述

9 拦截器的执行顺序

<struts>    <!-- 通过常量配置Struts 2的国际化资源信息 -->    <constant name="struts.custom.i18n.resources" value="mess"/>    <!-- 通过常量配置Struts 2所使用的解码集-->    <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="loginPro" class="org.crazyit.app.action.LoginAction">            <result name="error">/WEB-INF/content/error.jsp</result>            <result name="success">/WEB-INF/content/welcome.jsp</result>             <!-- 配置系统的默认拦截器 -->            <interceptor-ref name="defaultStack"/>            <!-- 应用自定义的mysimple拦截器 -->            <interceptor-ref name="mysimple">                <param name="name">第一个</param>            </interceptor-ref>            <interceptor-ref name="mysimple">                <param name="name">第二个</param>            </interceptor-ref>        </action>        <action name="*">            <result>/WEB-INF/content/{1}.jsp</result>        </action>    </package></struts>

这里写图片描述
这里写图片描述

10 拦截结果的监听器

这里写图片描述

public class MyPreResultListener implements PreResultListener{    //定义在处理Result之前的行为    public void beforeResult(ActionInvocation invocation        ,String resultCode)    {        //打印出执行结果        System.out.println("返回的逻辑视图为:" + resultCode);        try        {            invocation.invoke();        }        catch (Exception ex)        {            ex.printStackTrace();        }        finally        {        }    }}

手动注册给拦截器

public class BeforeResultInterceptor    extends AbstractInterceptor{    public String intercept(ActionInvocation invocation)        throws Exception    {        //将一个拦截结果的监听器注册给该拦截器        invocation.addPreResultListener(new MyPreResultListener());         System.out.println("execute方法执行之前的拦截...");        //调用下一个拦截器,或者Action的执行方法        String result = invocation.invoke();        System.out.println("execute方法执行之后的拦截...");        return result;    }}

这里写图片描述

11 覆盖拦截器栈里特定拦截器的参数

这里写图片描述

<struts>    <!-- 通过常量配置Struts 2的国际化资源信息 -->    <constant name="struts.custom.i18n.resources" value="mess"/>    <!-- 通过常量配置Struts 2所使用的解码集-->    <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>            <!-- 配置第二个拦截器 -->            <interceptor name="second" class="lee.SecondInterceptor"/>            <!-- 配置名为my-stack的拦截器栈 -->            <interceptor-stack name="my-stack">                <!-- 配置拦截器栈内的第一个拦截器 -->                <interceptor-ref name="mysimple">                    <param name="name">第一个</param>                </interceptor-ref>                <!-- 配置拦截器栈内的第二个拦截器 -->                <interceptor-ref name="second">                    <param name="name">第二个</param>                </interceptor-ref>            </interceptor-stack>        </interceptors>        <action name="loginPro" class="org.crazyit.app.action.LoginAction">            <result name="error">/WEB-INF/content/error.jsp</result>            <result name="success">/WEB-INF/content/welcome.jsp</result>             <!-- 配置系统的默认拦截器 -->            <interceptor-ref name="defaultStack"/>            <!-- 应用上面的拦截器栈 -->            <interceptor-ref name="my-stack">            <!-- 覆盖指定拦截器的指定参数值 -->            <param name="second.name">改名后的拦截器</param>            </interceptor-ref>        </action>        <action name="*">            <result>/WEB-INF/content/{1}.jsp</result>        </action>    </package></struts>

12 使用拦截器完成权限控制

这里写图片描述
权限检查拦截器类:

//权限检查拦截器继承AbstractInterceptor类public class AuthorityInterceptor    extends AbstractInterceptor{    //拦截Action处理的拦截方法    public String intercept(ActionInvocation invocation)        throws Exception    {        //取得请求相关的ActionContext实例        ActionContext ctx = invocation.getInvocationContext();        Map session = ctx.getSession();        //取出名为user的Session属性        String user = (String)session.get("user");        //如果没有登录,或者登录所用的用户名不是scott,都返回重新登录        if (user != null && user.equals("crazyit.org") )        {            return invocation.invoke();        }        //没有登录,将服务器提示设置成一个HttpServletRequest属性        ctx.put("tip" ,            "您还没有登录,请输入crazyit.org,leegang登录系统");        //直接返回login的逻辑视图        return Action.LOGIN;    }}

定义拦截器

<!-- 用户拦截器定义在该元素下 --><interceptors>   <!-- 定义了一个名为authority的拦截器 -->   <interceptor name="authority" class="org.crazyit.app.interceptor.AuthorityInterceptor"/></interceptors>

使用拦截器

<!-- 定义一个名为viewBook的Action,其实现类为ActionSupport --><action name="viewBook">    <!-- 返回success视图名时,转入/WEB-INF/content/viewBook.jsp页面 -->    <result>/WEB-INF/content/viewBook.jsp</result>    <interceptor-ref name="defaultStack"/>    <!-- 应用自定义拦截器 -->    <interceptor-ref name="authority"/></action><action name="*">    <result>/WEB-INF/content/{1}.jsp</result></action>

考虑到多个 Action 都需要跳转到 login 逻辑视图,故将 login 的结果映射定义为一个全局结果映射。

<!-- 定义全局Result --><global-results>    <!-- 当返回login视图名时,转入login.jsp页面 -->    <result name="login">/WEB-INF/content/login.jsp</result></global-results>

这里写图片描述

<interceptors>  <!-- -->  <interceptor name="authority" class="lee.AuthorityInterceptor" />  <!-- -->  <interceptor-stack name="mydefault">    <!-- -->    <interceptor name="default-stack" />    <!-- -->    <interceptor name="authority" />  </interceptor-stack></interceptors>

这里写图片描述

<default-interceptor-ref name="mydefault" />

这里写图片描述

0 0
原创粉丝点击