Interceptor的初步认识
一个名称 :
AOP(Aspect oriented programming) 面向切面编程
听着这个很神秘,其实不然 简单点说他就是个Interceptor (拦截器)
前两天刚刚学完了Filter(过滤器)被过滤器中的chain.doFilter() 一直搞的晕晕呼呼的,有人说执行了doFilter后返回到Action去,又有人说执行玩doFilter后返回下一个Filter中去,两个观点一直僵持不下。
今天了解了下Interceptor 其中的原理豁然开朗,Interceptor中也有类似doFilter的方法 叫做Invocation.invoke()方法,工作原来和doFilter很相似,暂时先把他们连个执行的原理归为一类。
先上一段代码,来解释Invocation.invoke()方法。
//Interceptor 中的代码//部分来嘛省略,页面传递值的代码省略。。。public String intercept(ActionInvocation invocation) throws Exception {System.out.println("Now in the Interceptor!");System.out.println("Interceptor startup before!");String s = invocation.invoke();System.out.println("Interceptor startup after!");String name = (String)invocation.getInvocationContext().getValueStack().findValue("name");System.out.println("In the Interceptor \t name= "+name);return s;}?
//Action中的代码public class TestAction extends ActionSupport{public String name,password;@Overridepublic String execute() throws Exception {System.out.println("name:"+name+"\tpassword:"+password);return super.execute();}}
来看看结果是什么,红色的标注是Action中执行的结果
==============================================================================
//Tomcat中的结果
Now in the Interceptor!
Interceptor startup before!
//突然发现Invocation.invoke()方法成为程序的分割线,程序跳入Action中了
//这一段是Action 中输出的值
name:1231123password:14213
//好了,在此程序又回到了 interceptor
Interceptor startup after!
In the Interceptor name= 1231123
==============================================================================
好了,到此为止可能还是不明确这个Invocation.invoke()方法执行完成以后是去了Action还是去了哪里。但到此能确定的一点是,程序到Invocation.invoke()这个方法的时候去执行了另一个程序,等到另一个程序执行完成后又回到了这个interceptor。
再上一段代码。
在这做一点说明,以上的代码都不动,只是在FirstInterceptor后面在加上一个Interceptor名字叫做SecondInterceptor。
好了上代码
public class SecondInterceptor implements Interceptor{public void destroy() {}public void init() {}public String intercept(ActionInvocation invocation) throws Exception {System.out.println("**************************************");System.out.println("Now in the SecondInterceptor");System.out.println("SecondInterceptor startup before!");String s = invocation.invoke();System.out.println("SecondInterceptor startup after!");String password = (String)invocation.getInvocationContext().getValueStack().findString("password");System.out.println("SecondInterceptor ---- password:"+password);System.out.println("**************************************");return s;}}
好了,我们再来看看结果。同样红色地方是Action输出的结果
==============================================================================
Now in the Interceptor!
Interceptor startup before!
**************************************
Now in the SecondInterceptor
SecondInterceptor startup before!
name:1231123password:14213
SecondInterceptor startup after!
SecondInterceptor ----? password:14213
**************************************
Interceptor startup after!
In the Interceptor name= 1231123
==============================================================================
结果很有意思,这个不能画图说明问题,很头痛,现在蛮喜欢画图的,要是能画图问题能说明的很清楚。
用文字图来表示吧,尽量清楚点
(忍不下这个编辑器了,每次调好了又变乱了)
?????????????????????????????? ? ? ? ? ?? request
??????????????????????????????????????? ? ??????|
?? 进入Action内部此处略去??? ? ????? |
??????????????????????????? ? ? ? ? FirstInterceptor
?? FirstInterceptor调用 ?? ??? ? ???? |??????????? 输出:
?? ActionInvocation中的 ? ?????????? |?????????????? Now in the Interceptor!
?? invoke()方法?????????????? ? ? ? ??? ? |?????????????? Interceptor startup before!
????????????????????????? ? ? ? ?? ? SecondInterceptor
?? SecondInterceptor调用????????? |??????????? 输出:
?? ActionInvocation中的?????????? ?? |????????????? Now in the SecondInterceptor
?? invoke()方法??????????????? ? ? ? ?? ? |????????? SecondInterceptor startup before!
???????????????????????????????? ? ? ? ? ? Action
???? 执行execute()方法????????? ?? ?? |??????????? 输出:
?????????????????????????????????? ? ? ? ? ?? ? |????????????? name:1231123password:14213?
? (好了在此Interceptor???????? ? ? |
??? 原路返回)???????????????? SecondInterceptor??
??????????????????????????????????????????????? |??????????? 输出:
??????????????????????????????????????????????? |?????? SecondInterceptor startup after!
?????????????????????????????????? ? ? ? ? ? ?? |?????? SecondInterceptor --assword:14213
????????????????????????? ? ? ? ? ? ?? ? FirstInterceptor
??????????????????????????????????????????????? |? ?????????? 输出:
??????????????????????????????????????????????? |?????? Interceptor startup after!
???????????????????????????? ? ? ? ? ? ?? ????? |?????? In the Interceptor name= 1231123
????????????????????????????? ? ? ? ? ? ?? response
?? 好了到此Interceptor执行完了,中间无关的步骤略去,在此就谈Interceptor工作流程。
从上很明显的可以看出Interceptor调用ActionInvocation中的invoke()方法 的时候,就进入了下一个Interceptor中执行,当下一个Interceptor调用ActionInvocation中的invoke()方法的时候,同样也会向下执行,直到Action之前的Interceptor全部执行完成,Action执行后,数据又会按照Interceptor进来的顺序原路返回。
?? 就在这一去一会的路上Interceptor能干很多事情,就对这个Action来说Interceptor完全起到了过滤的作用,可以这么说这个Interceptor就是这个Action的过滤器。
好了话题回到了过滤器上了,之前真论的chain.doFilter()有结果,两个的说法都正确,怎么说了,当只有一个Filter的时候执行chain.doFilter()确实将链条传递到了Action手上,Action得以执行,若不写这个chain.doFilter(),好了这个Filter就太自私了,将链条拿在自己手上,不向下传递,直接导致程序无法执行,程序始终处在等待执行的状态。
要是有多个Filter的时候呢,当一个Filter执行chain.doFilter()的时候是讲这个链条交向下一个Filter手中,直到交到Action手中。
?? 好了Filter和Interceptor的区别就出来了,Filter执行完以后它不会原路返回,而Interceptor调用ActionInvocation中的invoke()方法的时候就会向下执行,最终还会返回这个调用ActionInvocation中的invoke()方法的位置向下执行。
在Filter中一般chain.doFilter()是写在最后确定执行过滤后在执行chain.doFilter(),一去就不再回来了。
好了最后上一段配置文件,方便查看
<struts><package name="user" namespace="/user" extends="struts-default"><interceptors><interceptor name="firstInterceptor" class="com.ibm.test.TestAction"><interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="firstInterceptor"></interceptor-ref><interceptor-ref name="secondInterceptor"></interceptor-ref><result name="success"> /test/success.jsp</result></action></package></struts>
?