Spring Boot源码之旅三十五SpringMVC源码细节之拦截器

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

 

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

 

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

 

执行链结构图

拦截器哪里来的

执行链前面讲过,但是没细讲,我们先来看他是怎么形成的。首先是在EnableWebMvcConfiguration的父类WebMvcConfigurationSupportgetInterceptors里面会添加自定义的拦截器,然后再加入两个拦截器:

这些拦截器干嘛的

MyHandlerInterceptor自定义的

只是输出信息。

ConversionServiceExposingInterceptor

设置请求的转换服务,这个后面跟数据绑定相关,到时候会说的。

ResourceUrlProviderExposingInterceptor

设置静态资源url提供器,让客户端可以访问静态资源。

拦截器处理

遍历所有的拦截器,进行preHandle调用,如果返回true就继续并执行的拦截器索引,否则就直接后处理返回了,这里interceptorIndex是为了后面的处理可以反向进行遍历,其实就是类似于netty的出站入站处理,有兴趣的可以看看我的netty文章,数据进来的时候是顺序拦截,出去的时候是反的拦截,类似责任链,拦截器模式。

applyPreHandle

    	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];
    				if (!interceptor.preHandle(request, response, this.handler)) {
    					triggerAfterCompletion(request, response, null);//如果是false就直接返回
    					return false;
    				}
    				this.interceptorIndex = i;
    			}
    		}
    		return true;
    	}

applyPostHandle

这里就开始反向拦截了。

    	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable 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);
    			}
    		}
    	}

triggerAfterCompletion

处理完成后进行,这里就要用到interceptorIndex,反向执行,因为有可能有拦截器返回false了,然后只处理前面处理过的拦截器的triggerAfterCompletion方法。

    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
    			throws Exception {
    
    		HandlerInterceptor[] interceptors = getInterceptors();
    		if (!ObjectUtils.isEmpty(interceptors)) {
    			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);
    				}
    			}
    		}
    	}

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值