`

Struts2拦截器

 
阅读更多

拦截器:AOPAspect-Oriented Programming)中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作。拦截器是AOP的一种实现策略。

 

拦截器链:(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

 

拦截器的实现原理:拦截器方法都是通过代理的方式来调用的。Struts 2的拦截器实现相对简单。当请求到达Struts 2ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。

 

Struts2的拦截器
struts-default.xml中定义了很多拦截器,这些拦截器就是用来完成许多强劲功能的保证,而且可以根据已定义的若干拦截器中的某几个拦截器构建成interceptor-stack拦截器栈,其实拦截器栈还可以由拦截器栈组成。即从Struts2高层的角度来看,二者没有什么区别。我们可以在<package/>中增加这样一行<default-interceptor-ref name="拦截器的名字"/>:即表示将该拦截器作为整个包的默认拦截器,它会自动附加到我们的每一个Action中,
并且在一个<package/>中只能使用<default-interceptor-ref/>定义一个默认的拦截器。
<action/>没有引用任何一个拦截器,那么默认的defaultStack会自动附加到<action/>
<action/>手工引用任何一个拦截器,那么默认的defaultStack就不会附加到<action/>
若还想使用默认拦截器,则只能再通过手工方式导入
<interceptor-ref name="defaultStack"/>
如果没有引用Struts2的默认拦截器,那么就会影响到整体的输入校验即其它的一些功能
Struts2拦截器的配置和使用都很easy,这得益于其底层的良好架构以及它的AOP的思想,该拦截器即标准的
AOP思想,代码不写死到Action里,而是根据配置灵活附加到Action中。使用上,Struts2拦截器并不复杂。但实现上,是很复杂的,其底层用到了动态代理的机制。

 

Struts2常用的内置拦截器
alias:实现不同请求中相似参数别名的转换
autowiring:自动装配。主要用于Struts2和Spring整合时,Struts2可以使用自动装配的方式访问Spring容器中的Bean
chain:构建一个Action链,使当前Action可以访问前一个Action的属性。一般与<result type="chain"….../>一起使用
conversionError:处理类型转换错误。负责将类型转换错误从ActionContext中取出,并转换成Action的FieldError错误
createSession:负责创建一个HttpSession对象,主要用于那些需要提供HttpSession对象才能正常工作的拦截器中
debugging:当使用Struts2的开发模式时,该拦截器会提供更多的调试信息
execAndWait:后台执行Action,负责将等待画面发送给用户
exception:负责处理异常。它会将异常映射为结果
fileUpload:用于文件上传。负责解析表单中文件域的内容
i18n:支持国际化。它负责把所选的语言和区域放入用户Session
logger:负责日志记录。主要是输出Action的名字
modelDriven:用于模型驱动。当Action实现了ModelDriven接口时,它负责把getModel()方法的结果推入ValueStack中
scopedModelDriven:若Action实现ScopedModelDriven接口,它负责从指定生存范围中找出指定Model,并通过setModel()将该Model传给Action实例
params:最基本的一个拦截器,它负责解析HTTP请求中的参数,并将参数值设置成Action对应的属性值
主要用于在提交表单后,将表单中的参数自动赋值到Action的属性中
prepare:如果Action实现了Preparable接口,将会调用该拦截器的prepare()方法
staticParams:负责将XML中<action/>标签下<param/>标签中的参数传入Action
scope:范围转换拦截器,可以将Action状态信息保存到HttpSession范围或ServletContext范围内
servletConfig:如果某个Action需要直接访问Servlet API,就是通过该拦截器实现的
用于将HTTP请求中的HttpServletRequestHttpServletResponse对象传递给Action对象
roles:JAAS拦截器。Java授权和认证服务Java Authentication and Authorization Service
只有当浏览者取得合适的授权后,才可以调用被该拦截器拦截的Action
timer:负责输出Action的执行时间。它在分析Action的性能瓶颈时比较有用
token:阻止表单重复提交。它检查传到Action中的token,从而防止多次提交
tokenSession:作用与token基本类似,只是它把token保存在HttpSession
validation:通过执行在XxxAction-validation.xml中定义的校验器,从而完成数据校验
workflow:负责调用Action类的validate()方法。如果校验失败,则返回input逻辑视图

 

struts.xml文件中定义拦截器,拦截器栈:

 

<package name="my" extends="struts-default" namespace="/manage">

        <interceptors>

        <!-- 定义拦截器 -->

        <interceptor name="拦截器名" class="拦截器实现类"/>

        <!-- 定义拦截器栈 -->

        <interceptor-stack name="拦截器栈名">

             <interceptor-ref name="拦截器一"/>

             <interceptor-ref name="拦截器二"/>

        </interceptor-stack>

        </interceptors>

        ......

</package>

 使用拦截器:一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了。拦截器的拦截行为将会在Actionexceute方法执行之前被执行。

 

<action name="userOpt" class="org.qiujy.web.struts2.action.UserAction">

            <result name="success">/success.jsp</result>

            <result name="error">/error.jsp</result>

              <!-- 使用拦截器,一般配置在result之后, -->

             <!-- 引用系统默认的拦截器 -->
                <interceptor-ref name="拦截器名或拦截器栈名"/>

                <interceptor-ref name="defaultStack"/>

            

</action>

 

此处需要注意的是,如果为Action指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,所以上面配置文件中手动引入了默认拦截器。


自定义拦截器

作为“框架(framework)”,可扩展性是不可或缺的。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。

 

(1)实现拦截器类:

所有的Struts 2的拦截器都直接或间接实现接com.opensymphony.xwork2.interceptor.Interceptor。该接口提供了三个方法:

1)void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。

2)void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前,系统将回调该方法。

3)String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。

除此之外,继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor是更简单的一种实现拦截器类的方式,因为此类提供了init()destroy()方法的空实现,这样我们只需要实现intercept方法。

 

(2)使用自定义拦截器:两个步骤:

l通过<interceptor …>元素来定义拦截器。

l通过<interceptor-ref …>元素来使用拦截器

 

(3)使用自定义拦截器的实例:使用自定义拦截器来完成用户权限的控制:当浏览者需要请求执行某个操作时,应用需要先检查浏览者是否登录,以及是否有足够的权限来执行该操作。

AuthorizationInterceptor.java

 

package org.com;

 

import java.util.Map;

 

import com.opensymphony.xwork2.Action;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

 

/**

 * 权限检查拦截器

 * 

 * @author qiujy

 * @version 1.0

 */

public class AuthorizationInterceptor extends AbstractInterceptor {

 

    /*

     * 拦截Action处理的拦截方法

     * 

     */

    public String intercept(ActionInvocation invocation) throws Exception {

        

        Map session = invocation.getInvocationContext().getSession();

        String userName = (String) session.get("userName");

        

        if (null != userName && userName.equals("test")) {

            System.out.println("拦截器:合法用户登录---");

            return invocation.invoke();

        } else {

            System.out.println("拦截器:用户未登录---");

            return Action.LOGIN;

        }

    }

}

 struts.xml

 

<!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="my" extends="struts-default">

        

        <interceptors>

        <!-- 定义权限控制拦截器 -->

        <interceptor name="authority" class="org.com.AuthorizationInterceptor"/>

        </interceptors>

        

        <!-- 定义全局处理结果 -->

        <global-results>

        <!-- 逻辑名为login的结果,映射到/login.jsp页面 -->

        <result name="login">/login.jsp</result>

        </global-results>

        

        <action name="listall" class="org.com.UserAction" method="listAllUser">

            <result name="success">/listall.jsp</result>

            <!-- 使用拦截器 -->

            <interceptor-ref name="defaultStack"/>

            <interceptor-ref name="authority"/>

        </action>

        

        <action name="" class="">

            <result name="success">/success.jsp</result>

        </action>

    </package>

</struts>

 

 如果为了简化struts.xml文件的配置,避免在每个Action重复配置该拦截器,可以将拦截器配置成了一个默认拦截器栈。如下:

<!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="my" extends="struts-default">

 

        <interceptors>

            <!-- 定义权限控制拦截器 -->

            <interceptor name="authority"  class="org.com.AuthorizationInterceptor" />

            <!-- 定义一个包含权限控制的拦截器栈 -->

            <interceptor-stack name="mydefault">

               
                <interceptor-ref name="authority" />
                <interceptor-ref name="defaultStack" />


            </interceptor-stack>

        </interceptors>

        

        <!-- 定义默认拦截器 -->

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

 

        <!-- 定义全局处理结果 -->

        <global-results>

            <!-- 逻辑名为login的结果,映射到/login.jsp页面 -->

            <result name="login">/login.jsp</result>

        </global-results>

 

        <action name="listall"   class="org.com.UserAction"  method="listAllUser">

            <result name="success">/listall.jsp</result>

        </action>


         <action name="listall"   class=""  method="">

            <result name="success">/listall.jsp</result>

        </action>


    </package>

    

    <package name="font" extends="struts-default">

        <action name="" class="">

            <result name="success">/success.jsp</result>

        </action>

    </package>

</struts>

 一旦在某个包下定义了默认拦截器栈,在该包下的所有action都会使用此拦截器栈。对于那些不想使用些拦截器栈的action,则应该将它放置在其它的包下。

 

 

 Struts2的监听器
Struts2还有个的监听器,即com.opensymphony.xwork2.interceptor.PreResultListener接口。该接口中仅定义一个方法,即void beforeResult(ActionInvocation invocation, String resultCode),观察该监听器的名字,就可以知道,Pre就是在...之前的意思,也就是在结果之前进行监听。它的监听点是:在执行完execute()或者自定义的方法之后,真正转到视图资源之前,会自动调用监听器的beforeResult()方法。truts2的这个监听器,平时用到的不是很多
在上传文件时可能会用到,比如在返回到result之后 ,可以修改一下文件的后缀名,等等..

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics