6.3自定义的拦截器
6.3.1什么是自定义的拦截器
所谓自定义的拦截器,就是由我们自己定义并实现的拦截器,而不是由Struts2定义好的拦截器。
虽然Struts2的预定义拦截器已经满足了大多数情况的需要。但在有些时候,我们可能会根据项目的实际需要而自定义一些拦截器,来实现一些特别的功能。
比如,我们可能认为Struts2预置的logger拦截器功能比较弱,我们希望在任何一个action运行的时候,都会先打印出所访问的动作类Action,再打印出所有的request参数,最后打印出要跳转到的jsp。这个功能并不影响真正的业务逻辑,但是对调试错误是非常有帮助的,免的我们再手工一一对应和查看。
6.3.2开发自定义拦截器
好了,了解了什么是自定义的拦截器过后,一起来看看究竟如何实现自定义的拦截器。
其实在Struts2里面,要实现自定义的拦截器是非常简单的,只要写一个实现Interceptor接口的类就可以了。
也就是说,所有的拦截器都要实现com.opensymphony.xwork2.interceptor.Interceptor接口,这个接口中定义如下:
java代码:
-
publicinterfaceInterceptorextendsSerializable{
-
voiddestroy();
-
voidinit();
-
Stringintercept(ActionInvocationinvocation)throwsException;
-
}
方法的基本说明如下:
- init方法就类似于构造方法,用于初始化一些相关资源
- destory方法类似于析构方法,用于释放资源
- intercept方法,就是拦截器执行的处理方法,我们要实现的功能主要就写在这个方法里面。
对于intercept方法,再说明几点:
(1)在intercept方法中写“invocation.invoke();”,这句话的意思是继续运行拦截器后续的处理,如果这个拦截器后面还有拦截器,那么会继续运行,一直到运行Action,然后执行Result。
如果intercept方法中没有写“invocation.invoke();”这句话,那就意味着对请求的运行处理到此为止,不再继续向后运行了,换句话说,后续的拦截器和Action就不再执行了。而是在这里返回Result字符串,直接去进行Result处理了。
(2)在“invocation.invoke();”这句话之前写的功能,会在Action运行之前执行
(3)在“invocation.invoke();”这句话之后写的功能,会在Result运行之后执行
(4)intercept方法的返回值就是最终要返回的Result字符串,这个只是在前面没有执行Result的时候才有效,也就是前面没有“invocation.invoke();”这句话的时候,这个返回值就相当于是最终要返回的Result字符串,然后才执行相应的Result处理。
说了这么多,还是来示例一下,看看如何实现自定义的拦截器吧。
1:先来个最简单的,就是在Action运行之前,和Result运行之后输出一点信息,当然,有实际功能需求的时候,就写成实际功能的处理代码了,示例代码如下:
java代码:
-
packagecn.javass.action.action;
-
-
importcom.opensymphony.xwork2.ActionInvocation;
-
importcom.opensymphony.xwork2.interceptor.Interceptor;
-
-
publicclassMyInterceptorimplementsInterceptor{
-
publicvoiddestroy(){
-
System.out.println("MyInterceptor销毁");
-
}
-
publicvoidinit(){
-
System.out.println("MyInterceptor初始化");
-
}
-
-
publicStringintercept(ActionInvocationinvocation)throwsException{
-
System.out.println("在acton执行之前");
-
Stringresult=invocation.invoke();
-
System.out.println("在Result运行之后");
-
-
returnresult;
-
}
-
}
可以看到,这个Interceptor的init方法和destroy方法只是输出了一句信息,它的intercept方法用来执行响应,在“invocation.invoke();”这句话之前和之后分别输出了一句信息。最后返回的result,就是invocation.invoke()的返回值。
2:HelloWorldAction这个类不用修改
3:需要到struts.xml里面配置拦截器的声明和引用,示例如下:
java代码:
-
<packagename="helloworld"extends="struts-default">
-
<interceptors>
-
<interceptorname=“myInterceptor”class="cn.javass.action.action.MyInterceptor"/>
-
</interceptors>
-
-
<actionname="helloworldAction"class="cn.javass.action.action.HelloWorldAction">
-
<resultname="toWelcome">/s2impl/welcome.jsp</result>
-
<interceptor-refname=“myInterceptor”/>
-
<interceptor-refname="defaultStack"/>
-
</action>
-
</package>
在这个<package>元素中,首先声明了一个自定义的拦截器:
java代码:
-
<interceptors>
-
<interceptorname=“myInterceptor”class="cn.javass.action.action.MyInterceptor"/>
-
</interceptors>
然后在<action>中引用了这个拦截器。
4:运行测试一下,后台输出:
java代码:
-
在acton执行之前
-
用户输入的参数为===account=test,password=test,submitFlag=login
-
在Result运行之后
可以看到加粗部分就是在拦截器里输出的信息,它分别运行于Action运行之前和Result运行之后。可能有朋友会说,从这里只看到了Action的运行,并没有看到Result的运行啊,你怎么知道是在Result运行之后呢?
很简单,前面增经做过一个自定义的Result,这里来使用它,这样就可以在里面输出信息,从而看出拦截器、Action和Result运行的顺序了。
5:上一章自定义Result的类MyResult不需要改动
6:修改struts.xml,在里面添加上Result的定义,配置如下:
java代码:
-
<packagename="helloworld"extends="struts-default">
-
<result-types>
-
<result-typename="MyResult"class="cn.javass.action.action.MyResult"default="false"/>
-
</result-types>
-
-
<interceptors>
-
<interceptorname=“myInterceptor”class="cn.javass.action.action.MyInterceptor"/>
-
</interceptors>
-
-
<actionname="helloworldAction"class="cn.javass.action.action.HelloWorldAction">
-
<resultname="toWelcome"type="MyResult">/s2impl/welcome.jsp</result>
-
<interceptor-refname=“myInterceptor”/>
-
<interceptor-refname="defaultStack"/>
-
</action>
-
</package>
7:再次访问登录页面,重新运行测试,后台的输出为:
java代码:
-
在acton执行之前
-
用户输入的参数为===account=test,password=test,submitFlag=login
-
要处理的Result字符串是=toWelcome
-
在Result运行之后
加粗的那句话,就是自定义的Result运行时输出的,你会发现,确实是Result运行完成过后,才运行的自定义拦截器中“invocation.invoke();”这句话后面的输出语句的。
另外一点,你要是细心的话,你会发现,在启动服务器的时候,就会输出如下一句:
这表明,拦截器在启动服务器的时候,就已经初始化好了。
8:要注意,如果自定义拦截器中没有调用“invocation.invoke();”这句话的话,那么就相当于后续的拦截器和Action都不会运行了,而是直接根据拦截器的intercept方法所直接返回的Result字符串,来匹配和运行Result。
首先,要修改拦截器类,去掉“invocation.invoke();”这句话,直接返回一个Result字符串,示例代码如下:
java代码:
-
publicclassMyInterceptorimplementsInterceptor{
-
publicvoiddestroy(){
-
System.out.println("MyInterceptor销毁");
-
}
-
publicvoidinit(){
-
System.out.println("MyInterceptor初始化");
-
}
-
publicStringintercept(ActionInvocationinvocation)throwsException{
-
System.out.println("在acton执行之前");
-
System.out.println("在Result运行之后");
-
return"toWelcome";
-
}
-
}
然后再次运行测试,后台的输出为:
java代码:
-
在acton执行之前
-
在Result运行之后
-
要处理的Result字符串是=toWelcome
也就是说,是先把拦截器的intercept方法执行完成,然后才运行的Result。
6.3.3向拦截器传入参数
为什么要传入参数呢?因为有些时候,同一个拦截器为不同的Action服务的时候,需要根据传入的参数进行处理上的变化。比如说,一个记录日志的拦截器,可以根据配置来决定到底把日志记录在数据库还是文件里面。
可以把这种配置数据作为一个参数,在配置的时候设置值,会自动传入拦截器中。具体做法还是看个示例比较清楚。
1:首先看看在struts.xml中,如何为拦截器设置参数。
java代码:
-
<actionname="helloworldAction"class="cn.javass.action.action.HelloWorldAction">
-
<resultname="toWelcome"type="MyResult">/s2impl/welcome.jsp</result>
-
<interceptor-refname=“myInterceptor”>
-
<paramname="dbOrFile">db</param>
-
</interceptor-ref>
-
<interceptor-refname="defaultStack"/>
-
</action>
在这里,通过<param>子元素来为拦截器注入参数,名称是自定义的,当然要与拦截器里面的属性匹配上。
2:拦截器类要想接到这个参数,就必须定义一个对应的属性,并提供setter方法,示例代码如下:
java代码:
-
publicclassMyInterceptorimplementsInterceptor{
-
privateStringdbOrFile;
-
publicvoidsetDbOrFile(StringdbOrFile){
-
this.dbOrFile=dbOrFile;
-
}
-
publicvoiddestroy(){
-
}
-
publicvoidinit(){
-
}
-
publicStringintercept(ActionInvocationinvocation)throwsException{
-
System.out.println("接到dbOrFile的参数=="+this.dbOrFile);
-
if("db".equalsIgnoreCase(this.dbOrFile)){
-
System.out.println("记录日志到数据库");
-
}else{
-
System.out.println("记录日志到文件");
-
}
-
Stringresult=invocation.invoke();
-
returnresult;
-
}
-
}
注意加粗的部分,名称为dbOrFile的属性以及对应的setter方法。这样,在初始化这个拦截器的时候,Struts2就会反射的调用对应的setter,把在<param>元素中配置的值设置到dbOrFile属性上去。
测试运行,后台输出为:
java代码:
-
接到dbOrFile的参数==db
-
记录日志到数据库
-
用户输入的参数为===account=test,password=test,submitFlag=login
-
要处理的Result字符串是=toWelcome
3:上面是在引用拦截器的时候设置参数,还有另一种方式指定参数。就是在拦截器声明的时候就设置参数,示例配置如下:
java代码:
-
<packagename="helloworld"extends="struts-default">
-
<result-types>
-
<result-typename="MyResult"class="cn.javass.action.action.MyResult"default="false"/>
-
</result-types>
-
-
<interceptors>
-
<interceptorname=“myInterceptor”class="cn.javass.action.action.MyInterceptor">
-
<paramname="dbOrFile">db</param>
-
</interceptor>
-
</interceptors>
-
-
<actionname="helloworldAction"class="cn.javass.action.action.HelloWorldAction">
-
<resultname="toWelcome"type="MyResult">/s2impl/welcome.jsp</result>
-
<interceptor-refname=“myInterceptor”/>
-
<interceptor-refname="defaultStack"/>
-
</action>
-
</package>
去运行测试一下,这种配置方式得到的运行效果和前一种方式是一样的。
4:在<interceptor-ref>元素上注册的参数会覆盖在<interceptor>元素上注册的同名参数。示例配置如下:
java代码:
-
<packagename="helloworld"extends="struts-default">
-
<result-types>
-
<result-typename="MyResult"class="cn.javass.action.action.MyResult"default="false"/>
-
</result-types>
-
-
<interceptors>
-
<interceptorname=“myInterceptor”class="cn.javass.action.action.MyInterceptor">
-
<paramname="dbOrFile">db</param>
-
</interceptor>
-
</interceptors>
-
-
<actionname="helloworldAction"class="cn.javass.action.action.HelloWorldAction">
-
<resultname="toWelcome"type="MyResult">/s2impl/welcome.jsp</result>
-
<interceptor-refname=“myInterceptor”>
-
<paramname="dbOrFile">file</param>
-
</interceptor-ref>
-
<interceptor-refname="defaultStack"/>
-
</action>
-
</package>
再次运行测试,后台输出为:
java代码:
-
接到dbOrFile的参数==file
-
记录日志到文件
-
用户输入的参数为===account=test,password=test,submitFlag=login
-
要处理的Result字符串是=toWelcome
后台输出的是file而不是db,这说明,在声明拦截器的时候定义的参数,被引用拦截器的时候配置的参数覆盖了。
注意:
拦截器是无状态的,不要在拦截器中存储与当前正在处理的请求相关的数据,这不是拦截器的职责。拦截器应该只把它的处理逻辑应用在请求数据上,你可以通过ActionInvocation访问这些已经方便地存储在不同对象上地数据。
通过变成方法访问ActionContext限制在拦截器中。
参考链接:
http://www.blogjava.net/hwpok/archive/2008/10/28/237015.html
分享到:
相关推荐
简单的struts2自定义拦截器 很适合web初学者
Struts2全局、局部自定义拦截器源码。
struts2自定义拦截器.pdf
Struts2自定义拦截器实现防止重复提交
strut2 配置自定义拦截器 包括struts2.xml 和 action对应的xml 以及拦截器 可能有点简单 但是基本配置都有
JSP 开发之Struts2内建自定义拦截器.docx
NULL 博文链接:https://llxhna.iteye.com/blog/1067851
由于struts2标签的性能不好,项目组决定不使用,但是如果用struts2自带的拦截器防止重复提交又必须struts标签,所以只好自定拦器实现
综合使用servlet filter与struts2 interceptor对权限进行验证。
本篇文章主要介绍了struts2自定义拦截器的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
此实例实现功能:用户需要指定用户名登陆, 登陆成功进入相应页面执行操作,否则返回到登陆页面进行登陆, 当直接访问操作页面(登陆后才能访问的页面)时则不允许,须返回登陆页面。
主要给大家介绍了关于Struts2学习基础教程之拦截器机制与自定义拦截器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Struts2_自定义拦截器 struts2_3500_my_interceptor
struts2的自定义拦截器代码
struts2 用拦截器 实现用户权限登录 可以直接运行,只单单用到struts的东西。
struts2的自定义拦截器代码例子
主要介绍了JSP 开发之Struts2内建自定义拦截器的相关资料,需要的朋友可以参考下
自定义拦截器的实现以及拦截器的详细配置,配置文件里面有特别详细的注释,希望对刚接触拦截器的同学有帮助