Struts2内建拦截器
Strus2框架内建了大量的拦截器完成了框架几乎70%的工作,比如,params拦截器将HTTP请求中的参数解析出来,设置成Action的属性;servlet-config拦截器直接将HTTP请求中的HttpServletRequest实例和HttpServletResponse实例传给Action;fileUpload拦截器负责解析请求参数中的文件域,并将一个文件域设置成Action的3个属性...
由于默认的struts拦截器栈中定义了许多框架的常用操作,且若Action中使用了自定义拦截器,struts-default包中定义的defaultStack将不起作用,从而无法完成HTTP参数映射到Action各属性的过程,因此大部分情况下,为某个Action指定了相应的拦截器后,组合使用多个拦截器/拦截器栈,或者自定义一个拦截器栈,其中包含对defaultStack的引用。
3.拦截器的实现原理
定义接口
public interface Dog { public void info(); public void run();
定义接口实现类
public class DogImpl implements Dog{ public void info() { ... } public void run(){ ... } }
系统拦截器类
public class DogIntercepter { public void method1(){} public void method2(){} }
上面只是些普通的JAVA类,实现拦截器功能关键是下面的代理类
public class ProxyHandler implemtsInvocationHandler { private Objecttarget;//需被代理的目标对象 //创建拦截器实例 DogIntercepter di = newDogIntercepter(); //执行代理的目标方法时,该Invoke方法会被自动调用 public Object invoke(Object proxy, Methodmethod, Object[] args) { Objectresult = null; if(method.getName().equals("info"){ di.methord1(); result =method.invoke(tart,args); di.method2(); } else { result =methos.invoke(target,args); } return result; } public void setTarget(Objecto){ this.target=o; } }
代理工厂类
public class MYProxyFactory{ public static Object getProxy(Objectobject){ ProxyHandler handler = newProxyHandler(); handler.setTarget(object); return Proxy.newProxyInstance(Dogimpl.class.getClassLoader(),object.getClass().getInterfaces(),handler); } }
主程序
public class Test{ public static void main(String[]args){ Dog targetObject = newDogImpl(); Dog dog = null; //以目标对象创建代理 Object proxy =MyProxyFactory.getProxy(targetObject); if(proxy instance of Dog) { dog=(Dog)proxy; } dog.info(); dog.run(); } }
上例通过JDK动态代理,在执行目标方法之前调用拦截器方法一,在执行目标方法之后调用拦截器方法二。
4. 拦截器及拦截器栈的配置
在Struts.xml中配置拦截器
<interceptor name="name"class="class"/>
还可以指定拦截器参数
<interceptor name="name"class="class">
<param name="param name">…</param>
</interceptor>
在Struts.xml中配置拦截器栈
拦截器栈是由多个拦截器组成的,即一个拦截器栈包含了多个拦截器。
<interceptor-stack name="stackname">
<interceptor-ref name="interceptor 1"/>
<interceptor-ref name="interceptor 2"/>
<interceptor-ref name="interceptor stack 1"/>
</interceptor>
提示:一个包中所有的拦截器都应定义在<interceptors…/>元素中
5. 拦截器及拦截器栈的使用
通过<interceptor-ref…/>元素来使用拦截器和拦截器栈。下面是在Action中定义拦截器的配置示例:
<action name="..." ...> ...... <!-- interceptor 1--> <interceptor-refname="int1"/> <!--interceptor 2 --> <interceptor-refname="int2"> <param name="...">...</param> </nterceptor-ref> </action>
7.使用自定义拦截器
实现拦截器类
如果用户要开发自己的拦截器类,有如下两种方式:
实现com.opensymphony.xwork2.interceptor.Interceptor接口
继承AbstractInterceptor类
Interceptor定义如下:
public interface Interceptor extendsSerializable {
/**
* Called to let an interceptor clean up any resources it has allocated.
*/
void destroy();
/**
* Called after an interceptor is created, but before any requests areprocessed using
* {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept}, giving
* the Interceptor a chance to initialize any needed resources.
*/
void init();
/**
* Allows the Interceptor to do some processing on the request beforeand/or after the rest of the processing of the
* request by the {@link ActionInvocation} or to short-circuit theprocessing and just return a String return code.
*
* @param invocation the action invocation
* @return the return code, either returned from {@linkActionInvocation#invoke()}, or from the interceptor itself.
* @throws Exception any system-level error, as defined in {@linkcom.opensymphony.xwork2.Action#execute()}.
*/
String intercept(ActionInvocation invocation) throws Exception;
}
我们的拦截器必须重写Interceptor接口中的intercept方法,该方法有一个ActionInvocation的参数,该参数实例可以用于获得被拦截的Action实例。
MyAction action =(MyAction)invocation.getAction();
一旦获得了Action实例,几乎获得了Action的全部控制权:
可以实现将HTTP请求参数解析出来,设置成Action的属性(这是系统拦截器干的事情)
可以直接将HTTP请求中的HttpServletRequest实例和HttpServletResponse实例传给Action(这是servlet-config拦截器干的事情)
…..
下面是个自定义拦截器类的例子
拦截器类
importcom.jj.test.redirect.RedirectTest;
importcom.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extendsAbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
RedirectTest action = (RedirectTest)invocation.getAction();
System.out.println(action.getTarget());
System.out.println("Start------");
long start = System.currentTimeMillis();
//执行Action的exceute方法
String result = invocation.invoke();
long end = System.currentTimeMillis();
System.out.println("End------"+(end-start));
return result;
}
}
ActionInvocation 类常用方法
getAction方法 -获取Action实例
getInvocationContext方法 - 获取ActionContext实例
invoke方法 - 执行该拦截器的后一个拦截器,或者直接执行Action的execute方法
在intercept方法中获取Session
ActionContext ctx =invocation.getInvocationContext();
Map session = ctx.getSession();
struts.xml中的配置
<package name="redir"namespace="/redir" extends="struts-default"> <interceptors> <interceptor name="MyInterceptor"class="com.jj.test.interceptor.MyInterceptor"></interceptor> </interceptors> <default-interceptor-refname="MyInterceptor"/> <action name="RedirTest"class="com.jj.test.redirect.RedirectTest"> <result name="SUCCESS"type="dispatcher">/${target}.jsp</result> </action> </package>