拦截器是拦截Action,与servlet中的filter相似,主要采用配置方式(struts.xml)实现的。
一个拦截器要实现Interceptor接口,其中有三个方法:init, destroy, intercept.
MyInterceptor
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor
{
private String hello;
public String getHello()
{
return hello;
}
public void setHello(String hello)
{
this.hello = hello;
}
public void destroy()
{
System.out.println("destroy");
}
public void init()
{
System.out.println("init");
System.out.println(hello);
}
public String intercept(ActionInvocation invocation) throws Exception
{
System.out.println("intercept");
String result = invocation.invoke(); //如果还有其它拦截器,则调用其它拦截器,若无,则调用Action
System.out.println("finish");
return result;
}
}
struts.xml
定义拦截器
<interceptors>
//配置自定义的拦截器
<interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor">
<param name="hello">world</param> //对myInterceptor里面的hello属性赋初值
</interceptor>
<interceptor name="myInterceptor2" class="com.test.interceptor.MyInterceptor2">
<param name="hello">world</param> //对myInterceptor里面的hello属性赋初值
</interceptor>
<interceptor name="myInterceptor2" class="com.test.interceptor.MyInterceptor3">
</interceptor>
//配置一个拦截器栈
<interceptor-stack name="myStack">
<!--
<interceptor-ref name="myInterceptor"></interceptor-ref> //拦截器会按照此此配置顺序执行
<interceptor-ref name="myInterceptor2"></interceptor-ref>
-->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
还可自定义默认的拦截器,以替换struts默认的拦截器。它会应用到所有的没配置拦截器的action中去。0或1个
<default-interceptor-ref name="myStack"></default-interceptor-ref>
拦截器对谁起作用
<action name="register" class="com.test.action.RegisterAction" method="test">
<result name="success">/success.jsp</result>
<param name="hello">welcome</param> //对上面的初值时行了覆盖
<result name="input">/register2.jsp</result>
<!--
或直接使用拦截器栈,拦截器栈还可引用拦截器栈。
<interceptor-ref name="myInterceptor"></interceptor-ref>
-->
<!--
<interceptor-ref name="myInterceptor3">
<param name="includeMethods">test, execute</param> //表示拦截这两个方法
</interceptor-ref>
-->
<interceptor-ref name="myInterceptor3">
<param name="excludeMethods">test, execute</param> //表示不拦截这两个方法
</interceptor-ref>
//或一个拦截器中同时含有includeMethods和excludeMethods,则includeMethods优先。
</action>
本来在register提交时若发生错误,应回到自身页面,但配置了此拦截器,则会跳到success页面。
多个拦截器可以构成一个拦截器栈。
因为在struts.xml中的<packge name="struts2" extends="struts-default">继承了struts-default.xml
struts-default.xml中已经定义好了许多的拦截器,并有一个默认的拦截器栈。
当我们在一个action中配置了一个自定义的拦截器栈后,struts-default.xml中的默认拦截器栈就不起作用了。
解决方法:手动的再将struts-default.xml中的默认拦截器栈导入。
大部分情况下,自定义的拦截器会extends AbstractInterceptor 而不去实现Interceptor
AbstractInterceptor实现了Interceptor,并重写了INterceptor中的init() 与 destory(),方法体什么都不做,
并且把intercept()重写为抽象的方法,让继承者去重写。因此extends AbstractInterceptor只须重写intercept()即可。
MyInterceptor2
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor2 extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("intercept2"); //执行目标之前做什么
String result = invocation.invoke(); //执行下一个拦截器或action
System.out.println("finish2"); //执行之后做什么
return result;
}
}
拦截器的嵌套类似于(())的嵌套,出口顺序与入口顺序相反。
以上的拦截器是对action的拦截,即对action中的可调用方法都进行拦截。
而MethodFilterInterceptor可具体到action中的某个方法,更加细粒度。
它也继承了AbstractInterceptor,并将intercept()重写了,但intercept()中又调用了
抽象的doIntercept()因此,我们只要继承它并重写doIntercept()即可。
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class MyInterceptor3 extends MethodFilterInterceptor {
@Override
public void init() {
System.out.println("init3");
}
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
System.out.println("my interceptor3");
String result = invocation.invoke();
return result;
}
}