转自: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拦截器的更多相关文章

  1. SpringMvc中Interceptor拦截器用法

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆等. 一. 使用场景 1 ...

  2. SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  3. SpringMVC 中的Interceptor 拦截器

    1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors>  <!-- 日志拦截器 -->  <mvc:interceptor> ...

  4. SpringMVC中使用Interceptor拦截器顺序

    一.简介 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验 证,或者是来判断用户是否登陆,或者是像1 ...

  5. SpringMVC中的Interceptor拦截器及与Filter区别

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  6. springmvc中的拦截器interceptor用法

    1.配置拦截器 在springMVC.xml配置文件增加: 1 <mvc:interceptors> 2 <!-- 日志拦截器 --> 3 <mvc:intercepto ...

  7. [转]SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  8. SpringMVC之七:SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  9. 9.springMVC中的拦截器

    springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...

随机推荐

  1. 字符串匹配--扩展KMP模板

    对于一个字符串 s 以及子串 t ,扩展KMP可以用来求 t 与 s 的每个子串的最长公共前缀 ext [ i ],当然,如果有某个 ext 值等于 t 串的长度 lent ,那么就说明从其对应的 i ...

  2. FSTConfiguration 高性能序列化框架FST

    转自:https://blog.csdn.net/z69183787/article/details/53005961 fst是完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍 ...

  3. day9 python学习 文件的操作 读 写 seek

    文件的操作 1   文件的打开操作: 文件句柄 = open('文件路径', '模式') f=open('wangyakun','a+',encoding='utf-8') #文件名, 如果是绝对路径 ...

  4. 无法对 数据库'XXXXX' 执行 删除,因为它正用于复制

    无法对 数据库'XXXXX' 执行 删除,因为它正用于复制. (.Net SqlClient Data Provider) 使用以下方式一般可以解决 sp_removedbreplication 'X ...

  5. pykd试用

    啥是pykd? 一个windbg插件,能在windbg里面运行python指令 试用步骤 下载from https://pykd.codeplex.com/releases/view/615625 解 ...

  6. 浏览器同源策略,跨域请求jsonp

    浏览器的同源策略 浏览器安全的基石是"同源政策"(same-origin policy) 含义: 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这 ...

  7. java 字符串String

    在 Java 中,字符串被作为 String 类型的对象处理. String 类位于 java.lang 包中.默认情况下,该包被自动导入所有的程序. 创建 String 对象的方法: 只要是双引号标 ...

  8. 远程连接linux服务器mysql

    今天遇到一个问题  无法远程链接mysql Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQ先解决第一个提 ...

  9. 【Spring-AOP-学习笔记-4】@After后向增强处理简单示例

    说明 After增强处理的作用非常类似于异常处理中的finally块的作用,无论如何,他总会在方法执行结束之后被织入,因此特别适应于垃圾回收. 项目结构 程序 @Component("hel ...

  10. PAT 乙级 1038 统计同成绩的学生C++版

    1038. 统计同成绩学生(20) 时间限制 250 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求读入N名学生的成绩,将 ...