• Spring MVC(一)— DispatcherServlet


     DispatcherServlet 是Spring MVC框架的HTTP 请求处理器的中央调度器。它具有以下的功能:

    1)基于IoC容器JavaBean配置机制。

    2)使用HandlerMappingl来实现请求到处理器的路由映射。

    3)使用HandlerAdapter 来处理不同的处理器。

    4)处理器抛出的异常解决策略由HandlerExceptionResolver指定。

    5)视图解析策略可以通过ViewResolver实现指定。

    6)文件上传策略通过MultipartResolver来确定。

    7)Locale解析策略由LocaleResolver确定。

    8)主题解析策略由ThemeResolver确定。

    1 WebApplicationinitializer

    Spring 中用于以编程方式配置ServletContext,来替代web.xml的方式。其本身的执行由任何Servlet3.0 容器自动引导。

    图 WebApplicationInitializer UML

    1. public class CustomWebApplicationInitializer implements WebApplicationInitializer {
    2. @Override
    3. public void onStartup(ServletContext servletContext) throws ServletException {
    4. AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
    5. webApplicationContext.register(CustomAutowireConfigurer.class); // 配置注解方式的IoC容器
    6. DispatcherServlet dispatcherServlet = new DispatcherServlet(webApplicationContext); // 可以在servlet中使用IoC容器
    7. ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcherServlet", dispatcherServlet);
    8. dynamic.addMapping("/app/*"); // 所以以/app开头的请求都会映射到servlet
    9. }
    10. }

    相当于下面的web.xml

    1. <web-app>
    2. <listener>
    3. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    4. </listener>
    5. <context-param>
    6. <param-name>contextConfigLocation</param-name>
    7. <param-value>/WEB-INF/app-context.xml</param-value>
    8. </context-param>
    9. <servlet>
    10. <servlet-name>dispatcherServlet</servlet-name>
    11. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    12. </servlet>
    13. <servlet-mapping>
    14. <servlet-name>dispatcherServlet</servlet-name>
    15. <url-pattern>/app/*</url-pattern>
    16. </servlet-mapping>
    17. </web-app>

    1.1 运行原理

    javax.servlet.ServletContainerInitializer 接口是Servlet 3.0规范中定义的,当Servlet 3.0 的容器启动时,会调用其onStartup 方法。

    图 ServletContainerInitializer UML

    而Spring MVC通过SPI的方式,通过SpringServletContainerInitializer类来实现这个接口从而提供服务。在onStartup 方法中,会遍历IoC容器中定义的所有WebApplicationInitializer实例,并执行其onStart方法。

    1.2 Servlet配置

    AbstractDispatcherServletInitializer的customizeRegistration(ServletRegistration.Dynamic registration)方法用来定制Servlet。

    图 Dynamic 的UML

    1.2.1 WebMvcConfigurer

    是一个用于配置Spring MVC的接口。允许你自定义视图解析器、消息转换器、拦截器、静态资源处理器等。使用时需将它的实例注册为容器的bean,并在其实现类上加上@EnableWebMvc注解。

    图 WebMvcConfigurer UML

    1.3 DispatcherServlet处理请求的流程

    DispatcherServlet 处理请求的流程如下:

    1)WebApplicationContext 被绑定到请求中,处理器及其他元素可以访问它。

    2)Locale解析器被绑定到请求中,在解析请求时使用。

    3)主题解析器被绑定到请求中,让视图等元素确定要使用的主题。

    4)如果定义了文件解析器,会检查请求是否有文件,是则会把请求包装为MultipartHttpServletRequest。

    5)找到一个合适的解析器,与处理程序关联的执行器会被执行。准备模型或渲染。可以呈现响应或返回视图。

    2 基本组件

    DispatcherServlet 通过代理模式来代理特殊的组件用以处理请求及渲染合适的响应。

    2.1 HandlerInterception 拦截器

    HandlerMapping 根据当前请求来找的对应的Handler。并与一系列的HandlerInterceptor封装到HandlerExecutionChain对象中。这个过程发生在容器启动的过程中。

    当请求到达前端控制器(DispatcherServlet)时,DispatcherServlet会从容器取出所有的HandlerMapping实例并遍历,每个HandlerMapping 实例都会根据请求的信息(如URL、请求方法等)来确定对应的Handler(通常是Controller的一个方法)。

    图 HandlerInterceptor 接口UML

    preHandle 如果返回false,则其接下来的处理链都不会被执行。

    2.2 HandlerExceptionResolver 异常解析器

    处理在处理器方法执行过程中抛出的异常,不会处理拦截器中preHandle抛出的异常。

    可以定义多个异常解析器来组成一条解析链。可以设置它们的优先级,其返回值有如下情况:

    1)指向错误视图的ModelAndView。

    2)如果处理了异常,则返回空的ModelAndView。

    3)如果异常未解析,则返回null,供后续解析器尝试,最终可能会冒泡到Servlet容器。

    1. @Configuration
    2. public class CustomExceptionResolver implements HandlerExceptionResolver {
    3. @Override
    4. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    5. // 设置响应内容类型为JSON
    6. response.setContentType("application/json;charset=UTF-8");
    7. response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    8. Map<String, Object> errorDetails = new HashMap<>();
    9. errorDetails.put("message", ex.getMessage());
    10. try {
    11. response.getWriter().write(errorDetails.toString());
    12. response.getWriter().flush();
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. }
    16. return new ModelAndView();
    17. }
    18. }

    2.3 LocaleResolver 区域解析器

    Spring 容器可以实现国际化,通过LocaleResolver 来获取区域信息。

    时区解析

    LocaleContextResolver 扩展了该接口,包括了时区信息。

    请求头解析

    检查请求中的accept-language头部字段来获取区域信息。但该解析器不包含时区信息。

    Cookie解析

    检测Cookie中是否有区域与时区信息,需要在解析器中指出该cookie的属性名。过期时间(可选)

    Session解析

    从用户会话中检索区域和时区信息。这些信息是临时存储在HttpSession中的,会话结束时,信息会丢失。与外部会话管理机制(如Spring Session)没有直接关联。

    区域拦截器

    可以定义拦截器来设置区域信息。

    表 LocaleResolver 的种类

    2.4 MultipartResolver 文件解析器

    如果设置了文件解析器(默认为空),DispatcherServlet 会检查请求是否带有文件,是,则会将请求包装为MultipartHttpServletRequest。其实现主要有两种:

    CommonMultipartResolver: 是Spring在Apache Commons FileUpload组件的基础上封装而来的。允许进行更详细的配置。需要额外的依赖和配置。

    StandardServletMultipartResolver: 是基于Servlet 3.0 规范来处理multipart请求。不需要额外的依赖,但要求使用支持Servlet3.0的容器。

    1. public class CustomWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    2. @Override
    3. protected Class[] getRootConfigClasses() {
    4. return new Class[]{RootAnnotationConfig.class};
    5. }
    6. @Override
    7. protected Class[] getServletConfigClasses() {
    8. return new Class[]{ServletAnnotationConfig.class};
    9. }
    10. @Override
    11. protected String[] getServletMappings() {
    12. return new String[] {"/"};
    13. }
    14. @Override
    15. protected void customizeRegistration(ServletRegistration.Dynamic registration) {
    16. MultipartConfigElement element = new MultipartConfigElement("");
    17. registration.setMultipartConfig(element);
    18. }
    19. }
  • 相关阅读:
    c++基于CImage实现图片格式转换完整源代码
    第五章第三节:数和二叉树的应用(二叉排序树和哈夫曼树及哈夫曼编码)
    VectorDraw Developer Framework 10.1004 Crack
    北斗导航 | ION GNSS+2023论文集及PPT(Proceedings with presentations)
    HTTP请求头中Referer的作用
    ssm162基于SSM的药房药品采购集中管理系统的设计与实现+vue
    vite-react修改antd得prefix
    一文读懂Python异常
    Codeforces Round 953 (Div. 2)(A~D题解)
    一文了解硬盘AFR年化故障率评估方式和预测方案
  • 原文地址:https://blog.csdn.net/qq_25308331/article/details/136726289