`

《研磨struts2》 第六章 拦截器 之 6.3 自定义的拦截器

阅读更多

6.3  自定义的拦截器

6.3.1  什么是自定义的拦截器

所谓自定义的拦截器,就是由我们自己定义并实现的拦截器,而不是由Struts2定义好的拦截器。

虽然Struts2的预定义拦截器已经满足了大多数情况的需要。但在有些时候,我们可能会根据项目的实际需要而自定义一些拦截器,来实现一些特别的功能。

       比如,我们可能认为Struts2预置的logger拦截器功能比较弱,我们希望在任何一个action运行的时候,都会先打印出所访问的动作类Action,再打印出所有的request参数,最后打印出要跳转到的jsp。这个功能并不影响真正的业务逻辑,但是对调试错误是非常有帮助的,免的我们再手工一一对应和查看。

6.3.2  开发自定义拦截器

好了,了解了什么是自定义的拦截器过后,一起来看看究竟如何实现自定义的拦截器。

其实在Struts2里面,要实现自定义的拦截器是非常简单的,只要写一个实现Interceptor接口的类就可以了。

       也就是说,所有的拦截器都要实现com.opensymphony.xwork2.interceptor.Interceptor接口,这个接口中定义如下:

 

java代码:
  1. public interface Interceptor extends Serializable {  
  2.     void destroy();  
  3.     void init();  
  4.     String intercept(ActionInvocation invocation) throws Exception;  
  5. }  

方法的基本说明如下:

  • 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代码:
  1. package cn.javass.action.action;  
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;  
  4. import com.opensymphony.xwork2.interceptor.Interceptor;  
  5.   
  6. public class MyInterceptor implements Interceptor{    
  7.     public void destroy() {  
  8.         System.out.println("MyInterceptor 销毁");  
  9.     }     
  10.     public void init() {  
  11.         System.out.println("MyInterceptor 初始化");          
  12.     }  
  13.       
  14.     public String intercept(ActionInvocation invocation) throws Exception {  
  15.         System.out.println("在acton执行之前");  
  16.         String result = invocation.invoke();  
  17.         System.out.println("在Result运行之后");  
  18.           
  19.         return result;  
  20.     }  
  21. }  

可以看到,这个Interceptor的init方法和destroy方法只是输出了一句信息,它的intercept方法用来执行响应,在“invocation.invoke();”这句话之前和之后分别输出了一句信息。最后返回的result,就是invocation.invoke()的返回值。

2:HelloWorldAction这个类不用修改

3:需要到struts.xml里面配置拦截器的声明和引用,示例如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.     <interceptors>  
  3.             <interceptor name=“myInterceptor” class="cn.javass.action.action.MyInterceptor"/>  
  4.         </interceptors>  
  5.                   
  6.         <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  7.             <result name="toWelcome">/s2impl/welcome.jsp</result>  
  8.             <interceptor-ref name=“myInterceptor”/>  
  9.             <interceptor-ref name="defaultStack"/>  
  10.         </action>  
  11. </package>  

在这个<package>元素中,首先声明了一个自定义的拦截器:

 

java代码:
  1. <interceptors>  
  2.         <interceptor name=“myInterceptor” class="cn.javass.action.action.MyInterceptor"/>  
  3.     </interceptors>  

然后在<action>中引用了这个拦截器。

4:运行测试一下,后台输出:

 

java代码:
  1. 在acton执行之前  
  2. 用户输入的参数为===account=test,password=test,submitFlag=login  
  3. 在Result运行之后  

可以看到加粗部分就是在拦截器里输出的信息,它分别运行于Action运行之前和Result运行之后。可能有朋友会说,从这里只看到了Action的运行,并没有看到Result的运行啊,你怎么知道是在Result运行之后呢?

       很简单,前面增经做过一个自定义的Result,这里来使用它,这样就可以在里面输出信息,从而看出拦截器、Action和Result运行的顺序了。

5:上一章自定义Result的类MyResult不需要改动

6:修改struts.xml,在里面添加上Result的定义,配置如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.         <result-types>  
  3.             <result-type name="MyResult" class="cn.javass.action.action.MyResult" default="false"/>  
  4.         </result-types>  
  5.                   
  6.         <interceptors>  
  7.             <interceptor name=“myInterceptor” class="cn.javass.action.action.MyInterceptor"/>  
  8.         </interceptors>  
  9.                   
  10.         <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  11.             <result name="toWelcome" type="MyResult">/s2impl/welcome.jsp</result>  
  12.             <interceptor-ref name=“myInterceptor”/>  
  13.             <interceptor-ref name="defaultStack"/>  
  14.         </action>  
  15. </package>  

7:再次访问登录页面,重新运行测试,后台的输出为:

 

java代码:
  1. 在acton执行之前  
  2. 用户输入的参数为===account=test,password=test,submitFlag=login  
  3. 要处理的Result字符串是=toWelcome  
  4. 在Result运行之后  

加粗的那句话,就是自定义的Result运行时输出的,你会发现,确实是Result运行完成过后,才运行的自定义拦截器中“invocation.invoke();”这句话后面的输出语句的。

       另外一点,你要是细心的话,你会发现,在启动服务器的时候,就会输出如下一句:

 

java代码:
  1. MyInterceptor 初始化  

这表明,拦截器在启动服务器的时候,就已经初始化好了。

8:要注意,如果自定义拦截器中没有调用“invocation.invoke();”这句话的话,那么就相当于后续的拦截器和Action都不会运行了,而是直接根据拦截器的intercept方法所直接返回的Result字符串,来匹配和运行Result。

       首先,要修改拦截器类,去掉“invocation.invoke();”这句话,直接返回一个Result字符串,示例代码如下:

 

java代码:
  1. public class MyInterceptor implements Interceptor{  
  2.     public void destroy() {  
  3.         System.out.println("MyInterceptor 销毁");  
  4.     }  
  5.     public void init() {  
  6.         System.out.println("MyInterceptor 初始化");          
  7.     }  
  8.     public String intercept(ActionInvocation invocation) throws Exception {  
  9.         System.out.println("在acton执行之前");  
  10.         System.out.println("在Result运行之后");  
  11.         return "toWelcome";  
  12.     }  
  13. }  

然后再次运行测试,后台的输出为:

 

java代码:
  1. 在acton执行之前  
  2. 在Result运行之后  
  3. 要处理的Result字符串是=toWelcome  

也就是说,是先把拦截器的intercept方法执行完成,然后才运行的Result。

6.3.3  向拦截器传入参数

为什么要传入参数呢?因为有些时候,同一个拦截器为不同的Action服务的时候,需要根据传入的参数进行处理上的变化。比如说,一个记录日志的拦截器,可以根据配置来决定到底把日志记录在数据库还是文件里面。

可以把这种配置数据作为一个参数,在配置的时候设置值,会自动传入拦截器中。具体做法还是看个示例比较清楚。

1首先看看在struts.xml中,如何为拦截器设置参数。

 

java代码:
  1. <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  2.         <result name="toWelcome" type="MyResult">/s2impl/welcome.jsp</result>  
  3.         <interceptor-ref name=“myInterceptor”>  
  4.                 <param name="dbOrFile">db</param>  
  5.         </interceptor-ref>  
  6.         <interceptor-ref name="defaultStack"/>  
  7. </action>  

在这里,通过<param>子元素来为拦截器注入参数,名称是自定义的,当然要与拦截器里面的属性匹配上。

2拦截器类要想接到这个参数,就必须定义一个对应的属性,并提供setter方法,示例代码如下:

 

java代码:
  1. public class MyInterceptor implements Interceptor{  
  2.     private String dbOrFile;  
  3.     public void setDbOrFile(String dbOrFile) {  
  4.         this.dbOrFile = dbOrFile;  
  5.     }  
  6.     public void destroy() {  
  7.     }  
  8.     public void init() {  
  9.     }  
  10.     public String intercept(ActionInvocation invocation) throws Exception {  
  11.         System.out.println("接到dbOrFile的参数=="+this.dbOrFile);  
  12.         if("db".equalsIgnoreCase(this.dbOrFile)){  
  13.             System.out.println("记录日志到数据库");  
  14.         }else{  
  15.             System.out.println("记录日志到文件");  
  16.         }  
  17.         String result = invocation.invoke();  
  18.         return result;  
  19.     }     
  20. }  

注意加粗的部分,名称为dbOrFile的属性以及对应的setter方法。这样,在初始化这个拦截器的时候,Struts2就会反射的调用对应的setter,把在<param>元素中配置的值设置到dbOrFile属性上去。

       测试运行,后台输出为:

 

java代码:
  1. 接到dbOrFile的参数==db  
  2. 记录日志到数据库  
  3. 用户输入的参数为===account=test,password=test,submitFlag=login  
  4. 要处理的Result字符串是=toWelcome  

3上面是在引用拦截器的时候设置参数,还有另一种方式指定参数。就是在拦截器声明的时候就设置参数,示例配置如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.         <result-types>  
  3.             <result-type name="MyResult" class="cn.javass.action.action.MyResult" default="false"/>  
  4.         </result-types>  
  5.                   
  6.         <interceptors>  
  7.             <interceptor name=“myInterceptor” class="cn.javass.action.action.MyInterceptor">  
  8.                 <param name="dbOrFile">db</param>  
  9.             </interceptor>  
  10.         </interceptors>  
  11.                   
  12.         <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  13.             <result name="toWelcome" type="MyResult">/s2impl/welcome.jsp</result>  
  14.             <interceptor-ref name=“myInterceptor”/>    
  15.             <interceptor-ref name="defaultStack"/>  
  16.         </action>  
  17. </package>  

去运行测试一下,这种配置方式得到的运行效果和前一种方式是一样的。

4:在<interceptor-ref>元素上注册的参数会覆盖在<interceptor>元素上注册的同名参数。示例配置如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.         <result-types>  
  3.             <result-type name="MyResult" class="cn.javass.action.action.MyResult" default="false"/>  
  4.     </result-types>  
  5.                   
  6.         <interceptors>  
  7.             <interceptor name=“myInterceptor” class="cn.javass.action.action.MyInterceptor">  
  8.                 <param name="dbOrFile">db</param>  
  9.             </interceptor>  
  10.         </interceptors>  
  11.                   
  12.     <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  13.         <result name="toWelcome" type="MyResult">/s2impl/welcome.jsp</result>  
  14.         <interceptor-ref name=“myInterceptor”>  
  15.                 <param name="dbOrFile">file</param>  
  16.         </interceptor-ref>                  
  17.         <interceptor-ref name="defaultStack"/>  
  18. </action>  
  19. </package>  

再次运行测试,后台输出为:

 

java代码:
  1. 接到dbOrFile的参数==file  
  2. 记录日志到文件  
  3. 用户输入的参数为===account=test,password=test,submitFlag=login  
  4. 要处理的Result字符串是=toWelcome  

后台输出的是file而不是db,这说明,在声明拦截器的时候定义的参数,被引用拦截器的时候配置的参数覆盖了。

 

 

私塾在线网站原创《研磨struts2》系列

转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4059.html

欢迎访问http://sishuok.com获取更多内容

2
3
分享到:
评论
1 楼 429537044 2013-01-06  
看完这一篇,多谢楼主分享

相关推荐

    研磨Struts2配书视频对应的演示源代码

    2. **拦截器(Interceptors)**:Struts2的核心之一是其拦截器机制,它们在Action执行前后执行一系列预定义或自定义的操作。这些拦截器可以用于登录验证、日志记录、性能监控等。源代码中可能包含了不同类型的拦截器...

    《研磨Struts 2》PDF版本下载.txt

    相比于第一代Struts框架,Struts 2提供了更多的功能,如拦截器、动态方法调用、更强大的表单处理机制等,并且它与Spring和Hibernate等其他Java EE技术栈的集成更加紧密。 ### Struts 2的特点 1. **强大的表单处理...

    研磨Struts2

    ### 知识点一:Struts2入门(MVC HelloWorld) #### 1.1 Struts2简介 ...以上就是关于“研磨Struts2”的主要知识点梳理,通过深入学习这些内容,开发者可以更好地掌握Struts2框架的核心技术和实践技巧。

    研磨Struts2配书视频对应的PPT

    Struts2框架的拦截器是其一大特色,它允许开发者定义一系列预定义或自定义的行为,这些行为在请求被处理前和后执行。例如,登录验证、日志记录、性能监控等都可以通过拦截器实现。通过灵活的拦截器链,开发者可以...

    研磨struts2 高清版

    由于文件较大,我把这个文档切割为2部分,这是第一部分,请下载完第一部分后一定要下载第二部分,否则不能阅读。

    研磨struts

    11. **Interceptor**:拦截器是Struts2中的另一个重要特性,它们在Action执行前后插入,提供了日志、权限检查、事务控制等功能。拦截器链可以根据需要定制,提高了代码的复用性和可扩展性。 12. **其他重要知识**:...

    研磨Struts2 高清完整版.part2

    研磨Struts2 高清完整版,请和第一部分一起下载啊

    研磨Struts2_12859679_高清完整版.part2.rar

    研磨Struts2_12859679_高清完整版

    研磨Struts2-高清-完整目录-2011年10月

    研磨Struts2-高清-完整目录-2011年10月,分享给所有需要的人

    研磨设计模式(完整带书签).part2.pdf

    第6章 工厂方法模式(Factory Method) 第7章 抽象工厂模式(Abstract Factory) 第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 ...

    研磨设计模式-part2

    第6章 工厂方法模式(Factory Method) 第7章 抽象工厂模式(Abstract Factory) 第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 ...

    研磨设计模式(完整带书签).part1.pdf

    第6章 工厂方法模式(Factory Method) 第7章 抽象工厂模式(Abstract Factory) 第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) 第12章 ...

    研磨设计模式.part2(共4个)

    第6章 工厂方法模式(Factory Method) 第7章 抽象工厂模式(Abstract Factory) 第8章 生成器模式(Builder) 第9章 原型模式(Prototype) 第10章 中介者模式(Mediator) 第11章 代理模式(Proxy) ...

    Java工程师三大框架面试题.pdf

    Java工程师三大框架面试题.pdf

Global site tag (gtag.js) - Google Analytics