zoukankan      html  css  js  c++  java
  • 九、Struts2之拦截器


    一、拦截器介绍


    拦截器是Struts2最重要的组成部分,因为Struts2的大部分操作都是通过他完成的,以下列举了一些内建拦截器:

    (1)params :拦截HTTP请求参数,并完成类型转换

    (2)fileUpload:文件上传拦截器;

    (3)conversionError:处理类型转换错误的拦截器;

    (4)exception:处理异常的拦截器,因此在execute方法中,才可以安心抛出异常;

    (5)i18n:处理国际化拦截器;

    (6)static-params:用于在struts.xml中注入action属性值;

    (7)validation:在xml文件中配置的输入校验拦截器;

    (8)workflow:处理手动校验的拦截器

    以上内建拦截器都在struts2-core-Xxx.jar\struts-default.xml中定义,因此在定义<package>时需要填写 extends="struts-default",这样能够自动继承这些拦截器;

    而我们还可以自己定义拦截器,不过注意,如果配置了自定义拦截器,则会让内建拦截器消失,因此我们必须要显式地引用内建拦截器,如下 <interceptor name="defaultStack"/>;

    Struts2通过可插拔设计,可以添加、删除任意拦截器,非常灵活;


    拦截器&拦截器栈


    拦截器栈是由多个拦截器构成的,在使用时可以把他当作一个“大一点的拦截器”,除了定义不同,使用起来是相同的;

    拦截器栈应用:多个拦截器同时使用时,方便管理;

    拦截器栈

        拦截器1

        拦截器2

        拦截器3

    拦截器的使用:拦截器配置在<action>中,即为某个Action配置一个或多个拦截器, 即执行Action方法之前会被拦截器拦截,并执行拦截器方法;


    二、自定义拦截器

    1.配置自定义拦截器和拦截器栈

    定义拦截器或拦截器栈的根元素为<interceptors>,而此元素是<package>的子元素;


    (1)定义拦截器:<interceptors>的子元素

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

    注:如果需要传入参数,则表示拦截器类属性的默认值;

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

    (2)引用拦截器:<action>或<interceptor-stack>的子元素

    如果是<action>的子元素,则表示在action中配置一个拦截器;

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

    注:如果需要传入参数,则表示使用拦截器时类属性的值,将覆盖定义拦截器时传入的参数;

    <interceptor-ref name="拦截器名">
        <param name="name">value</param>
    </interceptor-ref>

    (3)定义拦截器栈:<interceptors>的子元素

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

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

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

    </interceptor-stack>

    (4)引用拦截器栈:<action>的子元素

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

    注:这里传递参数方法比较特殊,因为拦截器栈中有多个拦截器,因此必须以如下形式执行参数:

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

    <param name="interceptorName.attrName">value</param>

    </interceptor-ref>

    (5)定义默认拦截器:<package>的子元素

    <default-interceptor-ref name="拦截器或拦截器栈名"/>

    注:可以在此处传入参数:

    <default-interceptor-ref name="默认拦截器名">

        <param name="name">value</param>

    </default-interceptor-ref>

    默认拦截器使用时机:当action中没有显式地引用拦截器,则会使用默认拦截器;

    2.定义拦截器类

    实现Interceptor接口,并实现方法:

    (1)public void init();        //初始化,一般为空

    (2)public void destroy();        //销毁,一般为空

    (3)public String interceptor(ActionInvocation invocation)throws Exception;    //实现拦截功能,返回值为execute方法返回值;

    String result = invocation.invoke()即可调用拦截器拦截的Action的execute()方法,并返回逻辑视图;
    public String interceptor(ActionInvocation invocation)throws Exception{

            //调用execute()方法之前

            String result = invocation.invoke();

            //调用execute()方法之后

            return result;

    注意:

    (1)在使用自定义拦截器时,会丢失默认内建拦截器,因此需要显式引用默认拦截器栈:<interceptor-ref name="defaultStack"/>

    (2)如果在一个Action中配置了两个拦截器,则如果拦截器A在拦截器B之前引用,即:

    <action>

    <interceptor-ref name="A"/>

    <interceptor-ref name="B"/>

    </action>

    则虽然在两个拦截器中都调用了invocation.invoke(),但是只会执行一遍Action方法;Action方法执行之前,拦截器A比拦截器B先执行;Action方法执行之后,则拦截器B比拦截器A先执行;

    即结果为:

     A拦截器语句

    B拦截器语句

    execute

    B拦截器语句

    A拦截器语句


    代码实例:


    HelloAction.java


    package org.xiazdong.action;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class HelloAction extends ActionSupport {
    	public String execute()throws Exception{
    		System.out.println("execute...");
    		return SUCCESS;
    		
    	}
    }
    


    Interceptor01.java


    package org.xiazdong.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    
    public class Interceptor01 implements Interceptor {
    	private String name;
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	@Override
    	public void destroy() {
    	}
    	@Override
    	public void init() {
    	}
    	@Override
    	public String intercept(ActionInvocation invocation) throws Exception {
    		System.out.println("name属性:"+name);
    		System.out.println("execute方法之前...");
    		String result = invocation.invoke();
    		System.out.println("execute方法之后...");
    		return result;
    	}
    }


    struts.xml


    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
    	<constant name="struts.devMode" value="true" />
    	<package name="default" namespace="/" extends="struts-default">
    		<interceptors>
    			<interceptor name="interceptor01" class="org.xiazdong.interceptor.Interceptor01">
    				<param name="name">xiazdong</param>
    			</interceptor>
    			<interceptor-stack name="stack">
    				<interceptor-ref name="defaultStack"></interceptor-ref>
    				<interceptor-ref name="interceptor01"></interceptor-ref>
    			</interceptor-stack>
    		</interceptors>
    		<action name="hello" class="org.xiazdong.action.HelloAction">
    			<interceptor-ref name="stack"></interceptor-ref>
    			<result>/index.jsp</result>
    		</action>
    	</package>
    </struts>
    

    3.方法过滤


    默认自定义拦截器将会拦截Action的所有方法,比如在Action中定义了login()方法、regist()方法,则默认会拦截两个方法,如果只想拦截login()方法,则需要通过如下步骤实现过滤:

    (1)继承 MethodFilterInterceptor类;

    (2)重写public String doIntercept(ActionInvocation invocation)throws Exception;此方法和intercept方法功能一致,只是名字不一样;

    (3)在struts.xml中配置参数进行过滤:在<interceptor-ref>的子元素中设置:

    <param name="excludeMethods">不过滤的方法1,不过滤的方法2</param>、<param name="includeMethods">需要过滤的方法</param>


    注意:如果一个方法在includeMethods和excludeMethods参数中同时列出,则还是会被拦截;


    代码实例:

    如果Action中提供了login()、regist()方法,则struts.xml中如下配置,可以实现login()不被拦截器拦截:

    struts.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    
    <struts>
    
    	<constant name="struts.devMode" value="true" />
    
    	<package name="default" namespace="/" extends="struts-default">
    
    		<interceptors>
    			<interceptor name="interceptor01"
    				class="org.xiazdong.interceptor.Interceptor01">
    				<param name="name">xiazdong</param>
    			</interceptor>
    			<interceptor-stack name="stack">
    				<interceptor-ref name="defaultStack">
    
    				</interceptor-ref>
    				<interceptor-ref name="interceptor01">
    					<param name="excludeMethods">login</param>
    				</interceptor-ref>
    			</interceptor-stack>
    		</interceptors>
    		<action name="hello" class="org.xiazdong.action.HelloAction">
    			<interceptor-ref name="stack"></interceptor-ref>
    			<result>/index.jsp</result>
    		</action>
    	</package>
    </struts>
    


    补充:PreResultListener应用


    在Action的介绍中也介绍过这个类,是用于在Action方法执行之后、转入物理视图之前被调用;
    这个类也可以在拦截器类中被添加,则只要应用该拦截器的action都会起作用,步骤如下:
    (1)定义MyPreResultListener:
    public class MyPreResultListener implements PreResultListener{
    public void beforeResult(ActionInvocation invocation,String resultCode);
    }
    (2)在intercept方法中添加invocation.addPreResultListener(new MyPreResultListener());
    即可;

    代码:

    MyPreResultListener.java
    package org.xiazdong.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.PreResultListener;
    
    public class MyPreResultListener implements PreResultListener {
    
    	@Override
    	public void beforeResult(ActionInvocation arg0, String arg1) {
    		System.out.println("beforeResult...");
    	}
    
    }
    

    Interceptor01.java

    package org.xiazdong.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
    
    public class Interceptor01 extends MethodFilterInterceptor{
    
    	@Override
    	public String doIntercept(ActionInvocation invocation) throws Exception {
    		
    		invocation.addPreResultListener(new MyPreResultListener());
    		System.out.println("execute1方法之前...");
    		String result = invocation.invoke();
    		System.out.println("execute1方法之后...");
    		return result;
    	}
    }
    

    结果如下:

     execute1方法之前...
    regist...
    beforeResult...
    execute1方法之后...

    可以看出,此方法在Action方法一执行完就触发PreResultListener,比拦截器先执行;




    最后配上一张图作为结尾:








    作者:xiazdong
    出处:http://blog.xiazdong.info
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    day10_发送邮件终极版
    day10_发送带附件的邮件
    day10_发送普通邮件
    day10_多线程性能测试
    day10_虚拟环境和搭建测试环境的步骤
    codeforces 877B
    codeforces 982C Cut 'em all! (dfs)
    洛谷P1171 售货员的难题 dp
    点集配对问题
    codeforces 891A Pride (数学)
  • 原文地址:https://www.cnblogs.com/xiazdong/p/3058080.html
Copyright © 2011-2022 走看看