虽然以前已经学了很多的拦截器,但是在这里还是想重头梳理一下所有有关拦截器的知识,尤其是struts2中的拦截器
1:拦截器是什么?
java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西。
Struts2中的很多功能都是由拦截器完成的。比如:servletConfig,staticParam,params,modelDriven等等。
是AOP编程思想的一种应用形式。
2:执行顺序:
在struts2中,从服务器接受到用户请求开始,struts2的拦截器filter就将其产生的action进行拦截,根据配置文件struts.xml进行适配放行,去寻找action对应的Java的class,根据其返回值,返回到不同的jsp页面,但值得注意的是,拦截器是在服务器启动便加载了,并不是用到才加载,我们需要做的就是对struts.xml进行配置,将产生的请求动作配置到合适的动作类即可
3:自定义拦截器
1:自定义拦截器四步如下:
1>.添加一个类,让它继承AbstractInterceptor类,或者实现Interceptor接口
public class TimeInterceptor extends AbstractInterceptor {
/**
* 拦截器的核心方法intercept的返回值是一个字符串
*/
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
return "login";
}
}
2>.在struts.xml的package中添加interceptors子节点,并在它下面添加Interceptor节点
<package name="goods" namespace="/goods" extends="common-pkg">
<interceptors>
<interceptor name="timeInterceptor" class="com.wskj.struts2.interceptor.TimeInterceptor"></interceptor>
</interceptors>
</package>
3>.在想被拦截的action节点下添加子节点interceptor-ref
<action name="list_Category" class="com.wskj.struts2.controller.CategoryAction" method="list">
<interceptor-ref name="timeInterceptor"></interceptor-ref>
<result name="list" type="dispatcher">/pages/Category/list.jsp</result>
</action>
3.配置默认的拦截器
<!-- 设置默认的拦截器 -->
<default-interceptor-ref name="timeInterceptor"></default-interceptor-ref>
2:在我们自己写拦截器之前首先要清楚,当我们自己写了拦截器时,struts2默认的拦截器就不再起作用了,但是我们还是需要struts2的大部分的拦截器,这个时候怎么办呐?以检查登陆为例渐进性的谈谈这个问题:
a、把默认拦截器加入到配置文件中
b、a中暴露的问题:当有多个拦截器时,需要改写的地方非常多。
解决办法:抽取公共的包,把全局配置放入公共包中。
c、b中的问题:还要再每个动作方法中引入拦截器。能不能不写呢?
思路:我们在设置【开发模式】时,覆盖掉了一个default.properties中的常量,能不能把struts-default.xml中的默认拦截器栈的设置给覆盖掉呢?答案是可以的。
解决办法:
d、c中出现的问题:当使用了默认拦截器栈,这时候三个动作login,showIndex和show1Action都将被检查登录的拦截器拦截。
解决办法:
需要通过AbstractInterceptor类的子类入手,通过查看发现,该类还有一个子类是抽象的:
所以我们在自定义拦截器时,还可以继承MethodFilterInterceptor并且重写doIntercept方法。
并且在struts的配置文件中,配置需要拦截哪些方法,和需要放过哪些方法。
e、d中遗留的问题:我们在声明时配置了哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。
解决办法:我们需要在使用拦截器的时候给它注入参数。
经过这些步骤,自定义拦截器就基本完成了!
疑问:b中抽取公共包在进行需要拦截方法的配置即可,与e方法配置和注入相比并不是很麻烦,为什么还要选择e方法呐?