侧边栏壁纸
博主头像
soulballad博主等级

技术文章记录及总结

  • 累计撰写 169 篇文章
  • 累计创建 26 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

【源码分析-Spring Boot】-3.Spring Boot WebMVC 工作流程及原理

soulballad
2020-07-12 / 0 评论 / 0 点赞 / 62 阅读 / 3,429 字
温馨提示:
本文最后更新于 2022-03-03,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Spring Boot WebMVC:【从零开始学Spring Boot】-3.Spring Boot WebMVC

1.Spring WebMvc 运行流程是怎样的?

  1. 用户发送请求至前端控制器 DispatcherServlet。
  2. DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
  3. 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet,一般使用的是 url 映射器。
  4. DispatcherServlet 调用 HandlerAdapter 处理器适配器。
  5. HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)。
  6. Controller 执行完成返回 ModelAndView。
  7. HandlerAdapter 将 ModelAndView 返回给 DispatcherServlet。
  8. DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器。
  9. ViewReslover 解析后返回具体 View。
  10. DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet 返回响应给用户。

2.Spring WebMvc 的原理

DispatcherServlet 其实也是一个 HttpServlet,它的类图如下

在传统的 HttpServlet 中,它的生命周期包含 init、service、destroy,在 service 中一般有 doGet、doPost 分别来处理 get、post 请求。DispatcherServlet 即是在 HttpServlet 上面进行的扩展。

SpringMvc 的初始化时序图:

protected void initStrategies(ApplicationContext context) {
    // 初始化上传组件,用于文件上传等
    initMultipartResolver(context);
    // 初始化本地化组件,用于国际化
    initLocaleResolver(context);
    // 初始化主题组件
    initThemeResolver(context);
    // 初始化处理器映射器
    initHandlerMappings(context);
    // 初始化处理器适配器
    initHandlerAdapters(context);
    // 初始化异常处理器
    initHandlerExceptionResolvers(context);
    // 初始化请求-视图名称翻译器
    initRequestToViewNameTranslator(context);
    // 初始化视图处理器
    initViewResolvers(context);
    // 初始化 FlashMapManager
    initFlashMapManager(context);
}

SpringMvc 的运行时序图:

3.DispatcherServlet 是如何初始化的?

在一般的 Spring WebMvc 项目中,通常会在 web.xml 中配置好 DispatcherServlet,如下所示

<servlet>  
    <!-- 配置DispatcherServlet -->  
    <servlet-name>springMvc</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <!-- 指定spring mvc配置文件位置 不指定使用默认情况 -->  
    <init-param>     
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-context.xml</param-value>
    </init-param>  
    <!-- 设置启动顺序 -->  
    <load-on-startup>1</load-on-startup>  
</servlet>

<!-- ServLet 匹配映射 -->
<servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

那么,在 Spring Boot 项目中,DispatcherServlet 又是如何配置的呢?

其实,在 spring-boot-autoconfigure/META-INF/spring.factories 中有这样一个配置

这个 DispatcherServletAutoConfiguration 即是 DispatcherServlet 的自动装配类

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {

    public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

    @Configuration(proxyBeanMethods = false)
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })
    protected static class DispatcherServletConfiguration {

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
            dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
            dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
            dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
            dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());
            return dispatcherServlet;
        }
    }

    // ...
}
0

评论区