本文主要用于理解掌握Struts2 Intercept的调用过程 及动态代理
前言:Struts2的 拦截器机制实际上是java设计模式中最重要的设计模式------动态代理 ,
它的需求来源如下:
一个class 有具体的 operation(method) ,现在有一个需求是: 要在调用这个方法调用前加上 一些业务(比如打印"Today is saturday ") 在调用方法后加入一些业务逻辑(比如 Tomorrow is sunday ,so we can play)
好,瞬间的思考可以得到如下实现方法
class proxy{
public static void myMetod(){
System.out.println("Today is saturday ");//新加业务逻辑 (前)
System.out.println("we can't play any more"); //原来的业务需要打印的是we can't play any more
System.out.println(" Tomorrow is sunday ,so we can play ");//新加业务逻辑 (后)
}
}
这样虽然也实现了我们想要的效果,但是,这样的代码是高度耦合的,完全不具备重用性,试想下,如果需求变了,现在要在100个方法上加入100个不同的前后调用,这样的代码修改量将会是 100的平方的2倍 ,能不能有一种高效的方法,你给我业务逻辑,我就可以完全重用的实现业务逻辑
AOP 编程, (aspect to programing ) 为此而生。
想要达到的效果如下
AOP 编程, (aspect to programing ) 为此而生。
想要达到的效果如下
class DynamicProxy{
public static void main(String[] arg){
DynamiPproxy dynamicproxy =new
DynamiPproxy(proxy.myMethod(),
beforeMethod(),
AfterMethod()); //第一个参数是原来方法,第二个参数是业务调用前执行方法,第三个参数是业务调用钩执行方法
dynamicproxy.invoke(); //调用
// 这里dynamicproxy就是 原来proxy的一个动态代理,它会根据后面的三个参数生成一个类, 里面有 一个方法, 和上面proxy类中的myMethod方法体一样,然后执行 invoke 方法!
//庆幸的是这一切都有人已经帮我们写好,并出书育人:java设计模式
// 这样我们就可以只修改 参数的具体实现 ,就可以非常解耦的实现我们的AOP需求
}
public void beforeMethod(){
System.out.println("Today is saturday ");//新加业务逻辑 (前)
}
public void before AfterMethod(){
System.out.println(" Tomorrow is sunday ,so we can play ");//新加业务逻辑 (后)
}
}
具体的动态代理实现可以看其他博客
http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html
http://blog.csdn.net/heyutao007/article/details/49738887
我们再来看Struts2的拦截器
![](https://img-my.csdn.net/uploads/201703/25/1490417674_4058.png)
以下是例子
Struts.xml拦截器定义如下
<package name="interceptor" extends="struts-default">
<!-- 定义多个拦截器 -->
<interceptors>
<!-- 定义一个拦截器 -->
<interceptor name="my1" class="com.baizhi.action2.MyInterceptor"></interceptor>
<interceptor name="my2" class="com.baizhi.action2.MyInterceptor2"></interceptor>
<!-- 定义一个拦截器栈 -->
<interceptor-stack name="myStack">
<interceptor-ref name="my2"></interceptor-ref>
<interceptor-ref name="my1"></interceptor-ref>
</interceptor-stack>
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<action name="aAction" class="com.baizhi.action2.AAction">
<interceptor-ref name="myStack"></interceptor-ref>
<result name="success">/index.jsp</result>
</action>
AAction.java
publicclass AAction implements Action{
public String execute() throws Exception { System.out.println("this is AAction!!!");
return"AAction";
}
}
MyInterceptor2.java
publicclassMyInterceptor2implements Interceptor {
publicvoid destroy() {
// TODO Auto-generated method stub
System.out.println("MyInterceptor2 结束");
}
publicvoidinit() {
System.out.println("MyInterceptor2 初始化");
}
public String intercept(ActionInvocation ai) throws Exception {
System.out.println("this is MyInterceptor22222!!");
System.out.println(" MyInterceptor2 ai.invoke()="+ai.invoke()+"ai.getAction()="+ai.getAction());
return"MyInterceptor2";
}
}
MyInterceptor.java
package com.baizhi.action2;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor {
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation ai) throws Exception {
//共有的部分
//1 让程序通过拦截器
System.out.println("this is myinterceptor 1111");
//ai.invoke();
System.out.println(" MyInterceptor2 ai.invoke()="+ai.invoke()+"ai.getAction()="+ai.getAction());
//拦截响应
System.out.println("this is myinterceptor end!!!!");
//2. 通过ai获取值栈对象
/*ValueStack vs = ai.getStack();
vs.setValue("#request.name", "haoge");
System.out.println(vs.findValue("#request.name"));
ValueStack vs = ActionContext.getContext().getValueStack();*/
return "MyInterceptor";
}
}
调用过程
值得注意的是:<default-interceptor-ref>默认拦截器和普通拦截器如果同用一个类,将生成两个代理实例
输出结果
this is MyInterceptor22222!!
this is myinterceptor 1111
this is AAction!!!
MyInterceptor2 ai.invoke()=errorai.getAction()=com.baizhi.action2.AAction@1c0b049a
this is myinterceptor end!!!!
MyInterceptor2 ai.invoke()=MyInterceptorai.getAction()=com.baizhi.action2.AAction@1c0b049a