`

《研磨struts2》 第六章 拦截器 之 6.4 两个有用的拦截器

 
阅读更多

6.4  两个有用的拦截器

6.4.1  更强大的logger拦截器

在学习了这么多拦截器的理论知识过后,来示范两个真实项目中用得到的拦截器。先来看看更强大的logger拦截器。

Struts2自带的logger拦截器只是打印出了Action所对应的URL以及执行的方法名称,这对实际开发来说是肯定不够的。

       实际开发中为了调试方便,要记录的信息比较多,通常需要把这次请求相关的几乎所有信息都打印出来,比如:

  • 要访问哪个Action类
  • 要访问这个Action类的哪个方法
  • 打印出这次请求中所有的request中的parameter参数
  • 这次请求最后跳转到哪个页面。

       如果我们现在就要在拦截器中实现这样的功能,该怎么实现呢?

1:ActionInvocation接口

       在实现拦截器的功能的时候,需要使用ActionInvocation接口,这个接口有很多的功能,这里并不打算全部讲到,只描述一下接下来我们要用到的功能,更多的功能请参见Struts2的API文档。

  • getAction方法:返回这次请求准备执行的Action对象。
  • getProxy方法:返回这次请求的ActionProxy对象,可以在这个对象上获得要运行Action的哪个方法。
  • getInvocationContext方法:返回这个Action执行的上下文(ActionContext),可以在这个上下文对象中获取到大量的数据,比如请求的parameter值、session的值等等。
        在ActionContext中取到的parameter值是一个Map<String,Object>,其中以String为key,以String[]为value。这个Map中记录了所有的request参数。
  • getResult方法:返回Result运行之后代表结果的Result对象。

2:具体的LoggerInterceptor,示例代码如下:

 

java代码:
  1. package cn.javass.action.action;  
  2.   
  3. import java.util.Map;  
  4. import org.apache.struts2.dispatcher.ServletDispatcherResult;  
  5. import com.opensymphony.xwork2.ActionInvocation;  
  6. import com.opensymphony.xwork2.Result;  
  7. import com.opensymphony.xwork2.interceptor.Interceptor;  
  8.   
  9. public class LoggerInterceptor implements Interceptor{  
  10.     public void destroy() {  
  11.     }  
  12.     public void init() {  
  13.     }     
  14.     public String intercept(ActionInvocation invocation) throws Exception {  
  15.         System.out.println("begin-------------------------------");  
  16.         //找到运行的Action对象,并打印其类名  
  17.         System.out.println("Action:"+invocation.getAction().getClass().getName());  
  18.         //找到运行的ActionProxy对象,并打印其要运行的方法名  
  19.         System.out.println("Method:"+invocation.getProxy().getMethod());  
  20.         //找到这次请求的request中的parameter参数,并打印  
  21.         Map<String, Object> params = invocation.getInvocationContext().getParameters();  
  22.         for (String key:params.keySet()){  
  23.             Object obj = params.get(key);  
  24.               
  25.             if(obj instanceof String[]){  
  26.                 String[] arr = (String[]) obj;  
  27.                 System.out.println("Param:"+key);  
  28.                 for (String value:arr){  
  29.                     System.out.println(value);  
  30.                 }  
  31.             }  
  32.         }  
  33.           
  34.         //运行后续的拦截器、Action和Result  
  35.         String resultCode = invocation.invoke();  
  36.           
  37.         //在Action和Result运行之后,得到Result对象  
  38.         //并且可以强制转换成ServletDispatcherResult,打印其下一个JSP的位置  
  39.         Result rresult = invocation.getResult();  
  40.         if (rresult instanceof ServletDispatcherResult){  
  41.             ServletDispatcherResult result = (ServletDispatcherResult) rresult;  
  42.             System.out.println("JSP:"+result.getLastFinalLocation());  
  43.         }  
  44.           
  45.         System.out.println("end-------------------------------");           return resultCode;  
  46.     }  
  47. }  

3:在struts.xml中配置和使用这个拦截器,示例如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.         <interceptors>  
  3.             <interceptor name="MyLogger" class="cn.javass.action.action.LoggerInterceptor"/>  
  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="MyLogger"/>  
  9.             <interceptor-ref name="defaultStack"/>  
  10.         </action>  
  11. </package>  

4:测试一下,运行登录页面,填入用户名和密码,点击提交按钮。然后查看后台的输出,示例如下:

 

java代码:
  1. begin-------------------------------  
  2. Action:cn.javass.action.action.HelloWorldAction  
  3. Method:execute  
  4. Param:submitFlag  
  5. login  
  6. Param:account  
  7. test  
  8. Param:password  
  9. test  
  10. 用户输入的参数为===account=test,password=test,submitFlag=login  
  11. JSP:/s2impl/welcome.jsp  
  12. end-------------------------------  

上面加粗的那句话,是Action运行的时候输出的信息,其余信息就是由我们的拦截器来输出的了。

基本实现了前面提出的四个要求,分别输出了如下信息:运行哪个Action类,运行哪个方法,请求的参数,Action运行完要跳转到哪个JSP。

这些信息对我们进行调试是非常有用的。

6.4.2  登录检查拦截器

在实际开发中,一个常见的功能要求是:有很多操作都需要登录后才能操作,如果操作的时候还没有登录,那么通常情况下会要求跳转回到登录页面。

1:如何实现这样的功能呢?

在具体实现之前,先来考虑几个问题:

1)这个功能应该在哪里实现?

要实现登录检查的功能,很明显是在Action运行之前,就要判断用户是否登陆了,判断方式是看session里面是否有相关信息,如果有,则继续操作;如果没有,则要跳转到预先制定好的登录页面。

简单点说,登录检查应该写在“invocation.invoke();”语句之前。

       2)是否需要参数?

要判断是否需要参数,其实就是判断这个拦截器有没有什么可变的量,可以把这些可变量从程序中分离出来,通过struts.xml来配置。经过分析,可以抽出两个参数:

  • 代表登陆页面的Result
  • 判断session中哪个attribute,也就是attribute的名称

       3)如何引用呢?

现在的情况是只有部分Action需要登陆录检查,另外一些Action不需要,这就需要权衡了。对于大多数Action都要进行登录检查的包,可以在包的默认拦截器引用上设置登录检查,而对于少数不需要登陆检查的Action,可以让它们直接引用默认的defaultStack拦截器栈。

2:接下来,就来实现满足要求的拦截器,示例代码如下:

 

java代码:
  1. package cn.javass.action.action;  
  2.   
  3. import java.util.Map;  
  4. import com.opensymphony.xwork2.ActionContext;  
  5. import com.opensymphony.xwork2.ActionInvocation;  
  6. import com.opensymphony.xwork2.interceptor.Interceptor;  
  7.   
  8. public class SessionCheckInterceptor implements Interceptor{  
  9.     //设置参数  
  10.     private String sessionAttribute;  
  11.     private String reloginResult;  
  12.     public void setSessionAttribute(String sessionAttribute) {  
  13.         this.sessionAttribute = sessionAttribute;  
  14.     }  
  15.     public void setReloginResult(String reloginResult) {  
  16.         this.reloginResult = reloginResult;  
  17.     }  
  18.     public void destroy() { }  
  19.     public void init() {    }  
  20.     public String intercept(ActionInvocation invocation) throws Exception {  
  21.         //读取Session  
  22.         Map<String, Object> session = invocation.getInvocationContext().getSession();  
  23.         //判断Session中是否有相应的attribute  
  24.         if (session.containsKey(sessionAttribute)){  
  25.             String resultCode = invocation.invoke();  
  26.             return resultCode;  
  27.         }else{  
  28.             return reloginResult;  
  29.         }         
  30.     }  
  31. }  

在intercept方法中,先读取session中指定的attribute,具体读取哪个attribute由参数从外界传进来,然后判断Session中是否存在这个attribute,如果有则继续执行后续的拦截器、Action和Result,如果没有则跳转到指定的Result所对应的页面,具体跳转到哪个Result也是由参数从外界传进来的。

3:写好了拦截器,该来写配置了,配置示例如下:

 

java代码:
  1. <package name="helloworld"  extends="struts-default">  
  2.         <interceptors>  
  3.             <interceptor name="LoginChecker" class="cn.javass.action.action.SessionCheckInterceptor"/>  
  4.             <interceptor-stack name="myStack">  
  5.                 <interceptor-ref name="LoginChecker">  
  6.                     <param name="sessionAttribute">login_user</param>  
  7.                     <param name="reloginResult">login</param>  
  8.                 </interceptor-ref>  
  9.                 <interceptor-ref name="defaultStack"/>  
  10.             </interceptor-stack>  
  11.         </interceptors>  
  12.           
  13.         <default-interceptor-ref name="myStack"/>  
  14.           
  15.         <global-results>  
  16.             <result name="login">/login.jsp</result>  
  17.         </global-results>  
  18.                   
  19.         <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
  20.             <result name="toWelcome">/s2impl/welcome.jsp</result>  
  21.         </action>  
  22.         <action name="secondAction" class="cn.javass.action.action.SecondAction">  
  23.             <result name="toWelcome">/s2impl/welcome.jsp</result>  
  24.             <interceptor-ref name="defaultStack"/>  
  25.         </action>  
  26. </package>  

配置比较多,分解说明一下:

(1)上面的配置声明了一个叫LoginChecker的自定义拦截器,如下:

 

java代码:
  1. <interceptor name="LoginChecker" class="cn.javass.action.action.SessionCheckInterceptor"/>  

2)声明了一个myStack拦截器栈,在这个栈里面引用了LoginChecker拦截器和defaultStack拦截器,在引用LoginChecker拦截器的时候,还传入了两个自定义的参数,其中sessionAttribute传入login_user,reloginResult传入login,以备在拦截器中使用,如下:

 

java代码:
  1. <interceptor-stack name="myStack">  
  2.                 <interceptor-ref name="LoginChecker">  
  3.                     <param name="sessionAttribute">login_user</param>  
  4.                     <param name="reloginResult">login</param>  
  5.                 </interceptor-ref>  
  6.                 <interceptor-ref name="defaultStack"/>  
  7.             </interceptor-stack>  

(3)将myStack拦截器栈指定为这个包的默认拦截器引用,如下:

 

java代码:
  1. <default-interceptor-ref name="myStack"/>  

(4)声明了一个全局Result,作为所有需要登录检查的Action在没有登陆的时候,跳转到的登陆页面。这个Result的命名,要与引用LoginChecker拦截器时注入的reloginResult参数一致,如下:

 

java代码:
  1. <global-results>  
  2.             <result name="login">/login.jsp</result>  
  3.         </global-results>  

(5)这时,在整个包中,没有自己声明<interceptor-ref>的Action,都会采用包声明的默认拦截器引用,比如已经可以对helloworldAction执行登录检查了。

       为了测试需要,对于secondAction,配置了引用defaultStack,这样它就不会进行登录检查。

(6)去测试看看,是否能满足功能要求。

 

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

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

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

4
4
分享到:
评论

相关推荐

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

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

    研磨Struts2

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

    研磨struts2

    **Struts2** 作为 **Struts1** 的下一代产品,在很多方面进行了改进,例如支持拦截器、动态方法调用、文件上传下载等。其核心组件包括: - **Action**:控制器组件,用于处理具体的业务逻辑。 - **Interceptor**:...

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

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

    研磨struts2 高清版

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

    研磨Struts2配书视频对应的PPT

    Struts2是一个强大的Java web应用程序开发框架,它基于Model-View-Controller(MVC)设计模式,为开发者提供了构建高效、可扩展且易于维护的Web应用的工具和组件。《研磨Struts2》这本书是专门针对Struts2框架的学习...

    研磨struts2_系列文章.pdf

    Struts2内置了多个预定义的拦截器,同时也支持自定义拦截器的开发。 ### 值栈和OGNL 值栈(ValueStack)是Struts2用于存储Action和相关数据的容器,它支持多层嵌套,可以方便地在Action之间共享数据。OGNL(Object-...

    研磨struts

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

    研磨Struts2 高清完整版.part2

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

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

    研磨Struts2_12859679_高清完整版

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

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

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

    本电子书一共两个压缩文档,本文件为part2. 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,...

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

    本电子书一共两个压缩文档,该文档为part1。 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等...

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

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

    研磨设计模式-part2

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

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

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

Global site tag (gtag.js) - Google Analytics