SpringMVC 源码剖析

ops/2024/10/21 10:16:28/

SpringMVC 源码剖析

在这里插入图片描述

0 从源码角度分析SpringMVC执行流程

// 前端控制器,SpringMVC最核心的类
public class DispatcherServlet extends FrameworkServlet {// 前端控制器最核心的方法,这个方法是负责处理请求的,一次请求,调用一次 doDispatch 方法。protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {// 通过请求获取处理器// 请求:http://localhost:8080/springmvc/hello (有URI)// 根据请求路径来获取对应的要执行的处理器// 实际上返回的是一个处理器执行链对象// 这个执行链(链条)把谁串起来了呢?把这一次请求要执行的所有拦截器和处理器串起来了。// HandlerExecutionChain是一次请求对应一个对象HandlerExecutionChain mappedHandler = getHandler(request);// 根据处理器获取处理器适配器对象HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Handler就是我们写的Controller// 执行该请求对应的所有拦截器中的 preHandle 方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 调用处理器方法,返回ModelAndView对象// 在这里进行的数据绑定,实际上调用处理器方法之前要给处理器方法传参// 需要传参的话,这个参数实际上是要经过一个复杂的数据绑定过程(将前端提交的表单数据转换成POJO对象)mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 执行该请求对应的所有拦截器中的 postHandle 方法mappedHandler.applyPostHandle(processedRequest, response, mv);// 处理分发结果(本质上就是响应结果到浏览器)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {// 渲染render(mv, request, response);// 执行该请求所对应的所有拦截器的afterCompletion方法mappedHandler.triggerAfterCompletion(request, response, null);}protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {// 通过视图解析器进行解析,返回视图View对象View view = resolveViewName(viewName, mv.getModelInternal(), locale, request);// 调用视图对象的渲染方法(完成响应)view.render(mv.getModelInternal(), request, response);}protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,Locale locale, HttpServletRequest request) throws Exception {// 视图解析器ViewResolver viewResolver;// 通过视图解析器解析返回视图对象ViewView view = viewResolver.resolveViewName(viewName, locale);}
}// 视图解析器接口
public interface ViewResolver {View resolveViewName(String viewName, Locale locale) throws Exception;
}// 视图解析器接口实现类也很多:ThymeleafViewResolver、InternalResourceViewResolver// 视图接口
public interface View{void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)throws Exception;
}// 每一个接口肯定是有接口下的实现类,例如View接口的实现类:ThymeleafView、InternalResourceView....

1 关于根据请求获取处理器执行链

分析这一行代码:
HandlerExecutionChain mappedHandler = getHandler(request);1. HandlerExecutionChain:处理器执行链对象2. HandlerExecutionChain中的属性:public class HandlerExecutionChain{// 底层对应的是一个HandlerMethod对象// 处理器方法对象Object handler = new HandlerMethod(.....);// 该请求对应的所有的拦截器按照顺序放到了ArrayList集合中// 所有的拦截器对象也都是在服务器启动的时候都创建好。List<HandlerInterceptor> interceptorList;}3. HandlerMethod 是什么?HandlerMethod是最核心的要执行的目标,翻译为:处理器方法。注意:HandlerMethod 是在web服务器启动时初始化spring容器的时候,就创建好了。这个类当中比较重要的属性包括:beanName和Method例如,以下代码:@Controller("userController")public class UserController{@RequestMapping("/login")public String login(User user){return ....}}那么以上代码对应了一个HandlerMethod对象:public class HandlerMethod{private String beanName = "userController";private Method loginMethod;}4. getHandler(request);这个方法还是在DispatcherServlet类中。protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {// 通过合适的 HandlerMapping才能获取到 HandlerExecutionChain对象。// 如果你处理器方法使用了 @RequestMapping注解,那么以下代码中的mapping是:RequestMappingHandlerMapping对象。HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}重点:我们处理请求的第一步代码是:HandlerExecutionChain mappedHandler = getHandler(request);其本质上是调用了:HandlerExecutionChain handler = mapping.getHandler(request);mapping变量就是 HandlerMappingHandlerMapping是一个接口:翻译为处理器映射器,专门负责映射的。就是本质上根据请求路径去映射处理器方法的。HandlerMapping接口下有很多实现类:例如其中一个比较有名的,常用的:RequestMappingHandlerMapping这个 RequestMappingHandlerMapping 叫做:@RequestMapping注解专用的处理器映射器对象。当然,如果你没有使用 @RequestMapping注解,也可以写xml配置文件来进行映射,那个时候对应的就是其他的HandlerMapping接口的实现类了。HandlerMapping 对象也是在服务器启动阶段创建的,所有的HandlerMapping对象都是在服务器启动阶段创建,并且存放到集合中。public class DispatcherServlet{List<HandlerMapping> handlerMappings;}5. RequestMappingHandlerMapping中的 getHandler(request);HandlerExecutionChain handler = mapping.getHandler(request);mapping.getHandler(request);这个方法底层一定是获取了 HandlerMethod 对象,将其赋值给 HandlerExecutionChain的handler属性public class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping{protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {super.registerHandlerMethod(handler, method, mapping);updateConsumesCondition(mapping, method);}}public class AbstractHandlerMethodMapping{protected void registerHandlerMethod(Object handler, Method method, T mapping) {this.mappingRegistry.register(mapping, handler, method);}public void register(T mapping, Object handler, Method method) {HandlerMethod handlerMethod = createHandlerMethod(handler, method);}protected HandlerMethod createHandlerMethod(Object handler, Method method) {if (handler instanceof String beanName) {return new HandlerMethod(beanName,obtainApplicationContext().getAutowireCapableBeanFactory(),obtainApplicationContext(),method);}return new HandlerMethod(handler, method);}}这一步牵连到的类有哪些:HandlerExecutionChainHandlerMethodHandlerInterceptorHandlerMappingRequestMappingHandlerMapping(是HandlerMaping接口的实现)

2 关于根据处理器来获取处理器适配器

分析:
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());1. 底层使用了适配器模式。2. 每一个处理器(我们自己写的Controller),都有自己适合的处理器适配器。3.SpringMVC当中处理器适配器也有很多种,其中一个比较有名的,常用的处理器适配器是:RequestMappingHandlerAdapter
这个处理器适配器是专门处理 “处理器方法”上有 @RequestMapping 注解的。4. mappedHandler.getHandler() 获取的是 HandlerMethod 对象5. HandlerAdapter也是一个接口:其中有一个常用的实现类:RequestMappingHandlerAdapter6. 在服务器启动阶段,所有的 HandlerAdapter接口的实现类都会创建出来。在服务器启动阶段!!!!!!List<HandlerAdapter> handlerAdapters;7. HandlerAdapter接口非常重要,通过这个接口来调用最终的 HandlerMethod8. HandlerAdapter是适配器,是对 HandlerMethod 进行的适配。9.DispatcherServlet类中,如下代码:protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}}

3 关于执行请求对应的拦截器preHandle

关于执行请求对应的拦截器的preHandle方法DispatcherServlet:
if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;
}HandlerExecutionChainboolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;
}遍历List集合,从List集合中取出每一个 HandlerInterceptor对象,调用 preHandle,i++,可见是顺序调用。

4 关于调用处理器方法

关于调用处理器方法:mv = ha.handle(processedRequest, response, mappedHandler.getHandler());ha 是处理器适配器mv 是ModelAndView对象这个方法是最核心的,调用请求路径对应的HandlerMethod。(调用处理器方法。)ha是HandlerAdapter,如果是 @RequestMapping 注解对应的,那么就是 RequestMappingHandlerAdapterRequestMappingHandlerAdapterprotected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {mav = invokeHandlerMethod(request, response, handlerMethod);}protected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {// 获取一个数据绑定工厂WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);// 获取一个可调用的处理器方法ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);// 给可调用的方法绑定数据invocableMethod.setDataBinderFactory(binderFactory);// 给可调用的方法设置参数invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);// 可调用的方法执行了。invocableMethod.invokeAndHandle(webRequest, mavContainer);}HandlerAdapter中做的核心事情:将前端提交的form数据通过 HttpMessageConverter 将其转换成 POJO对象。(数据转换)并将数据绑定到 HandlerMethod 对象上。调用HandlerMethod。返回 ModelAndView

5 关于执行请求对应的拦截器的postHandle

DispatcherServlet:mappedHandler.applyPostHandle(processedRequest, response, mv);HandlerExecutionChain:void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler, mv);}}通过源码解决,可以很轻松的看到,从List集合中逆序(i--)逐一取出拦截器对象,并且调用拦截器的 postHandle方法。

6 关于处理分发结果

public class DispatcherServlet{// 处理分发结果processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {// 渲染render(mv, request, response);}protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {// 通过视图解析器进行解析,返回视图View对象View view = resolveViewName(viewName, mv.getModelInternal(), locale, request);// 调用视图对象的渲染方法(完成响应)view.render(mv.getModelInternal(), request, response);}protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,Locale locale, HttpServletRequest request) throws Exception {// 视图解析器ViewResolver viewResolver;// 通过视图解析器解析返回视图对象ViewView view = viewResolver.resolveViewName(viewName, locale);}
}// 视图解析器接口
public interface ViewResolver {View resolveViewName(String viewName, Locale locale) throws Exception;
}// 视图解析器接口实现类也很多:ThymeleafViewResolver、InternalResourceViewResolver// 视图接口
public interface View{void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)throws Exception;
}// 每一个接口肯定是有接口下的实现类,例如View接口的实现类:ThymeleafView、InternalResourceView....

7 关于执行拦截器的afterCompletion方法

DispatcherServlet:private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {// 渲染render(mv, request, response);// 执行该请求所对应的所有拦截器的afterCompletion方法mappedHandler.triggerAfterCompletion(request, response, null);}HandlerExecutionChain:void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);try {interceptor.afterCompletion(request, response, this.handler, ex);}catch (Throwable ex2) {logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);}}}通过源码可以看出,也是通过逆序(i--)的方式进行拦截器的调用,调用拦截器的afterCompletion方法。

http://www.ppmy.cn/ops/22123.html

相关文章

装饰器模式、代理模式、适配器模式对比

装饰器模式、代理模式和适配器模式都是结构型设计模式&#xff0c;它们的主要目标都是将将类或对象按某种布局组成更大的结构&#xff0c;使得程序结构更加清晰。这里将装饰器模式、代理模式和适配器模式进行比较&#xff0c;主要是因为三个设计模式的类图结构相似度较高、且功…

React的基础概念

React是什么&#xff1f; React由Meta公司研发&#xff0c;是一个用于 构建Web和原生交互界面的库 React的优势 相较于传统基于DOM开发的优势 组件化的开发方式不错的性能 相较于其它前端框架的优势 丰富的生态跨平台支持 大厂使用比较多&#xff0c;小厂用vue的比较多

[SQL系列]从零开始学Clickhouse

起因 听说2024年开始金三银四了&#xff0c;所以我和我的小伙伴们也抱着再去拿一些Offer的准备。但是一上来就蒙了&#xff0c;对方问&#xff0c;听说你对数据库非常熟悉&#xff0c;那就说说ClickHouse吧。 这怎么就不按套路出牌呢&#xff1f;不一般就问Mysql的InnoDB嘛。 赶…

设计模式学习笔记 - 项目实战一:设计实现一个支持各种算法的限流框架(设计)

概述 上篇文章&#xff0c;我们介绍了限流框架产生的项目背景&#xff0c;并对需求做了分析&#xff0c;这其中包括功能性需求和非功能性需求。 前面提到&#xff0c;我们把项目实现分为分析、设计、实现三部分来讲解。其中&#xff0c;分析环境跟之前讲过的面向对象分析很相…

uniapp分包,以及通过uni-simple-router进行分包

先说一下uniapp的直接分包方式&#xff0c;很简单&#xff1a; 配置分包信息 打开manifest.json源码视图&#xff0c;添加 “optimization”:{“subPackages”:true} 开启分包优化 我们在根目录下创建一个pagesA文件夹&#xff0c;用来放置需要分包的页面 然后配置路由 运行到…

C#基础之选择排序

选择排序 文章目录 选择排序1、概念2、代码实现 1、概念 1、新建一个下标 int index 0; 2、依次比较 3、找出极值 arr[index] < arr[n] 4、放入目标 //数组长度-1-n轮从第0轮开始 5、比较n轮2、代码实现 int[] arr new int[]{8,7,1,5,4,2,6,3,9}; 第一步 声明索引0&…

生成对抗网络的无载体信息隐藏算法简介

一、研究背景 随着互联网技术的广泛应用和移动智能设备的快速普及&#xff0c;人们有了更多的途径传播和获取信息。每天海量的数据以视频、音频、图像、文字等各类形式在互联网中产生&#xff0c;这为人们的生活带来了极大的便利&#xff0c;但同时也引起了人们对信息泄露的担…

Java基础知识总结(77)

* 2、JMM模型 JMM&#xff08;Java Memory Model&#xff09;&#xff1a;Java 内存模型&#xff0c;是 Java 虚拟机规范中所定义的一种内存模型&#xff0c;Java 内存模型是标准化的&#xff0c;屏蔽掉了底层不同计算机的区别。也就是说&#xff0c;JMM 是 JVM 中定义的一种并…