struts2学习笔记之拦截器(Interceptor)

简介: 一、拦截器介绍拦截器即interceptor 其实现类似于Servlet技术中的Filter,与AOP概念是相关的。 关于AOP可以参考:http://www.cnblogs.com/wayfarer/articles/241024.
一、拦截器介绍
拦截器即interceptor
其实现类似于Servlet技术中的Filter,与AOP概念是相关的。
关于AOP可以参考:
http://www.cnblogs.com/wayfarer/articles/241024.html
http://baike.baidu.com/view/73626.htm

Servlet中的Filter技术可以参考:
http://blog.csdn.net/sun305355024sun/article/details/4815471
http://download.oracle.com/javaee/6/api/javax/servlet/Filter.html

拦截器通常封装了一些具有独立逻辑的通用功能,比如登录校验、异常捕捉、日志记录等等;利用它
可以在Action的执行前后做一些额外的工作,比如在执行前进行用户登录信息检查,若未登录跳转到登录页面,
否则执行Action。

二、拦截器的接口与实现
public interface Interceptor extends Serializable{
    void destroy();  // 销毁时执行,用于释放在init方法使用的资源
    void void init(); //初始化时执行


    //拦截方法的实现
    String intercept(ActionInvocation invocation)throws Exception;
}


AbstractInterceptor实现了该接口,并提供init和destroy方法的空实现,一般情况下实现自定义拦截器只需要
继承该类并重写intercept方法即可。


intercept方法的实现示例(登录信息检查):
 ActionContext  context = invocation.getInvocationContext();
    Map session = context.getSession();
    String user = session.get("user");
    if(user == null){   
        return Action.LOGIN;    //未登录,直接返回登录逻辑视图
    }else{
        return invocation.invoke();  //已登录则继续执行
     }

三、拦截器的配置

1 在package中定义拦截器

<interceptors>
        <interceptor name="exceptionManager"  class="cn.uc.mms.action.ExceptionInterceptor"/>
 </interceptors>

2 拦截器可以组成拦截器栈,拦截器栈可以由拦截器和栈组成。

 <interceptor-stack  name="myDefault">  
         <interceptor-ref name="exceptionManager"/>  //引用前面定义的拦截器
         <interceptor-ref  name="defaultStack"/>    //引用当前上下文的默认拦截器栈
    </interceptor-stack>  


  3 可以为package定义全局的拦截器引用,该定义仅支持一个引用,如果需要引用多个拦截器,可以声明为一个拦截器栈。
    <default-interceptor-ref name="myDefault" />   //该声明需要在拦截器或拦截器栈定义之后,Action声明之前
    
  4 为Action定义拦截器引用:
     <interceptor-ref name="exceptionManager"></interceptor-ref>  
       需要注意的是Action定义了拦截器引用之后,全局的拦截器引用将失效,需要显示声明来恢复:
     <interceptor-ref name="myDefault"></interceptor-ref>

  5 为拦截器注入参数:

      interceptor/interceptor-stack、interceptor-ref和default-interceptor-ref都可以通过param向interceptor注入参数

      简单情况如:

      <param name="name">拦截器A</param>     //拦截器需要有name属性(定义了setName方法)即可注入。

      但如果是从interceptor-stack进行参数注入,则param的name属性需要包含目标拦截器的名称前缀:

       <param name="interceptorA.name">拦截器A</param>
       如果同一个拦截器的param定义出现冲突,则取最后定义的值。
 

 6 拦截器的执行顺序:

      把拦截器想象成一个栈,由配置顺序构造出一个拦截器的执行列表,最底下是Action;

      从第一个拦截器往下执行,执行完Action之后又从最后一个拦截器往上走。

四、实现常用的拦截功能
    1 过滤方法的拦截器:MethodFilterInterceptor,指定excludeMethods黑名单、includeMethods为白名单,多个方法以,分隔。
                                               如果一个方法在两个名单中,那么会被拦截(被黑)
        使用方式:用一个类继承该类,并进行配置即可。
  
     2 监听Action返回的逻辑结果

       实现PreResultListener的接口,并在action执行前为invocation对象添加监听;

      通过拦截器实现上述动作:
public class MyPreResultListener implements PreResultListener{
          public void beforeResult(ActionInvocation invocation, String resultCode){
               ...
               //resultCode为action返回的逻辑视图名
           }
       }
     使用拦截器在action执行前执行:
 invocation.addPreResultListener(new MyPreResultListener());
 //注意beforeResult中不可再执行invocation.invoke(小心死循环)

    
五、最佳实践-- 实现全局异常捕获的拦截器
    实现一个拦截器,捕获Action执行时发生的异常,将结果信息写入到ActionContext的值栈中,并返回ERROR视图:  
     拦截器实现:
public class ExceptionInterceptor extends AbstractInterceptor {
    private static final Log log = LogFactory.getLog(ExceptionInterceptor.class);


	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		String actionName = invocation.getInvocationContext().getName();
		try {
                /*以下代码用于检测在该拦截器之前是否有其他的拦截器执行了某些校验且不通过的情况,
                 *比如文件上传的条件检查、表单校验之类,若有则一并当做异常进行捕获返回。
                 *该做法不是必须的,因需求而异。
                 */
	        Object action = invocation.getAction();
	        if (action instanceof ValidationAware) {
	        	ValidationAware validation = (ValidationAware) action;
	        	if(validation.hasFieldErrors()){
	        		String errorStr = JSONObject.fromObject(validation.getFieldErrors()).toString();
	        		throw new RuntimeException("拦截到错误:" + errorStr);
	        	}
	        }
                 
	          return invocation.invoke();
		} catch (Exception ex) {
			ex.printStackTrace();
            log.error("Error by action{" + actionName + "}", ex);
            HashMap<String, String> map = new HashMap<String, String>();
            String msg = "unknown";
            if(ex.getMessage() != null){
            	msg = ex.getMessage();
            }
            map.put("success", String.valueOf(false));
            map.put("error", msg);
            map.put("errorType", ex.getClass().toString());
            
            ActionContext ac = invocation.getInvocationContext();
            ValueStack stack = ac.getValueStack();
            stack.set("error", map);  //将错误信息注入到ValueStack中
            return "error";
	  }
	}
     }
   
     配置文件:
     <interceptors>
        <interceptor name="exceptionManager"  class="action.ExceptionInterceptor"/>
        <interceptor-stack   name="myDefault">  
              <interceptor-ref name="exceptionManager"/>   <!--将其配置在所有拦截器之上 -->
              <interceptor-ref   name="defaultStack"/>  
        </interceptor-stack>  
     </interceptors> 
     <default-interceptor-ref name="myDefault" />
	
     <global-results>   <!-- 配置全局逻辑结果 -->
	<result name="error" type="json">
	     <param name="root">error</param>
             <param name="contentType">text/html;charset=UTF-8</param>
             <param name="excludeNullProperties">true</param> 
        </result>
      </global-results>


     <action name="upload" class="..." method="doUpload">  
           <interceptor-ref name="fileUpload">  
              <param name="allowedTypes">application/vnd.ms-excel,application/excel,application/octet-stream</param>
              <param name="maximumSize">8192000</param>  
            </interceptor-ref>  
            <interceptor-ref name="myDefault"></interceptor-ref>  <!-- 文件上传的拦截,内置支持..详见代码 -->
       </action>  
      <action name="*" class="action.{1}Action"></action>

六、struts内置拦截器
     struts的拦截器是灵活的可插拔的,其通过强大的内置拦截器栈来完成大量通用的功能。
    比如params拦截器将http请求参数自动注入到action的属性中;validation完成表单校验;fileUpload用于
文件上传中将文件域信息注入到action的指定属性中,同时也提供相关的条件检查(如文件大小、类型)

    然而尽管内置拦截器栈是强大的,但有时也会导致一些不必要的开销,比如:
fileUpload的拦截器在默认拦截器栈中有一个,在普通用法中常常是另外声明一个fileUpload拦截器置于默认栈之前。
如此,在默认栈中的fileUpload拦截器则是多余。此时要提高性能则需自行定制。

     struts内置拦截器列表及说明:
     http://tsunzhang.iteye.com/blog/811565
img_9b09a36f6de95886f52ce82fa1e89c88.jpe

作者: zale

出处: http://www.cnblogs.com/littleatp/, 如果喜欢我的文章,请关注我的公众号

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接  如有问题, 可留言咨询.

目录
相关文章
Struts2的拦截器
Struts2的拦截器
39 0
QGS
|
存储 调度 数据安全/隐私保护
入门SpringMVC之Interceptor拦截器
SpringMVC中的Interceptor拦截器,它的主要作用是拦截指定的用户需求,并进行相应的预处理与后处理。
QGS
89 0
|
前端开发 Java Spring
SpringMVC拦截器interceptor
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
126 0
SpringMVC拦截器interceptor
|
Java 关系型数据库 MySQL
Struts2【拦截器】(二)
Struts2【拦截器】
159 0
Struts2【拦截器】(二)
|
Java
Struts2【拦截器】(一)
Struts2【拦截器】
164 0
Struts2【拦截器】(一)
|
小程序 Java
Struts2【拦截器】(三)
Struts2【拦截器】
183 0
Struts2【拦截器】(三)
|
Java NoSQL Redis
Struts 拦截器
介绍 实现aop的方式用于实现action之前,之后执行一般用于事物操作.一般用于对某些未授权的页面访问的时候,进行拦截操作,拦截非法访问. 开箱即用拦截器 <!-- 拦截器 --> <interceptor-ref name="params"/> ...
1106 0
|
Java 容器 应用服务中间件
12 Struts2 拦截器
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hxdeng/article/details/81941425 拦截器 拦截器在概念上和Servlet过滤器或JDK代理类一样。
1268 0
|
前端开发 Java Spring
详解SpringMVC中使用Interceptor拦截器
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。
1071 0
|
SQL Java 数据库
Struts2【拦截器】就是这么简单
什么是拦截器 拦截器Interceptor.....拦截器是Struts的概念,它与过滤器是类似的...可以近似于看作是过滤器 为什么我们要使用拦截器 前面在介绍Struts的时候已经讲解过了,Struts为我们实现了很多的功能,比如数据自动封装阿..文件上传功能阿....Struts为我们提供的这些功能都是通过拦截器完成的...... 数据自动封装通过这个拦截器。
1131 0