springMVC拦截器执行过程和使用

来源:互联网 发布:python截取中文字符串 编辑:程序博客网 时间:2024/05/29 19:14

1.拦截器: 用于对handle进行预处理和后处理
2.执行过程
在org.springframework.web.servlet.DispatcherServlet#doDispatch中:

HandlerExecutionChain mappedHandler = null;//首先获取HandlerExecutionChain(handle和拦截器)// Determine handler for the current request.mappedHandler = getHandler(processedRequest, false);...//1.拦截器开始作用(PreHandle方法:说明切点是在执行handle之前)if (!mappedHandler.applyPreHandle(processedRequest, response)) {//只要有拦截器返回false就退出,同时在catch语句块中触发AfterCompletion                    return;                }//通过applyPreHandle的for循环可以看出PreHandle的执行顺序为顺序执行boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {        if (getInterceptors() != null) {            for (int i = 0; i < getInterceptors().length; i++) {                HandlerInterceptor interceptor = getInterceptors()[i];                //只要一个preHandle返回false,就返回false                if (!interceptor.preHandle(request, response, this.handler)) {                    triggerAfterCompletion(request, response, null);                    return false;                }                this.interceptorIndex = i;            }        }        return true;    }//执行handle// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//2.执行PostHandle(切点在handle执行后,视图返回之前)mappedHandler.applyPostHandle(processedRequest, response, mv);//通过applyPostHandle的for循环可以知道PostHandle执行顺序为逆序void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {        if (getInterceptors() == null) {            return;        }        for (int i = getInterceptors().length - 1; i >= 0; i--) {            HandlerInterceptor interceptor = getInterceptors()[i];            interceptor.postHandle(request, response, this.handler, mv);        }    }//3.AfterCompletion在下面的方法中被调用(AfterCompletion切入点是在视图渲染后(执行异常后也会被调用),也就是视图返回前执行)//视图渲染,处理异常(视图渲染之后会执行triggerAfterCompletion)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//出现异常错误后执行catch (Exception ex) {    triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Error err) {    triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);}//afterCompletion被使用的方法:(从for循环可以看出是逆序执行)void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)            throws Exception {        if (getInterceptors() == null) {            return;        }        for (int i = this.interceptorIndex; i >= 0; i--) {            HandlerInterceptor interceptor = getInterceptors()[i];            try {                interceptor.afterCompletion(request, response, this.handler, ex);            }            catch (Throwable ex2) {                logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);            }        }    }

3.拦截器各个方法的作用
a)preHandle

//Called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler.(在handle被调用之前执行)//return false表示拦截,不向下执行//return true表示放行boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;

作用:用于身份认证、身份授权

b)postHandle

//Called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view.(handlle执行之后,视图返回之前)void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;

作用:将公用的模型数据在这里传到视图,也可以在这里统一指定视图(比如:菜单导航)

c)afterCompletion

//Callback after completion of request processing, that is, after rendering the view.(视图渲染后执行)void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;

作用:统一异常处理,统一日志处理,资源清理

4.拦截器的配置和使用

配置:
主要使用springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
在springMVC的配置文件中配置

<mvc:interceptors>        <!--多个拦截器,顺序执行 -->        <mvc:interceptor>            <!-- /**表示所有url包括子url路径 -->            <mvc:mapping path="/**"/>            <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>        </mvc:interceptor>        <mvc:interceptor>            <mvc:mapping path="/**"/>            <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean>        </mvc:interceptor></mvc:interceptors>

当需要配置公开地址时,在<mvc:interceptor> 中添加:

<!--将公开地址配置在path中--><mvc:exclude-mapping path="/"/>

使用:
实现org.springframework.web.servlet.HandlerInterceptor这个接口

public class HandlerInterceptor1 implements HandlerInterceptor{...}

5.注意点
1)对于统一日志处理之类的全局设置:需要将对应的拦截器放在拦截器链的第一个
2)preHandle方法按拦截器配置的顺序执行,postHandle和afterCompletion按拦截器配置的逆向顺序执行。
3)只要有一个拦截器不放行,postHandle不会执行,只有在拦截器链内所有拦截器放行(即返回true)才会执行
4)只有preHandle返回true,afterCompletion才会执行

运行示例
比如两个拦截器:
1)第一个拦截器放行,第二个放行:

HandlerInterceptor1...preHandleHandlerInterceptor2...preHandleHandlerInterceptor2...postHandleHandlerInterceptor1...postHandleHandlerInterceptor2...afterCompletionHandlerInterceptor1...afterCompletion

2)第一个拦截器放行,第二个拦截:

HandlerInterceptor1...preHandleHandlerInterceptor2...preHandleHandlerInterceptor1...afterCompletion

3)第一个拦截器拦截,第二个放行(或者不放行):
HandlerInterceptor1…preHandle

原创粉丝点击