Spring Boot WebMVC:【从零开始学Spring Boot】-3.Spring Boot WebMVC
1.Spring WebMvc 运行流程是怎样的?
- 用户发送请求至前端控制器 DispatcherServlet。
- DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
- 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet,一般使用的是 url 映射器。
- DispatcherServlet 调用 HandlerAdapter 处理器适配器。
- HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller 执行完成返回 ModelAndView。
- HandlerAdapter 将 ModelAndView 返回给 DispatcherServlet。
- DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器。
- ViewReslover 解析后返回具体 View。
- DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)。
- 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;
}
}
// ...
}