Spring MVC源码篇 刺骨的言语ヽ痛彻心扉 2022-11-24 14:22 163阅读 0赞 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70][] ### 第一步 加载默认策略 ### DispatcherServlet类加载的时候会执行其static代码块,其中读取其内部的DispatcherServlet.properties属性文件加载所有配置的属性,以key,value的形式加载到名为defaultStrategies的Properties中作为其默认的策略。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 1][] 上面的DEFAULT\_STRATEGIES\_PATH就是文件名DispatcherServlet.properties,看下这个属性文件包含了哪些: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 2][] 其中比较常用的: 两个HandlerMapping: 1.BeanNameUrlHandlerMapping Request到Controller的映射 request-bean 比如"/test"的请求会映射到加上@Component("/test")这个注解并且实现了Controller接口的bean 其底层存了一个key为request,value为bean的map 2.RequestMappingHandlerMapping Request到Controller的映射 request-method 就是我们常用的@RequestMapping注解,请求会被映射到具体的方法 其底层存了一个key为request,value为method的map 三个HandlerAdapter: 1.RequestMappingHandlerAdapter 主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器,其实就是对应上面的RequestMappingHandlerMapping 2.SimpleControllerHandlerAdapter 适配实现了Controller接口或Controller接口子类的处理器,其实就是对应上面的BeanNameUrlHandlerMapping 3.HttpRequestHandlerAdapter 主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。 一个ViewResolver: InternalResourceViewResolver(到具体页面的视图解析器) ### 第二步 初始化DispatcherServlet ### 加载完配置之后,就是初始化了。当web容器启动的时候,Servlet会执行初始化,具体的调用链路是 HttpServletBean\#init方法 -> FrameworkServlet\#initServletBean -> DispatcherServlet\#onRefresh -> DispatcherServlet\#initStrategies ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 3][] initMultipartResolver(context)用来初始化上传文件的bean,里面是固定使用multipartResolver这个名字去spring容器中获取bean的,所以这里也可以看出spring为什么规定上传文件的bean名字必须是multipartResolver。 后面开始初始化各种从DispatcherServlet.properties中加载到的组件,这里以initHandlerMappings为例: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 4][] 所以如果我们自定义一个handlerMapping通过bean的形式注入的话,spring就会抛弃掉默认的了! ### 第三步请求进来 ### 其实第二步之后springmvc的初始化步骤就完成了,之后请求通过HttpServlet的doGet或者doPost,通过调用链最终调到DispatcherServlet的doDispatch方法。 doDispatch方法主要做了这么几件事情: 第一件处理文件上传 第二件通过请求匹配对应的处理器映射器HandlerMapping(就是上面讲的两个) 具体代码在getHandler方法中: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 5][] 这里首先遍历所有的handlerMappings,找到符合的handlerMapping,我们还是已RequestMappingHandlerMapping为例,看下他的getHandler方法,这个方法其实是其父类AbstractHandlerMapping的: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 6][] 其实AbstractHandlerMapping基本上是所有handlerMapping的父类,最终返回的都是一个HandlerExecutionChain对象, 不同的就是这个getHandlerInternal方法,它其实是AbstractHandlerMapping的一个抽象方法,须要子类实现的,可以看到spring将其返回值定义为了object,最终这个handler会被包装到HandlerExecutionChain对象中(其中还会包含几个拦截器对象)。 也就是说每个handlerMapping返回的handler可能都不一样!RequestMappingHandlerMapping返回的就是一个HandlerMethod对象(意味着请求到方法的映射,也符合@RequestMapping注解的使用方式),BeanNameUrlHandlerMapping返回的就是一个Object对象(其实就是对应一个Controller对象,也符合请求到bean的映射关系) 这里还是说RequestMappingHandlerMapping的getHandlerInternal方法: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 7][] 主要是利用了lookupHandlerMethod方法找到了这个映射,这个方法中主要是利用了一个MappingRegistry对象获取到映射: ![20200806160301428.png][] MappingRegistry中就定义了许多的map存储这些映射关系, ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 8][] 那么这些映射关系是什么时候维护起来的呢?事实上是RequestMappingHandlerMapping实现了InitializingBean接口,当其实例化之后会调用afterPropertiesSet方法,意思就是当RequestMappingHandlerMapping初始化时扫描出这些映射关系出来,具体的调用链路: AbstractHandlerMethodMapping\#afterPropertiesSet方法 -> AbstractHandlerMethodMapping\#initHandlerMethods方法 -> AbstractHandlerMethodMapping\#detectHandlerMethods方法 -> AbstractHandlerMethodMapping\#registerHandlerMethod方法 -> MappingRegistry\#register方法。 其中在initHandlerMethods方法中Spring会获取所有的beanNames,然后拿到其类型,判断这个类型是否符合扫描标准: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 9][] ![20200806160516420.png][] 可以看到加了@Controller或者@RequestMapping的bean会被扫描! 第三件通过HandlerExecutionChain的getHandler方法匹配到对应的处理器适配器HandlerAdapter 具体代码在getHandlerAdapter方法中: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 10][] ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 11][] 对应的RequestMappingHandlerAdapter的supports方法: ![20200806160806402.png][] 因为RequestMappingHandlerMapping返回的是一个HandlerMethod对象,所以这里RequestMappingHandlerAdapter将被匹配到并返回出来。 第四件通过HandlerAdapter处理请求 处理请求主要下面几步: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 12][] 我们关键来看下处理请求的方法,其调用链是: RequestMappingHandlerAdapter\#handle方法 -> RequestMappingHandlerAdapter\#handleInternal方法 -> RequestMappingHandlerAdapter\#invokeHandlerMethod方法 invokeHandlerMethod方法中实例化了一个ServletInvocableHandlerMethod对象,并且对这个对象设置了两个比较重要的属性argumentResolvers和returnValueHandlers: ![20200806162149406.png][] 这两个参数的初始化同样是RequestMappingHandlerAdapter利用了InitializingBean接口 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 13][] argumentResolvers用来将请求中的参数绑定到方法的参数中。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 14][] returnValueHandlers则能够根据方法执行的返回值来确定如何解析视图。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 15][] 后面执行这个ServletInvocableHandlerMethod对象的invokeAndHandle方法, ![20200806162455190.png][] ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 16][] **point1:** 执行invokeForRequest方法其实就是执行我们真正的方法: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 17][] **point2:** 设置ResponseStatus,对应的是@ResponseStatus注解,可以指定响应的响应码和异常的文案 **point3&point4:** 如果有响应码或者响应异常,设置requestHandled属性为true **point5:** returnValueHandlers.handleReturnValue就是匹配到HandlerMethodReturnValueHandler来处理我们的响应。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 18][] ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 19][] 这里已两个常用的HandlerMethodReturnValueHandler为例: ### RequestResponseBodyMethodProcessor ### ![20200806163009456.png][] 可以看到RequestResponseBodyMethodProcessor可以处理加了@ResponseBody注解的方法返回值。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 20][] writeWithMessageConverters中有一个关键的代码,会遍历所有的HttpMessageConverters,找到匹配的然后写出去,最终调用的是HttpServletResponse\#write方法。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 21][] ### ModelAndViewMethodReturnValueHandler ### ![20200806163119657.png][] 可以看到ModelAndViewMethodReturnValueHandler可以处理返回值类型是ModelAndView的方法,看下他的handleReturnValue方法: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 22][] 可以看到方法内部其实就是先将返回值强转为ModelAndView,然后将ModelAndView中的相关参数赋值给了ModelAndViewContainer对象,这个对象是在执行RequestMappingHandlerAdapter\#invokeHandlerMethod方法的时候new出来的,并且在执行ServletInvocableHandlerMethod\#invokeAndHandle作为参数传了进去,最终当invokeAndHandle方法执行完毕之后,又将ModelAndViewContainer对象转成了ModelAndView返回。 ![20200806163211689.png][] ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 23][] 这里有个地方可以看到如果requestHandled是true的时候,就直接返回null,这个场景就是上面说的当有响应码或者响应异常时会设为true,另外当响应处理器是RequestResponseBodyMethodProcessor时也会设为true,这种场景直接输出json或者其他文本,也不需要返回视图。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70]: /images/20221124/3eb103ebc97c41cc94ff422090e15426.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 1]: /images/20221124/f1b0a95fc39a42a29d8d877d9ac945ca.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 2]: /images/20221124/e93f0f890d924dce920cd0e4206ec819.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 3]: /images/20221124/2ec35b8ae98a4d1e90b451d3d09cc23f.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 4]: /images/20221124/904d7fedbba7413a9278d71fd2e7fb62.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 5]: /images/20221124/954d7c11dbfd4c1abe0690f999307b88.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 6]: /images/20221124/6b2eb1d8bd9248298250a00d389e4a4d.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 7]: /images/20221124/dd273364c6474b48b4c344f0c00c298c.png [20200806160301428.png]: /images/20221124/84f1543a92f04b08bb421ab422dfdfed.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 8]: /images/20221124/09db969d9c904a6f80781bc834057891.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 9]: /images/20221124/f06bc8df02424aec81f1d07a00c33025.png [20200806160516420.png]: /images/20221124/dc73deb3d05941b284a0837ba27056bf.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 10]: /images/20221124/31efffd7bdfc44d2b102f070c04b5a79.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 11]: /images/20221124/f8a5cc1169dd4fdbace0e2a4d6dcf141.png [20200806160806402.png]: /images/20221124/8aeeb70456aa460e8445ed6228e182d8.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 12]: /images/20221124/f9abb00bbc5a4673b3029b3027df0c2a.png [20200806162149406.png]: /images/20221124/a4a163d81ba440b89b7894d9f351e5e4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 13]: /images/20221124/6bd30b1687c8461e90151371c4674171.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 14]: /images/20221124/54e9df44036248a498cebde81f6f3362.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 15]: /images/20221124/7d649bf4b2a649a2b3235afce7ac3f7b.png [20200806162455190.png]: /images/20221124/001be022c59f4f6da986e5384fe5dc40.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 16]: /images/20221124/3560b639856247ed8900efaa34894450.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 17]: /images/20221124/ac92dcb70e3042fb9c291d54f6564486.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 18]: /images/20221124/f13d79fe3aa44c87a2e2f53c74782758.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 19]: /images/20221124/6a2522e7aff847dda5e424436fdb75e1.png [20200806163009456.png]: /images/20221124/804b00a645c849bc8fd8d7ea875e518a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 20]: /images/20221124/bb6f3affbd5941ea9f248b4316719293.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 21]: /images/20221124/e0b328f801524aa9b7e48fc93348ebc3.png [20200806163119657.png]: /images/20221124/6dbf4f10e2b44c6ea02d16c51fe5b110.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 22]: /images/20221124/4ba3ca157321431abc8a5574fba6f310.png [20200806163211689.png]: /images/20221124/7bab426afc504fceb2e4d03ed324f5f2.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE1MzU1NDE_size_16_color_FFFFFF_t_70 23]: /images/20221124/e40e135358794036b7a9541d5b121282.png
还没有评论,来说两句吧...