拦截器:
在谈拦截器之前,我觉得有必要提一下和过滤器的区别。
1. 首先拦截器是Struts2自己的,只有用了Struts2框架才可以使用拦截器,而过滤器是servlet规范中的一部分,任何java web工程都可以使用;
2. 其次拦截器只可以拦截Action,而过滤器理论上可以拦截任何东西(jsp,html,css,image或者js等)。
拦截器配置(在Struts2.xml中进行):
1 <package name="default" extends="struts-default"> 2 ....... 3 <!-- 首先得声明一个拦截器,名字随便,类名是你自己编写的拦截器类的路径 --> 4 <interceptors> 5 <interceptor name="priceInterceptor" class="interceptor.priceInterceptor"></interceptor> 6 </interceptors> 7 ....... 8 <!-- 然后在某一action中使用这个拦截器 --> 9 <action name="updateBook" class="action.BookAction" method="update"> 10 <!-- 不仅要调用自己定义的拦截器,系统默认的拦截器也需要手动调用 --> 11 <interceptor-ref name="defaultStack"></interceptor-ref> 12 <interceptor-ref name="priceInterceptor"></interceptor-ref> 13 <result name="success">/updateBook.jsp</result> 14 <result name="error">/updateBook.jsp</result> 15 </action> 16 </package>
当有请求Action时,拦截器链(存放的是一系列的拦截器)就会进行拦截,拦截的流程是这样:顺序执行拦截器,每到一个拦截器都会找到该拦截器对应的类,并实例化这个类,然后执行类中的intercept方法(这个方法里面存放的是拦截逻辑),如果通过了,就会执行下一个拦截器,直到通过整个拦截器链,最后才会执行action方法。
1 return arg0.invoke();
上面这行代码就是 通过了当前的拦截器,去执行下一个拦截器的代码(在intercept方法中)。
这里提一下为什么要有下面这行代码:因为如果你自己不定义拦截器,他并不是没有拦截器了,还存在系统默认的拦截器,当你没有自己定义拦截器时,这些默认的拦截器会在你请求时自动调用,但是当你自己定义了拦截器,并且在某一个action中调用了这个拦截器,那么这个action并不会自动调用系统默认的拦截器,需要你手动调用。
1 <interceptor-ref name="defaultStack"></interceptor-ref>
当然这个调用的顺序也有讲究:
一般是先调用这个默认的拦截器,然后再调用自己的拦截器,因为顺序如果改变可能会造成很大的影响(除非你的功能就要求那样)。struts2里面有很多已经组合好的拦截器栈,这些拦截器栈里面的拦截器的顺序是精心设计的。举个例子,假如你现在自己定义了一个验证输入内容的拦截器。如果你在加拦截器栈的时候把defaultStack放在了后面,那么你可能无法验证传进的参数。原因是,defaultStack里面有一个叫params的拦截器,这个拦截器是用来将你传进来的参数封装到action中的对象中的,所以你如果在你的验证拦截器中写验证封装到这个对象中的参数时你会得到空值,因为还没有封装进来。defaultStack里面还有很多有用的拦截器,总之把这个拦截器放在你定义的拦截器的前面会比较好
下面是我的工程下默认的拦截器:
1 <interceptor-stack name="defaultStack"> 2 <interceptor-ref name="exception"/> 3 <interceptor-ref name="alias"/> 4 <interceptor-ref name="servletConfig"/> 5 <interceptor-ref name="i18n"/> 6 <interceptor-ref name="prepare"/> 7 <interceptor-ref name="chain"/> 8 <interceptor-ref name="scopedModelDriven"/> 9 <interceptor-ref name="modelDriven"/> 10 <interceptor-ref name="fileUpload"/> 11 <interceptor-ref name="checkbox"/> 12 <interceptor-ref name="multiselect"/> 13 <interceptor-ref name="staticParams"/> 14 <interceptor-ref name="actionMappingParams"/> 15 <interceptor-ref name="params"> 16 <param name="excludeParams">dojo..*,^struts..*</param> 17 </interceptor-ref> 18 <interceptor-ref name="conversionError"/> 19 <interceptor-ref name="validation"> 20 <param name="excludeMethods">input,back,cancel,browse</param> 21 </interceptor-ref> 22 <interceptor-ref name="workflow"> 23 <param name="excludeMethods">input,back,cancel,browse</param> 24 </interceptor-ref> 25 <interceptor-ref name="debugging"/> 26 </interceptor-stack>
好,拦截器的配置讲完了,下面来看看拦截器的3种创建方式:(可能这部分提到拦截器的配置前面讲更好)
这里的3种创建方式也就是3中编写拦截器对应类的方法。
1. 实现拦截器接口 Interceptor
该接口中有3个方法init,intercept,destory,我们只需要把我们的拦截逻辑写进intercept中去就行了;
2.继承抽象类 AbstractInterceptor
我们只需要重写intercept就行了,因为AbstractInterceptor帮我们实现了Interceptor接口中的init()、destory()方法;
3.继承抽象类MethodFilterInterceptor
我们需要重写doIntercept方法,
这种是我们常用的方式(推荐大家也用这种方式来创建),因为这种创建方式有个很大的优点,就是可以指定action中拦截的方法(通俗的讲就是该拦截的拦截,不该拦截的不拦截),下面举个例子:
1 <action name="updateBook" class="action.BookAction" method="update"> 2 <interceptor-ref name="defaultStack"></interceptor-ref> 3 <interceptor-ref name="priceInterceptor"> 4 <!-- 在这里加上不拦截的方法 --> 5 <param name="这个随意1">方法名1</param> 6 <param name="这个随意2">方法名2</param> 7 </interceptor-ref> 8 <result name="success">/updateBook.jsp</result> 9 <result name="error">/updateBook.jsp</result> 10 </action>
拦截器的配置与创建都讲完了,希望对你有所帮助!