不知道读者;有没有发现,在struts2中的核心Action中,环绕在Action周围的一直是拦截器这个东西,不错,拦截器的使用是Struts2的核心中的核心;Struts2 Action的设计被分为四层:拦截器、Action、PreResultListener和Result;
我们先讲讲这些层次的工作原理,你的请求被拦截器拿下之后,一般你的Action继承了ActionSupport并且使用的是默认包,所以你的请求会被Struts2内置的拦截器所操纵,会进行我们前面所说的类型转化和校验;稍等,我们会使用一个自定义的拦截器来体验拦截器的工作原理;等到拦截完成之后,会将结果给Action,在等到Action完成之后,一般情况下,会直接交给Result去显示;但是如果你需要在Action返回结果之前再次添加一些操作,就需要配置一个监听器,然后使用PreResultListener在这个类中去添加;然后再将结果交给Result;
这里我需要说明一下:struts2的拦截器的能力是,在Action周围环绕;作用主要是请求交给Action前和请求被Action处理之后的拦截,它只能拦截处理之后的结果,并不能像上面PreResultListener监听器那样可以改变Action的处理结果;
用简单的代码先说明一下,拦截器拦截Action处理结果和使用监听器改变Action的处理结果的区别:
1、拦截器拦截Action的处理结果:
public String intercept(ActionInvocation arg0) throws Exception {
System.out.println("output from myInterceptor----before action");
String result=arg0.invoke();//一旦调用Action,返回的结果,拦截器是不能改变的
System.out.println("output from myInterceptor----after action");
return result;
}
这个是拦截器的核心代码;我们可以看到,拦截器是在Action处理前后添加一些额外的业务逻辑;对Action的结果并不能改变;
2、使用监听器改变Action的处理结果:
public String execute() {
ActionInvocation invitation = ActionContext.getContext().getActionInvocation();
invitation.addPreResultListener(new PreResultListener() {
@Override
publicvoid beforeResult(ActionInvocation invitation, String resultCode) {
System.out.println(resultCode);
invitation.getInvocationContext().put("extra", new Date() + resultCode+"转入");
}
});
if ("randy".equals(getUsername()) && "jin".equals(getPassword())) {
ActionContext.getContext().getSession().put("user", username);
return SUCCESS;
}
return LOGIN;
}
这段代码是拷贝别人的,我们大致可以明白,正常情况下Action处理的结果的字符串是一个固定的;然而使用了监听器后,被Action处理之后的结果,显然无关紧要了,真正的结果在这里还会真正的传递至Result;
上面对Action处理结果的处理不同,做了介绍;下面介绍拦截器的工作原理;其核心代码正如上面所述的intercept(ActionInvocation arg0) 这个方法,还有就是拦截器必备的init和destory方法;你只需要实现Interceptor或者继承AbstractInterceptor便可以完成自定义的拦截器,当然你需要在struts.xml中注册并且调用你的拦截器,代码类似于:
<struts>
<!--定义-->
<package name="my" extends="struts-default">
<interceptors>
<interceptor name="myAuthority" class="nyist.interceptor.MyAuthority"></interceptor>
</interceptors>
<action name="Login" class="nyist.action.LoginAction">
<result>/welcome.jsp</result>
<result name="error">/error.jsp</result>
</action>
<action name="Inner">
<result>/WEB-INF/inner_jsps/MyJsp.jsp</result>
<result name="error">/WEB-INF/inner_jsps/error.jsp</result>
<!--调用-->
<interceptor-ref name="myAuthority"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>
红色的代码,不需要我在多说了吧;有了这些,你的拦截器便会起作用了,你可以随意添加新的业务逻辑在Action周围;
简单分析拦截器的的核心方法intercept(ActionInvocation arg0) :
对invoke有所了解的,就会知道这是责任链模式的使用,这个方法便是完成你一系列拦截器栈的调用直到你的拦截器调用完为止,再去调用Action;