Spring-MVC核心流程及源码解析

1.SpringMVC核心流程图

#SpringMVC具体解析步骤:

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找)

第三步:处理器映射器HandlerMapping向前端控制器返回Handler,
HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,
多个HandlerInterceptor拦截器对象), 通过这种策略模式,很容易添加新的映射策略

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView ModelAndView是springmvc框架的一个底层对象,包括 Model和view

第八步:前端控制器请求视图解析器去进行视图解析 
根据逻辑视图名解析成真正的视图(jsp),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染 
视图渲染将模型数据(在ModelAndView对象中)填充到request域

第十一步:前端控制器向用户响应结果
Spring-MVC核心流程及源码解析_第1张图片
Spring-MVC核心流程图.png
#总结 核心开发步骤(SpringMVC, 非 SpringBoot)
1.DispatcherServlet 在 web.xml 中的部署描述,从而拦截请求到 Spring Web MVC
2.HandlerMapping 的配置,从而将请求映射到处理器
3.HandlerAdapter 的配置,从而支持多种类型的处理器
注:处理器映射求和适配器使用注解(如@RequestMapping)的话包含在了注解驱动中,不需要再单独配置
4.ViewResolver 的配置,从而将逻辑视图名解析为具体视图技术
5.处理器(页面控制器)的配置,从而进行功能处理 
6.View是一个接口,实现类支持不同的View类型(jsp, freemarker, pdf...)

2.源码分析

2.1 核心类DispatcherServlet 分析

Spring-MVC核心流程及源码解析_第2张图片
DispatcherServlet继承关系图.png
Spring-MVC核心流程及源码解析_第3张图片
DispatcherServlet类图.png
Spring-MVC核心流程及源码解析_第4张图片
访问一个RequestMapping时main线程调用链--前半部分.png
#访问一个RequestMapping时main线程调用链--后半部分

--> DispatcherServlet#doDispatch
    --> DispatcherServlet#checkMultipart
        // StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/") ?
        --> StandardServletMultipartResolver#isMultipart
            --> StandardServletMultipartResolver#resolveMultipart
                --> StandardMultipartHttpServletRequest#StandardMultipartHttpServletRequest(HttpServletRequest, boolean)
                    --> StandardMultipartHttpServletRequest#parseRequest
                        --> AbstractMultipartHttpServletRequest#setMultipartFiles
    // WebEndpointServletHandlerMapping, ControllerEndpointHandlerMapping, BeanNameHandlerMapping
    // RequestMappingHandlerMapping --> @RequestMapping 注解对应的 handlerMapping --> 这里运用到了 策略模式
    // 这一步获取 handler 及 interceptorList (拦截器列表), 若为空, 则报 404 或其他错误
    --> DispatcherServlet#getHandler
        --> AbstractHandlerMapping#getHandler               
            --> AbstractHandlerMapping#getHandlerExecutionChain
    // HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter
    // RequestMappingHandlerAdapter --> @RequestMapping 注解对应的 handlerAdapter
    // 传入 handler, 获取 HandlerAdapter --> 这里运用到了 策略模式
    --> DispatcherServlet#getHandlerAdapter
    // 遍历上文获得的 interceptors 数组, 调用各个 HandlerInterceptor 的 preHandle 方法
    --> HandlerExecutionChain#applyPreHandle
        --> HandlerInterceptor#preHandle
    // 真正开始 通过 HandlerAdapter 调用 handler, 如 RequestMappingHandlerAdapter, 返回 ModelAndView
    --> AbstractHandlerMethodAdapter#handle
        --> RequestMappingHandlerAdapter#handleInternal
            --> RequestMappingHandlerAdapter#invokeHandlerMethod
                // 通过反射使用 controller 调用 service 层方法
                --> ServletInvocableHandlerMethod#invokeAndHandle
                    --> ServletInvocableHandlerMethod#invokeAndHandle
                        --> InvocableHandlerMethod#invokeForRequest
                            // 参数解析部分
                            --> InvocableHandlerMethod#getMethodArgumentValues
                                // this.resolvers.supportsParameter(parameter)
                                // this.resolvers.resolveArgument: 这一步中, 解析参数的过程中, 也可能会经过 HttpMessageConverter
                                --> HandlerMethodArgumentResolverComposite#resolveArgument
                                    // 如果加了 @RequestBody 注解, 将会走进这个方法, 最终经过 HttpMessageConverter 转换
                                    --> RequestResponseBodyMethodProcessor#resolveArgument
                                        --> RequestResponseBodyMethodProcessor#readWithMessageConverters
                                            --> AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters(HttpInputMessage, MethodParameter, Type)
                            // 真正通过反射执行方法调用的部分
                            --> InvocableHandlerMethod#doInvoke
                                --> HandlerMethodReturnValueHandlerComposite#handleReturnValue
                                    // 这里以 加了 @ResponseBody 注解 以及 org.springframework.http.MediaType 值的 controller 为例
                                    --> RequestResponseBodyMethodProcessor#handleReturnValue    
                                        --> AbstractMessageConverterMethodProcessor#writeWithMessageConverters(T, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)
                                            // SpringBoot 中默认的 MessageConverter --> MappingJackson2HttpMessageConverter
                                            // genericConverter.write(body, targetType, selectedMediaType, outputMessage);
                                            // 序列化方式
                                            MappingJackson2HttpMessageConverter.write
                        // this.returnValueHandlers.handleReturnValue
                        --> HandlerMethodReturnValueHandlerComposite#handleReturnValue
                            --> HandlerMethodReturnValueHandlerComposite#selectHandler
                            // handler.handleReturnValue, 如果加了 @ResponseBody 注解, 将会走进这个方法, 最终经过 HttpMessageConverter 转换
                            --> RequestResponseBodyMethodProcessor#handleReturnValue
                                --> AbstractMessageConverterMethodProcessor#writeWithMessageConverters(T, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)
                // 返回 ModelAndView, 注意这里是 Buffer, 还不是 String 数据
                --> RequestMappingHandlerAdapter#getModelAndView
    // 获取默认的 视图解析器名称
    --> DispatcherServlet#applyDefaultViewName
    // 遍历上文获得的 interceptors 数组, 调用各个 HandlerInterceptor 的 postHandle 方法
    --> HandlerExecutionChain#applyPostHandle
    // 加工结果: 遍历上文获得的 interceptors 数组, 调用各个 HandlerInterceptor 的 afterCompletion 方法
    --> DispatcherServlet#processDispatchResult
        --> HandlerExecutionChain#triggerAfterCompletion

2.2 WebMvcConfigurationSupport & WebMvcConfigurer

2.2.1 WebMvcConfigurationSupport

Spring-MVC核心流程及源码解析_第5张图片
WebMvcConfigurationSupport继承关系图.png

2.2.2 WebMvcConfigurer

WebMvcConfigurerAdapter 已废弃.

/**
 * @EnableWebMvc 注解驱动的配置类来实现该接口, 从而自定义一些 webmvc 的配置
 */
public interface WebMvcConfigurer {

    /**
     * 配置 HandlerMappings 路径匹配选项, 比如尾部斜杠匹配, 后缀注册, 路径匹配器和路径助手 
     * Configured path matcher and path helper instances are shared for:
     * RequestMappings, ViewControllerMappings, ResourcesMappings
     */
    default void configurePathMatch(PathMatchConfigurer configurer) {}

    /**
     * Configure content negotiation options. --> 消息体
     * 主要是方便一个请求路径返回多个数据格式。
     * ContentNegotiationConfigurer这个配置里面你会看到MediaType,里面有众多的格式
     */
    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}

    /**
     * Configure asynchronous request handling options. 
     * 处理异步请求的。只能设置两个值,
     * 一个超时时间(毫秒,Tomcat下默认是10000毫秒,即10秒),还有一个是AsyncTaskExecutor,异步任务执行器。
     */
    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {}

    /**
     * 将未被匹配到的 handler 转发至此处进行处理。
     * 可以实现静态文件可以像Servlet一样被访问。
     */
    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}

    /**
     * 增加转化器或者格式化器。这边不仅可以把时间转化成你需要时区或者样式。
     * 还可以自定义转化器和你数据库做交互,比如传进来userId,经过转化可以拿到user对象。
     */
    default void addFormatters(FormatterRegistry registry) {}

    /**
     * 添加拦截器. 可以拦截所有 controller 请求, 也可以拦截指定格式的URL.若要拦截静态资源:
     * 要么声明  MappedInterceptor 对象;
     * 要么继承 WebMvcConfigurationSupport 并重写 resourceHandlerMapping 方法.
     */
    default void addInterceptors(InterceptorRegistry registry) {}

    /**
     * 自定义资源映射。添加处理静态资源的 handler 来处理来自 root 路径, classpath, 及其他路径的静态资源:images, js, and, css
     * registry.addResourceHandler("/my/**").addResourceLocations("file:E:/my/"); // windows下, 请加上 file:
     * super.addResourceHandlers(registry);
     */
    default void addResourceHandlers(ResourceHandlerRegistry registry) {}

    /**
     * 配置跨域请求处理
     */
    default void addCorsMappings(CorsRegistry registry) {}

    /**
     * 配置一个路径自动跳转到另一个路径. 前后分离项目, 可以换种思路处理.
     */
    default void addViewControllers(ViewControllerRegistry registry) {}

    /**
     * 配置视图解析器
     */
    default void configureViewResolvers(ViewResolverRegistry registry) {}

    /**
     * 配置参数解析器
     */
    default void addArgumentResolvers(List resolvers) {}

    /**
     * 配置返回值处理的 handlers
     */
    default void addReturnValueHandlers(List handlers) {}

    /**
     * 配置 MessageConverters, 会覆盖已有的 MessageConverter
     */
    default void configureMessageConverters(List> converters) {}

    /**
     * 配置扩展的 MessageConverter, 不会覆盖已有的 MessageConverter
     */
    default void extendMessageConverters(List> converters) {}

    /**
     * 配置异常解析器
     */
    default void configureHandlerExceptionResolvers(List resolvers) {}

    /**
     * 配置扩展的异常解析器
     */
    default void extendHandlerExceptionResolvers(List resolvers) {}

    /**
     * 提供一个自定义的 Validator 来替代默认的 Validator.
     * 默认的实现基于 JSR-303 在 classpath 下, 是:  OptionalValidatorFactoryBean.
     */
    @Nullable
    default Validator getValidator() {
        return null;
    }

    /**
     * 提供一个自定义的 MessageCodesResolver 构建来自 data binding 以及 validation 错误码的 消息编码
     */
    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }

}
Spring-MVC核心流程及源码解析_第6张图片
WebMvcConfigurer继承关系图.png

2.3 RequestMappingHandlerAdapter

Spring-MVC核心流程及源码解析_第7张图片
Step1-->加载配置类.png
Spring-MVC核心流程及源码解析_第8张图片
step2-->创建RequestMappingHandlerAdapter.png
Spring-MVC核心流程及源码解析_第9张图片
step3-->添加默认的MessageConverters.png
Spring-MVC核心流程及源码解析_第10张图片
step4-->加载需要扩展的MessageConverters到beanfactory中.png
Spring-MVC核心流程及源码解析_第11张图片
step5-->实例化后, 调用其初始化方法, 添加各种resolvers.png

https://www.cnblogs.com/leskang/p/6101368.html (SpringMVC流程参考)
http://www.imooc.com/article/281642?block_id=tuijian_wz (源码分析综合)
https://www.jianshu.com/p/c415f04f61b5 (源码分析--> 已参考)
https://segmentfault.com/a/1190000019448892 (WebMvcConfigurer)
https://www.jianshu.com/p/c5c1503f5367 (WebMvcConfigurationSupport)

你可能感兴趣的:(Spring-MVC核心流程及源码解析)