一、拦截器介绍
拦截器是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参数中同时列出,则还是会被拦截;
代码实例:
<?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都会起作用,步骤如下:
(1)定义MyPreResultListener:
public class MyPreResultListener implements PreResultListener{
public void beforeResult(ActionInvocation invocation,String resultCode);
}
即可;
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方法之后... |
最后配上一张图作为结尾: