zoukankan      html  css  js  c++  java
  • springMVC之Interceptor拦截器

    转自:https://blog.csdn.net/qq_25673113/article/details/79153547

    Interceptor拦截器用于拦截Controller层接口,表现形式有点像Spring的AOP,但是AOP是针对单一的方法。Interceptor是针对Controller接口以及可以处理request和response对象。

    1 HandlerInterceptor接口的定义
    我们先来看下HandlerInterceptor接口的定义,定义了三个接口,分别是preHandle、postHandle、afterCompletion。

     1 public interface HandlerInterceptor {
     2 
     3     boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
     4             throws Exception;
     5 
     6     void postHandle(
     7             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
     8             throws Exception;
     9 
    10     void afterCompletion(
    11             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    12             throws Exception;
    13 
    14 }

    preHandle是调用Controller之前被调用,当返回false后,会跳过之后的拦截器,并且不会执行所有拦截器的postHandle,并调用返回true的拦截器的afterCompletion方法。
    postHandle是调用Controller之后被调用,但是在渲染View页面之前。
    afterCompletion是调用完Controller接口,渲染View页面最后调用。返回true的拦截器都会调用该拦截器的afterCompletion方法,顺序相反。

    和HandlerInterceptor很相似的要有一个AsyncHandlerInterceptor接口,只是多了个afterConcurrentHandlingStarted个方法,当接口使用了异步的方法的时候调用。

    1 public interface AsyncHandlerInterceptor extends HandlerInterceptor {
    2 
    3     void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
    4             throws Exception;
    5 
    6 }

    2 HandlerInterceptor接口的定义

    2.1 DispatcherServlet里doDispatch主处理逻辑

    DispatcherServlet里doDispatch()就是springMVC的处理主要逻辑。因此肯定包含了拦截器的主要处理逻辑

     1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     2         try {
     3 
     4             try {
     5                 //.......省略代码
     6 
     7                 //返回HandlerExecutionChain  其中包含了拦截器队列
     8                 mappedHandler = getHandler(processedRequest);
     9 
    10                 //调用拦截器PreHandle方法,若返回false不执行Controller逻辑,并不调用下面的PostHandle方法
    11                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    12                     return;
    13                 }
    14 
    15                 // 处理Controller层
    16                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    17 
    18                 applyDefaultViewName(processedRequest, mv);
    19 
    20                 //调用拦截器的PostHandle方法
    21                 mappedHandler.applyPostHandle(processedRequest, response, mv);
    22             }
    23             catch (Exception ex) {
    24                 dispatchException = ex;
    25             }
    26 
    27             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    28         }
    29         catch (Exception ex) {
    30             //抛出异常后都会调用拦截器AfterCompletion方法
    31             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    32         }
    33         finally {
    34             if (asyncManager.isConcurrentHandlingStarted()) {
    35                 // Instead of postHandle and afterCompletion
    36                 if (mappedHandler != null) {
    37                     //若Controller方法为异步调用,则执行拦截器afterConcurrentHandlingStarted(只有AsyncHandlerInterceptor拦截器才有)
    38                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
    39                 }
    40             }
    41         }
    42     }

    2.2 获取拦截器

     1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     2     //返回HandlerExecutionChain  其中包含了拦截器队列
     3     mappedHandler = getHandler(processedRequest);
     4 }
     5 //返回HandlerExecutionChain
     6 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     7 
     8     HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
     9     return executionChain;
    10 }
    11 
    12 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    13         HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
    14                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    15 
    16         //根据url和拦截器异常的配置url做对比,若符合则加入队列
    17         String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    18         for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
    19             if (interceptor instanceof MappedInterceptor) {
    20                 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
    21                 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
    22                     chain.addInterceptor(mappedInterceptor.getInterceptor());
    23                 }
    24             }
    25             else {
    26                 chain.addInterceptor(interceptor);
    27             }
    28         }
    29         return chain;
    30 }
    31 
    32 public boolean matches(String lookupPath, PathMatcher pathMatcher) {
    33         PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher;
    34         if (this.excludePatterns != null) {
    35             for (String pattern : this.excludePatterns) {
    36                 if (pathMatcherToUse.match(pattern, lookupPath)) {
    37                     return false;
    38                 }
    39             }
    40         }
    41         if (this.includePatterns == null) {
    42             return true;
    43         }
    44         else {
    45             for (String pattern : this.includePatterns) {
    46                 if (pathMatcherToUse.match(pattern, lookupPath)) {
    47                     return true;
    48                 }
    49             }
    50             return false;
    51         }
    52 }

    上述的拦截器的信息,都来自与下面的配置文件

     1 <!-- 拦截器链 -->
     2     <mvc:interceptors>
     3 
     4         <mvc:interceptor>
     5             <!--拦截器mapping 符合的才会执行拦截器-->
     6             <mvc:mapping path="/**"/>
     7             <!--在拦截器mapping中除去下面的url -->
     8             <mvc:exclude-mapping path="/transactional_test/*"/>
     9             <!--执行的拦截器-->
    10             <ref bean="apiInterceptor"/>
    11         </mvc:interceptor>
    12     </mvc:interceptors>
    13 
    14     <bean id="apiInterceptor" class="com.lk.dome.interceptor.ApiInterceptor"/>
    15 --------------------- 

    2.3 处理拦截器

     1 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
     2         HandlerInterceptor[] interceptors = getInterceptors();
     3         if (!ObjectUtils.isEmpty(interceptors)) {
     4             for (int i = 0; i < interceptors.length; i++) {
     5                 HandlerInterceptor interceptor = interceptors[i];
     6                 //若返回false,则直接执行拦截器的triggerAfterCompletion方法
     7                 if (!interceptor.preHandle(request, response, this.handler)) {
     8                     triggerAfterCompletion(request, response, null);
     9                     //直接返回,在外层的doDispatch逻辑中不执行后面的逻辑
    10                     return false;
    11                 }
    12                 //记录成功执行的拦截器个数
    13                 this.interceptorIndex = i;
    14             }
    15         }
    16         return true;
    17 }
    18 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
    19         HandlerInterceptor[] interceptors = getInterceptors();
    20         if (!ObjectUtils.isEmpty(interceptors)) {
    21             //拦截器队列从后往前之心,顺序相反
    22             for (int i = interceptors.length - 1; i >= 0; i--) {
    23                 HandlerInterceptor interceptor = interceptors[i];
    24                 interceptor.postHandle(request, response, this.handler, mv);
    25             }
    26         }
    27 }
    28 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
    29             throws Exception {
    30 
    31         HandlerInterceptor[] interceptors = getInterceptors();
    32         if (!ObjectUtils.isEmpty(interceptors)) {
    33             //interceptorIndex为执行成功的拦截器标志
    34             for (int i = this.interceptorIndex; i >= 0; i--) {
    35                 HandlerInterceptor interceptor = interceptors[i];
    36                 try {
    37                     interceptor.afterCompletion(request, response, this.handler, ex);
    38                 }
    39                 catch (Throwable ex2) {
    40                     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
    41                 }
    42             }
    43         }
    44 }
    45 //异步方法调用,拦截器必须属于AsyncHandlerInterceptor接口
    46 void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
    47         HandlerInterceptor[] interceptors = getInterceptors();
    48         if (!ObjectUtils.isEmpty(interceptors)) {
    49             for (int i = interceptors.length - 1; i >= 0; i--) {
    50                 if (interceptors[i] instanceof AsyncHandlerInterceptor) {
    51                     try {
    52                         AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
    53                         asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
    54                     }
    55                     catch (Throwable ex) {
    56                         logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
    57                     }
    58                 }
    59             }
    60         }
    61 }
    
    
    
    
    
    
    
  • 相关阅读:
    Thymeleaf学习记录(6)--迭代及条件语法
    Thymeleaf学习记录(5)--运算及表单
    Thymeleaf学习记录(4)--$/*/#/@语法
    Thymeleaf学习记录(3)--语法
    Thymeleaf学习记录(2)--自动编译设置
    ssh和scp详解
    持续集成(Continuous integration)
    部署基于python语言的WEB发布环境
    python垃圾回收机制(Garbage collection)
    Dockerfile定制镜像
  • 原文地址:https://www.cnblogs.com/sharpest/p/10416198.html
Copyright © 2011-2022 走看看