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。
 public interface HandlerInterceptor {
     boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception;
     void postHandle(
             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
             throws Exception;
     void afterCompletion(
             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
             throws Exception;
 }
preHandle是调用Controller之前被调用,当返回false后,会跳过之后的拦截器,并且不会执行所有拦截器的postHandle,并调用返回true的拦截器的afterCompletion方法。 
postHandle是调用Controller之后被调用,但是在渲染View页面之前。 
afterCompletion是调用完Controller接口,渲染View页面最后调用。返回true的拦截器都会调用该拦截器的afterCompletion方法,顺序相反。
和HandlerInterceptor很相似的要有一个AsyncHandlerInterceptor接口,只是多了个afterConcurrentHandlingStarted个方法,当接口使用了异步的方法的时候调用。
 public interface AsyncHandlerInterceptor extends HandlerInterceptor {
     void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception;
 }
2 HandlerInterceptor接口的定义
2.1 DispatcherServlet里doDispatch主处理逻辑
DispatcherServlet里doDispatch()就是springMVC的处理主要逻辑。因此肯定包含了拦截器的主要处理逻辑
 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
         try {
             try {
                 //.......省略代码
                 //返回HandlerExecutionChain  其中包含了拦截器队列
                 mappedHandler = getHandler(processedRequest);
                 //调用拦截器PreHandle方法,若返回false不执行Controller逻辑,并不调用下面的PostHandle方法
                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                     return;
                 }
                 // 处理Controller层
                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                 applyDefaultViewName(processedRequest, mv);
                 //调用拦截器的PostHandle方法
                 mappedHandler.applyPostHandle(processedRequest, response, mv);
             }
             catch (Exception ex) {
                 dispatchException = ex;
             }
             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
         }
         catch (Exception ex) {
             //抛出异常后都会调用拦截器AfterCompletion方法
             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
         }
         finally {
             if (asyncManager.isConcurrentHandlingStarted()) {
                 // Instead of postHandle and afterCompletion
                 if (mappedHandler != null) {
                     //若Controller方法为异步调用,则执行拦截器afterConcurrentHandlingStarted(只有AsyncHandlerInterceptor拦截器才有)
                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                 }
             }
         }
     }
2.2 获取拦截器
 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     //返回HandlerExecutionChain  其中包含了拦截器队列
     mappedHandler = getHandler(processedRequest);
 }
 //返回HandlerExecutionChain
 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
     return executionChain;
 }
 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
         HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
         //根据url和拦截器异常的配置url做对比,若符合则加入队列
         String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
         for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
             if (interceptor instanceof MappedInterceptor) {
                 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                     chain.addInterceptor(mappedInterceptor.getInterceptor());
                 }
             }
             else {
                 chain.addInterceptor(interceptor);
             }
         }
         return chain;
 }
 public boolean matches(String lookupPath, PathMatcher pathMatcher) {
         PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher;
         if (this.excludePatterns != null) {
             for (String pattern : this.excludePatterns) {
                 if (pathMatcherToUse.match(pattern, lookupPath)) {
                     return false;
                 }
             }
         }
         if (this.includePatterns == null) {
             return true;
         }
         else {
             for (String pattern : this.includePatterns) {
                 if (pathMatcherToUse.match(pattern, lookupPath)) {
                     return true;
                 }
             }
             return false;
         }
 }
上述的拦截器的信息,都来自与下面的配置文件
<!-- 拦截器链 -->
<mvc:interceptors> <mvc:interceptor>
<!--拦截器mapping 符合的才会执行拦截器-->
<mvc:mapping path="/**"/>
<!--在拦截器mapping中除去下面的url -->
<mvc:exclude-mapping path="/transactional_test/*"/>
<!--执行的拦截器-->
<ref bean="apiInterceptor"/>
</mvc:interceptor>
</mvc:interceptors> <bean id="apiInterceptor" class="com.lk.dome.interceptor.ApiInterceptor"/>
---------------------
2.3 处理拦截器
 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             for (int i = 0; i < interceptors.length; i++) {
                 HandlerInterceptor interceptor = interceptors[i];
                 //若返回false,则直接执行拦截器的triggerAfterCompletion方法
                 if (!interceptor.preHandle(request, response, this.handler)) {
                     triggerAfterCompletion(request, response, null);
                     //直接返回,在外层的doDispatch逻辑中不执行后面的逻辑
                     return false;
                 }
                 //记录成功执行的拦截器个数
                 this.interceptorIndex = i;
             }
         }
         return true;
 }
 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             //拦截器队列从后往前之心,顺序相反
             for (int i = interceptors.length - 1; i >= 0; i--) {
                 HandlerInterceptor interceptor = interceptors[i];
                 interceptor.postHandle(request, response, this.handler, mv);
             }
         }
 }
 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
             throws Exception {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             //interceptorIndex为执行成功的拦截器标志
             for (int i = this.interceptorIndex; i >= 0; i--) {
                 HandlerInterceptor interceptor = interceptors[i];
                 try {
                     interceptor.afterCompletion(request, response, this.handler, ex);
                 }
                 catch (Throwable ex2) {
                     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
                 }
             }
         }
 }
 //异步方法调用,拦截器必须属于AsyncHandlerInterceptor接口
 void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             for (int i = interceptors.length - 1; i >= 0; i--) {
                 if (interceptors[i] instanceof AsyncHandlerInterceptor) {
                     try {
                         AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
                         asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
                     }
                     catch (Throwable ex) {
                         logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
                     }
                 }
             }
         }
 }
springMVC之Interceptor拦截器的更多相关文章
- SpringMvc中Interceptor拦截器用法
		
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆等. 一. 使用场景 1 ...
 - SpringMVC中使用Interceptor拦截器
		
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...
 - SpringMVC 中的Interceptor 拦截器
		
1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors> <!-- 日志拦截器 --> <mvc:interceptor> ...
 - SpringMVC中使用Interceptor拦截器顺序
		
一.简介 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验 证,或者是来判断用户是否登陆,或者是像1 ...
 - SpringMVC中的Interceptor拦截器及与Filter区别
		
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...
 - springmvc中的拦截器interceptor用法
		
1.配置拦截器 在springMVC.xml配置文件增加: 1 <mvc:interceptors> 2 <!-- 日志拦截器 --> 3 <mvc:intercepto ...
 - [转]SpringMVC中使用Interceptor拦截器
		
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...
 - SpringMVC之七:SpringMVC中使用Interceptor拦截器
		
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...
 - 9.springMVC中的拦截器
		
springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...
 
随机推荐
- 字符串匹配--扩展KMP模板
			
对于一个字符串 s 以及子串 t ,扩展KMP可以用来求 t 与 s 的每个子串的最长公共前缀 ext [ i ],当然,如果有某个 ext 值等于 t 串的长度 lent ,那么就说明从其对应的 i ...
 - FSTConfiguration 高性能序列化框架FST
			
转自:https://blog.csdn.net/z69183787/article/details/53005961 fst是完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍 ...
 - day9 python学习 文件的操作 读 写 seek
			
文件的操作 1 文件的打开操作: 文件句柄 = open('文件路径', '模式') f=open('wangyakun','a+',encoding='utf-8') #文件名, 如果是绝对路径 ...
 - 无法对 数据库'XXXXX' 执行 删除,因为它正用于复制
			
无法对 数据库'XXXXX' 执行 删除,因为它正用于复制. (.Net SqlClient Data Provider) 使用以下方式一般可以解决 sp_removedbreplication 'X ...
 - pykd试用
			
啥是pykd? 一个windbg插件,能在windbg里面运行python指令 试用步骤 下载from https://pykd.codeplex.com/releases/view/615625 解 ...
 - 浏览器同源策略,跨域请求jsonp
			
浏览器的同源策略 浏览器安全的基石是"同源政策"(same-origin policy) 含义: 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这 ...
 - java 字符串String
			
在 Java 中,字符串被作为 String 类型的对象处理. String 类位于 java.lang 包中.默认情况下,该包被自动导入所有的程序. 创建 String 对象的方法: 只要是双引号标 ...
 - 远程连接linux服务器mysql
			
今天遇到一个问题 无法远程链接mysql Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQ先解决第一个提 ...
 - 【Spring-AOP-学习笔记-4】@After后向增强处理简单示例
			
说明 After增强处理的作用非常类似于异常处理中的finally块的作用,无论如何,他总会在方法执行结束之后被织入,因此特别适应于垃圾回收. 项目结构 程序 @Component("hel ...
 - PAT 乙级 1038 统计同成绩的学生C++版
			
1038. 统计同成绩学生(20) 时间限制 250 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求读入N名学生的成绩,将 ...