• Struts2拦截器


    拦截器(interceptor)是Struts2最强大的特性之一,拦截器可以让你在Action和result被执行之前或之后进行一些处理。同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很多特性都是由拦截器来完成的。例如params拦截器将HTTP请求中的参数解析出来,并设置为Action的属性。servlet-config拦截器直接将HTTP请求中的HttpServletRequest对象化HttpServletResponse对象传给Action。

    image

    Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特性。这些内置的拦截器在struts-default.xml中配置。只有配置了拦截器,拦截器才可以正常的工作和运行。在struts-default.xml中拦截器的配置片段为:

    <package name="struts-default" abstract="true"><interceptors>
            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/><interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
            //…其他拦截器配置
            <interceptor-stack name="defaultStack"><interceptor-ref name="exception"/>
                  <interceptor-ref name="alias"/>
                    <interceptor-ref name="servletConfig"/>
                    <interceptor-ref name="i18n"/>
                    //…其他拦截器的引用
              </interceptor-stack>    
        </interceptors>
        <default-interceptor-ref name="defaultStack"/></package>

    ① package将属性abstract设置为true,代表此package为一个抽象的package。抽象package和非抽象package的区别在于抽象的package中不能配置action。

    ② name属性指定拦截器的名字,class属性指定拦截器的完全限定名。

    ③ 多个拦截器可以组成拦截器栈。name属性为拦截器栈的名字。

    ④ 指定当前package的默认拦截器(栈)。当前指定的默认拦截器栈为defaultStack,该拦截器栈是Struts2运行的一个基本拦截器栈,一般我们不用在自己配置它,因为在大多数情况下,我们自定义的package是继承自struts-default这个package的。

    我们以Struts2内置的timer拦截器为例,来学习如何在我们的应用中添加其他的拦截器。timer拦截器可以统计action执行的时间。我们可以修改package中默认的拦截器,那么将替换掉struts-default中配置的defaultStack拦截器栈,导致Struts2无法正常运行,比如无法获取表单的值等等。那么该如何正确的配置呢?可以在添加新的拦截器的基础上加入defaultStack拦截器栈,这样就可以保证defaultStack拦截器栈的存在。

    <package name="myStruts" extends="struts-default">
    	<interceptors>
    		<interceptor-stack name="myInterceptor"><interceptor-ref name="timer"/>  
    			<interceptor-ref name="defaultStack"/>  
    		</interceptor-stack>
    	</interceptors>
    	<default-interceptor-ref name="myInterceptor"/><action name="userAction"
    		class="com.kay.action.UserAction">
    		<result name="success">suc.jsp</result>
    		<result name="input">index.jsp</result>
    		<result name="error">err.jsp</result>
    	</action>
    </package>

    ① 添加一个自定义的拦截器栈,并在其中包含time拦截器和defaultStack拦截器栈。

    ② 设置当前的package的默认拦截器栈为自定义的拦截器栈。

    修改package的默认拦截器会应用的package中的所有Action中,如果只想给其中一个Action添加拦截器,则可以这样来做:

    <package name="myStruts" extends="struts-default">
    	<interceptors>
    		<interceptor-stack name="myInterceptor">
    			<interceptor-ref name="timer"/>
    			<interceptor-ref name="defaultStack"/>
    		</interceptor-stack>
    	</interceptors>
    	<action name="userAction"
    		class="com.kay.action.UserAction">
    		<interceptor-ref name="myInterceptor"/><result name="success">suc.jsp</result>
    		<result name="input">index.jsp</result>
    		<result name="error">err.jsp</result>
    	</action>
    </package>

    ① 给UserAction添加拦截器。

    如果要创建自己的拦截器,只需要实现Interceptor接口,该接口中定义了以下三个方法:

    void init():

    在拦截器初始化之后,在执行拦截之前,系统调用该方法。对于一个拦截器而言,init方法只会被调用一次。

    String intercept(ActionInvocation invocation) throws Exception:

    该方法是拦截器的拦截方法,返回一个字符串,系统将会跳转到该字符串对应的视图资源。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该对象的invoke方法,将控制权转给下一个拦截器或者转给Action的execute方法。

    void destroy():

    该方法与init方法对应,在拦截器示例被销毁之前,系统将会调用该方法。

    除了Interceptor接口外,Struts2中还提供了一个AbStractInterceptor类,该类提供了一个init和destroy方法的空实现。如果不需要就不用重写这两个方法,可见继承自AbstractInterceptor类可以让我们构建拦截器时变得简单。

    下面我们构建自己的拦截器,实现timer拦截器的效果。

    public class MyInterceptor extends AbstractInterceptor {
    	public String intercept(ActionInvocation invocation) throws Exception {
    		long startTime = System.currentTimeMillis();  ①
    		String result = invocation.invoke();  ②
    		long endTime = System.currentTimeMillis();  ③
    		System.out.println("Action执行共需要" + (endTime - startTime) + "毫秒");
    		return result; 
    	}
    }

    ① 获得Action执行的开始时间。

    ② 将控制权交给下一个拦截器,如果该拦截器是最后一个拦截器,则调用Action的execute方法。

    ③ 获得Action执行的结束时间。

    在配置文件struts.xml中配置拦截器:

    <package name="myStruts" extends="struts-default">
    	<interceptors>
    		<interceptor name="myTimer" class="com.kay.interceptor.MyInterceptor"></interceptor><interceptor-stack name="myInterceptor">
    			<interceptor-ref name="myTimer"/><interceptor-ref name="defaultStack"/>
    		</interceptor-stack>
    	</interceptors>
    	<action name="userAction"
    		class="com.kay.action.UserAction">
    		<interceptor-ref name="myInterceptor"/>
    		<result name="success">suc.jsp</result>
    		<result name="input">index.jsp</result>
    		<result name="error">err.jsp</result>
    	</action>
    </package>

    ① 定义一个新的拦截器,name属性为拦截器的名字,class属性为拦截器的完全限定名。

    ② 在拦截器栈中加入新的拦截器。

    从拦截器的运行原理上和我们以前学习的Servlet中的过滤器是不是很相像呢?其实它们只有一个重要的区别,就是拦截器的工作是不依赖容器的,这会在进行单元测试时变得简单。

  • 相关阅读:
    云小课 | 搬迁本地数据至OBS,多种方式任你选
    云小课 | 磁盘容量不够用?小课教你来扩容!
    云图说 | 容器交付流水线ContainerOps,助力企业容器化转型
    云图说 | 华为云MCP多云容器平台,让您轻松灾备!
    【DevCloud · 敏捷智库】如何拆分用户故事
    十分钟从入门到精通(下)——OBS权限配置
    十分钟从入门到精通(上)——OBS权限配置
    云图说|全新华为云云备份服务:为您的数据提供三合一的保障
    费米问题——芝加哥有多少钢琴调音师?
    算法浅谈——人人皆知却很多人写不对的二分法
  • 原文地址:https://www.cnblogs.com/kay/p/1566805.html
Copyright © 2020-2023  润新知