啊最近由于逃课次数有点多,去上了计算机网络,挺同意老师说的一句话的:“不要只学框架的api,要学习框架的设计,要去想为什么struts有拦截器这种东西,它怎么实现的.....”。然而我并不打算在web开发上多费时间,以后没打算走这一行。所以这篇博客还是以“应用”为主,不讲理论。
拦截器
拦截器是干嘛的?顾名思义,拦截、过滤信息的。比如当jsp页面和action(java)相互传递信息的时候,会经过拦截器,那我们如何自定义拦截器?拦下我们想要的信息?
在Struts2(1)这篇博客的“简单案例”基础上,按惯例先做个很简单的demo引入拦截器,了解拦截器的大致流程。
简单Demo
(1)src下新建一个interceptor包,新建一个helloInterceptor.java拦截器类:
public class helloInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation arg0) throws Exception {
System.out.println("Action执行之前!");
String resultString = arg0.invoke(); //执行hellojava.java这个action
System.out.println("Action执行之后");
return resultString;
}
}
(2)局部修改struts.xml文件:
首先使用<interceptors>标签自定义拦截器helloljq,然后在action中使用<interceptor-ref>表示,当这个action开始工作前后,信息都要经过helloljq这个拦截器。
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="helloljq"
class="interceptor.helloInterceptor"> </interceptor>
</interceptors>
<action name="helloword" class="action.hellojava" method="execute" >
<interceptor-ref name="helloljq"></interceptor-ref>
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
运行 http://localhost:8080/自己的项目名/helloword
结果 就能在后台观察到,拦截器执行的顺序,运行helloword这个action之前,拦截器已经再执行并后台打印输出“action执行前”,当action执行成功,页面跳转后,拦截器输出“action执行后”。由此可见,拦截器可以处理传递前后的信息。
拦截器栈
假如同一个action捆绑了多个拦截器怎么办?它的执行顺序示意图如下:
举例子 比如什么过滤脏话的拦截器A、非法用户拦截器B什么的。
这时候我们就能能使用拦截器栈<interceptor-stack>这个标签,例如:
<package name="default" extends="struts-default">
<!--拦截器栈的声明-->
<interceptors>
<interceptor name="A"
class="interceptor.AInterceptor"> </interceptor>
<interceptor name="B"
class="interceptor.BInterceptor"> </interceptor>
<interceptor-stack name="ABinterceptors">
<interceptor-ref name="A"/>
<interceptor-ref name="B"/>
</interceptor-stack>
</interceptors>
<!--action中的调用-->
<action name="helloword" class="action.hellojava" method="execute" >
<interceptor-ref name="ABinterceptors"></interceptor-ref>
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
它的执行顺序是:先拦截器A再B然后执行helloword这个action,再触发B,接着触发A。
默认拦截器
如果有很多的action都要用同一个拦截器栈,使用标签<default-interceptor-ref>,则我们可以将这个拦截栈变成默认拦截器,action中无需<interceptor-ref>调用该拦截器,action会自动调用默认拦截器,例如:
<package name="default" extends="struts-default">
<!--拦截器栈的声明-->
<interceptors>
<interceptor name="A" class="interceptor.AInterceptor"> </interceptor>
<interceptor name="B" class="interceptor.BInterceptor"> </interceptor>
<interceptor-stack name="ABinterceptors">
<interceptor-ref name="A"/>
<interceptor-ref name="B"/>
</interceptor-stack>
</interceptors>
<!--默认拦截器-->
<default-interceptor-ref name="ABinterceptors"/>
<!--action中的调用-->
<action name="helloword" class="action.hellojava" method="execute" >
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
helloword这个action会自动触发默认拦截器。假如有个action不需要默认拦截器中的拦截器AB,只需要拦截器C的话,则action中直接调用C即可。当action有指定拦截器,即action中定义了其他拦截器引用时,则action将不再使用默认的拦截器,需要使用<interceptor-ref>调用默认拦截器。因此我们自己使用自定义拦截器的时候,为了不出错,最好也指定框架的默认拦截器——<interceptor-ref name="defaultStack"></interceptor-ref>。
【注】如果一个结果在多个Action或者拦截器中使用,就应该将它定义为全局的结果。例如假如每个action返回login时,都跳转到 login.jsp 页面,则需要在<package>标签中添加上:
<global-results>
<result name="login">login.jsp</result>
</global-results>
拦截器传值
一、从用户界面得到数值 (jsp->java)
如果jsp页面是使用表单储存用户的数值的,那么可以用request取得数值,例如在拦截器的java代码中加上:
HttpServletRequest request = ServletActionContext.getRequest();
request.getAttribute("属性名");
二、返回数值给用户界面 (java->jsp)
1、java代码中可以写(灵活处理数值):
利用request返回数值:
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("属性名","被传递的值");
利用session传递数值:
Map session = ActionContext.getContext().getSession();
session.put("属性名", 属性值);
2、struts.xml中可以写(写死的数值)
action标签中可以加上:
<interceptor-ref name="某个被调用的拦截器名">
<param name="name属性">"要被传递的数值"</param>
</interceptor-ref>
jsp页面中可以用EL表达式取到返回的数值。