【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(上)

简介: 【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(上)

前言


为了更好的去理解Spring MVC的工作机制,这边博文我们主要讲述Spring MVC在初始化的时候(容器启动的时候),做的一些准备工作。


比如URL和Controller的绑定,以及URL和方法method的绑定,拦截器的初始化,视图解析器的初始化等Spring MVC web9大组件的初始化


在上篇博文: 【小家Spring】Spring容器(含父子容器)的启动过程源码级别分析(含web.xml启动以及全注解驱动,和ContextLoader源码分析) 从源码层面,我已经很清楚的了解到了父容器以及Spring MVC子容器的一个初始化的过程。当时还留下两大悬念:


   1.refresh()刷新容器的详细过程


   2.web子容器中,初始化web9大组件的onRefresh()方法的详解


本文因为主讲web环境,因此主要剖析onRefresh()这个方法所做的事。(其实是DispatcherServlet里的initStrategies()这个方法)

  /**
   * Initialize the strategy objects that this servlet uses.
   * <p>May be overridden in subclasses in order to initialize further strategy objects.
   * 子类若有需要,还可以复写此方法,去初始化自己的其余组件(比如要和它集成等等)
   */
  protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    // 注意,下面是复数,有s。注意区别哦~
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
  }


Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)


Spring MVC九大组件(按照源代码顺序解释)


DispatcherServlet的默认配置文件DispatcherServlet.properties里都有定义这九大组件的默认值


从上面源码中,可能很清楚的看到9大组件的名称,那么我们先来介绍介绍他们各有什么作用:


这里顺便解释一下SpringMVC中的Servlet的三个层次:


   1.HttpServletBean直接继承自java的HttpServlet,其作用是将Servlet中配置的参数设置到相应的Bean属性上


   2.FrameworkServlet初始化了WebApplicationContext


   3.DispatcherServlet初始化了自身的9个组件(本文重点)

MultipartResolver

public interface MultipartResolver {
  boolean isMultipart(HttpServletRequest request);
  MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
  void cleanupMultipart(MultipartHttpServletRequest request);
}


MultipartResolver 用于处理文件上传,当收到请求时 DispatcherServlet#checkMultipart() 方法会调用 MultipartResolver#isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver#resolveMultipart() 方法对请求的数据进行解析。

然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest(继承了 HttpServletRequest) 对象中,最后传递给 Controller


它的两个实现类:

image.png

CommonsMultipartResolver 使用 commons Fileupload 来处理 multipart 请求,所以在使用时,必须要引入相应的 jar 包

StandardServletMultipartResolver 是基于 Servlet 3.0来处理 multipart 请求的(基于request.getParts()方法),使用支持 Servlet 3.0的容器


        不一样的是,配置StandardServletMultipartResolver这个Bean的时候,它的初始化参数都在web.xml的<multipart-config>里面配置

image.png


LocaleResolver


public interface LocaleResolver {
  //根据request对象根据指定的方式获取一个Locale,如果没有获取到,则使用用户指定的默认的Locale
  Locale resolveLocale(HttpServletRequest request);
  //用于实现Locale的切换。比如SessionLocaleResolver获取Locale的方式是从session中读取,但如果
  //户想要切换其展示的样式(由英文切换为中文),那么这里的setLocale()方法就提供了这样一种可能
  void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}

对于LocaleResolver,其主要作用在于根据不同的用户区域展示不同的视图,而用户的区域也称为Locale,该信息是可以由前端直接获取的。通过这种方式,可以实现一种国际化的目的,比如针对美国用户可以提供一个视图,而针对中国用户则可以提供另一个视图。


         解析视图需要两个参数:一是视图名,另一个是Locale。视图名是处理器返回的,Locale是从哪里来的?这就是LocaleResolver要做的事情


image.png

  • FixedLocaleResolver:在声明该resolver时,需要指定一个默认的Locale,在进行Locale获取时,始终返回该Locale,并且调用其setLocale()方法也无法改变其Locale;
  • CookieLocaleResolver:其读取Locale的方式是在session中通过Cookie来获取其指定的Locale的,如果修改了Cookie的值,页面视图也会同步切换;
  • SessionLocaleResolver:其会将Locale信息存储在session中,如果用户想要修改Locale信息,可以通过修改session中对应属性的值即可;
  • AcceptHeaderLocaleResolver:其会通过用户请求中名称为Accept-Language的header来获取Locale信息,如果想要修改展示的视图,只需要修改该header信息即可。


    对于Locale的切换,Spring是通过拦截器来实现的,其提供了一个LocaleChangeInterceptor,若要生效,这个Bean需要自己配置


ThemeResolver


主题就是系统的整体样式或风格,可通过Spring MVC框架提供的主题(theme)设置应用的整体样式风格,提高用户体验。Spring MVC的主题就是一些静态资源的集合,即包括样式及图片,用来控制应用的视觉风格。


SpringMVC中一个主题对应一个properties文件,里面存放着跟当前主题相关的所有资源、如图片、css样式等。

image.png


主题使用得太少了,特别现在前后端分离了。此处省略~

HandlerMapping(非常非常重要)


用来查找Handler的。在SpringMVC中会有很多请求,每个请求都需要一个Handler处理,具体接收到一个请求之后使用哪个Handler进行处理呢?这就是HandlerMapping需要做的事


作用是根据当前请求的找到对应的 Handler,并将 Handler(执行程序)与一堆 HandlerInterceptor(拦截器,也是他来处理的)封装到 HandlerExecutionChain 对象中。返回给中央调度器

public interface HandlerMapping {
  @Nullable
  HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}


该接口有很多的实现,同时它也是最复杂的一个类。因此为了更好的解释它的作用和原理,后面会出专门的博文深入分析,感兴趣可持续关注

HandlerMapping可以有多个

相关文章
|
11月前
|
人工智能 JSON 安全
Spring Boot实现无感刷新Token机制
本文深入解析在Spring Boot项目中实现JWT无感刷新Token的机制,涵盖双Token策略、Refresh Token安全性及具体示例代码,帮助开发者提升用户体验与系统安全性。
1181 4
|
9月前
|
运维 数据可视化 C++
2025 热门的 Web 化容器部署工具对比:Portainer VS Websoft9
2025年热门Web化容器部署工具对比:Portainer与Websoft9。Portainer以轻量可视化管理见长,适合技术团队运维;Websoft9则提供一站式应用部署与容器管理,内置丰富开源模板,降低中小企业部署门槛。两者各有优势,助力企业提升容器化效率。
593 1
2025 热门的 Web 化容器部署工具对比:Portainer VS Websoft9
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
534 2
|
10月前
|
JSON 前端开发 Java
Spring MVC 核心组件与请求处理机制详解
本文解析了 Spring MVC 的核心组件及请求流程,核心组件包括 DispatcherServlet(中央调度)、HandlerMapping(URL 匹配处理器)、HandlerAdapter(执行处理器)、Handler(业务方法)、ViewResolver(视图解析),其中仅 Handler 需开发者实现。 详细描述了请求执行的 7 步流程:请求到达 DispatcherServlet 后,经映射器、适配器找到并执行处理器,再通过视图解析器渲染视图(前后端分离下视图解析可省略)。 介绍了拦截器的使用(实现 HandlerInterceptor 接口 + 配置类)及与过滤器的区别
1037 0
|
XML Java Maven
Spring 手动实现Spring底层机制
Spring 第六节 手动实现Spring底层机制 万字详解!
581 32
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
2453 15
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
1252 4
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
684 8
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
578 4
|
开发者 Docker Python
从零开始:使用Docker容器化你的Python Web应用
从零开始:使用Docker容器化你的Python Web应用
775 4