该文章较多源码分析))
Web 场景中的自动配置
如何使用 Spring Boot,进行 web 开发
Spring Boot 的 Web 开发能力,由 SpringMVC 提供,给予了 Spring MVC 自动配置的能力
一般来说,在 Spring Initliazer 中,勾选一个web starter 场景,再选上一个 Lombok 就可以了。
前面说过,Spring Boot 将会帮我们自动配置好 web 开发场景中需要的相关配置,只需要在配置文件中指定少量配置就可以运行起来了,我们只需要注意在业务代码中就可以了。
自动配置
Spring Boot 的自动配置类是其核心特性之一,通过
@EnableAutoConfiguration
注解和
AutoConfigurationImportSelector
机制,会从类路径下的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.imports
文件中加载自动配置类
整合 Web 场景
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>引入了
autoconfigure
功能@EnableAutoConfiguration
会使用@Import(AutoConfigurationImportSelector.class)
批量导入一些组件加载
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.imports
文件中配置的所有组件大约重要的所有自动配置类如下
Web 相关自动配置类
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
配置 Spring MVC 的核心组件,如控制器、视图解析器、静态资源处理等。org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
配置嵌入式 Servlet 容器(如 Tomcat、Jetty)的工厂类。org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
配置 HTTP 消息转换器(如 JSON、XML 转换)。org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
配置错误处理页面和异常处理机制。org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration
基于 Spring WebFlux,支持 Netty 服务器的响应式编程模型,新增对 WebAssembly 部署的支持。
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
默认使用 Jackson 2.16+,新增对 JSON Schema 自动生成的支持(通过
@Schema
注解)。org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration
(响应式 Web)配置 Reactive 模式的 Web 服务器工厂。org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
配置 WebSocket 的 Servlet 支持。org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration
配置响应式 WebSocket 支持。
数据访问相关自动配置类
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
配置数据源(DataSource),支持 JDBC 连接池。默认连接池为 HikariCP 5.0。org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
配置 JDBC Template,简化数据库操作。org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
配置 JPA(Hibernate 实现),支持实体映射和数据库操作。org.springframework.boot.autoconfigure.mybatis.MybatisAutoConfiguration
(MyBatis 框架)配置 MyBatis 集成,自动扫描 mapper 接口和 XML 配置。org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration
配置 Redis 缓存连接和操作组件。org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
配置 MongoDB 数据库连接和操作组件。org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration
配置 Cassandra 数据库连接。org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchAutoConfiguration
配置 Elasticsearch 搜索引擎连接。
缓存与消息中间件相关
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
配置 Spring 缓存抽象(Cache),支持多种缓存实现(如 Redis、Caffeine)。org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
配置 Kafka 消息中间件的生产者和消费者。org.springframework.boot.autoconfigure.rabbit.RabbitAutoConfiguration
配置 RabbitMQ 消息中间件的连接和组件。org.springframework.boot.autoconfigure.activemq.ActiveMQAutoConfiguration
配置 ActiveMQ 消息中间件。
安全与认证相关
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
配置 Spring Security 的基本安全规则。org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
配置用户认证服务(UserDetailsService)。org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration
配置 OAuth 2.0 客户端认证。org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerAutoConfiguration
配置 OAuth 2.0 资源服务器。org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
配置 HTTP 会话(Session)管理,支持内存、Redis 等存储方式。
日志与监控相关
org.springframework.boot.autoconfigure.logging.LoggingAutoConfiguration
配置日志系统(默认使用 Logback),支持日志级别、输出格式等。org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
配置 JMX 管理功能,用于应用监控。org.springframework.boot.autoconfigure.actuate.metrics.MetricsAutoConfiguration
配置应用指标收集(如 CPU、内存、HTTP 接口耗时)。org.springframework.boot.autoconfigure.actuate.web.WebEndpointAutoConfiguration
配置 Spring Boot Actuator 的 Web 端点(如/health
、/info
)。org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
配置数据库变更管理工具 Liquibase,支持版本控制。org.springframework.boot.autoconfigure.actuate.observability.ObservabilityAutoConfiguration
内置 Micrometer 1.11.0 和 OTel SDK 1.24.0,自动配置应用指标、链路追踪(默认采样率 100%)。
这里只列出了常用的,在 Maven 项目中,查看
spring-boot-autoconfigure
依赖的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.imports
文件,该文件列出了所有可用配置类(3.5.0 约包含 200+ 个配置类)。绑定了配置文件的一堆配置项
- Spring MVC 的所有配置
spring.mvc
- Web 场景通用的配置
spring.web
- 文件上传配置
spring.servlet.multipart
- 服务器的一些配置
server
比如编码方式
如何找:
- Spring MVC 的所有配置

默认效果
我们上面说了Spring Boot 对 Spring MVC 的自动配置(AutoConfiguration)机制,那么如何在保持默认配置的同时进行自定义扩展,或者完全接管 MVC 配置。所以我们要了解 Spring Boot 对 Spring MVC 的默认配置
Spring Boot 通过 WebMvcAutoConfiguration
类为 Spring MVC
提供了默认配置,主要包含以下默认效果
- 包含了
ContentNegotiatingViewResolver
和BeanNameViewResolver
组件,方便视图解析ContentNegotiatingViewResolver
会根据请求的Accept
头(如application/json
、text/html
)选择合适的视图解析器,支持内容协商(如返回 JSON 或 HTML)。BeanNameViewResolver
按 Bean 名称解析视图(例如,控制器返回的视图名与 Bean 名称匹配时生效)
- 默认的静态资源处理机制:静态资源放在
static
文件夹下即可直接访问 - 自动注册了
Converter
,GenericConverter
,Formatter
组件,适配常见的数据类型转换和格式化需求。Converter
:类型转换器(如字符串转日期)。GenericConverter
:通用类型转换器(支持更复杂的类型转换逻辑)。Formatter
:格式化器(如日期格式化yyyy-MM-dd
)。
- 支持
HttpMessageConverters
,可以方便返回 json 等数据类型HttpMessageConverters
自动配置 JSON(默认使用 Jackson)、XML(JAXB)等消息转换器,支持@RequestBody
和@ResponseBody
。
- 注册
MessageCodesResolver
,方便国际化及错误消息处理MessageCodesResolver
处理国际化消息和错误码(如表单验证错误),配合messages.properties
使用。
- 支持静态
index.html
,若存在static/index.html
,则自动映射为根路径/
的默认页面 - 自动使用
ConfigurableWebBindingInitializer
,实现消息处理、数据绑定、类型转化等功能ConfigurableWebBindingInitializer
初始化数据绑定器,支持自定义属性编辑器、验证器等。
重要:
如果想保持 boot mvc 的默认配置,并且自定义更多的 mvc 配置,如:
interceptors
,formatters
,view
controllers
等,可以使用@Configuration
注解添加一个WebMvcConfigurer
类型的配置类, 并不要标注@EnableWebMvc
。如果想保持 boot mvc 的默认配置,但要自定义核心组件实例,比如: RequestMappingHandlerMapping, RequestMappingHandlerAdapter, 或 ExceptionHandlerExceptionResolver,给容器中放一个 WebMvcRegistrations 组件即可
如果想全面接管 Spring MVC,@Configuration 标注一个配置类,并加上 @EnableWebMvc 注解,实现 WebMvcConfigurer 接口
Spring MVC 的请求处理流程:
客户端发送 HTTP 请求 → DispatcherServlet 接收请求 → 通过
RequestMappingHandlerMapping
找到对应的控制器方法 → 执行方法并返回结果。RequestMappingHandlerMapping
是这个流程的核心组件,决定了请求如何被路由到具体方法。
自定义 MVC 配置的三种方式
- 扩展默认配置(推荐方式)
方式:创建
@Configuration
类并实现WebMvcConfigurer
接口,不添加@EnableWebMvc
。效果:保持 Spring Boot 的默认配置,仅添加或修改部分功能(如拦截器、格式化器)。
可扩展的常用功能:
- 拦截器(
addInterceptors
) - 格式化器 / 转换器(
addFormatters
) - 视图控制器(
addViewControllers
) - 静态资源处理器(
addResourceHandlers
) - CORS 配置(
addCorsMappings
)
- 拦截器(
示例
1
2
3
4
5
6
7
8
9
10
11
12
public class MyWebMvcConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new MyDateFormatter());
}
}
自定义核心 MVC 组件
方式:创建
WebMvcRegistrations
类型的 Bean,覆盖特定组件的创建逻辑。WebMvcRegistrations
是 Spring MVC 提供的一个扩展接口,允许开发者替换默认的核心 MVC 组件(如请求映射处理器、请求适配器、异常解析器等),同时保留 Spring Boot 的其他自动配置。
效果:保持默认配置,但替换核心组件(如
RequestMappingHandlerMapping
)。可自定义的核心组件:
RequestMappingHandlerMapping
(请求映射处理器)RequestMappingHandlerAdapter
(请求处理适配器)ExceptionHandlerExceptionResolver
(异常处理解析器)
示例
1
2
3
4
5
6
7
8
9
public class MyWebMvcRegistrations implements WebMvcRegistrations {
// RequestMappingHandlerMapping:负责将 HTTP 请求映射到对应的控制器方法(即处理 @RequestMapping、@GetMapping 等注解)
// 通过自定义 RequestMappingHandlerMapping,可以改变请求映射的默认行为(如添加自定义拦截规则、修改路径匹配策略等)。
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new CustomRequestMappingHandlerMapping();
}
}
完全接管 MVC 配置
方式:创建
@Configuration
类并添加@EnableWebMvc
注解,实现WebMvcConfigurer
接口。**效果:禁用 Spring Boot 的所有 MVC 自动配置,完全由开发者手动配置
注意:启用
@EnableWebMvc
后,Spring Boot 的所有 MVC 默认配置(如静态资源处理、内容协商)将失效,需手动配置所有功能。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 禁用 Spring Boot 的 MVC 自动配置
public class MyWebMvcConfig implements WebMvcConfigurer {
public void configureViewResolvers(ViewResolverRegistry registry) {
// 手动配置视图解析器
registry.jsp("/WEB-INF/views/", ".jsp");
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 手动配置消息转换器
converters.add(new MappingJackson2HttpMessageConverter());
}
}
全自动 | 直接编写控制器逻辑 | 全部使用自动配置默认效果 | |
---|---|---|---|
手自一体 | @Configuration + 配置 WebMvcConfigurer +
配置 WebMvcRegistrations |
不要标注@EnableWebMvc |
自动配置效果 手动设置部分功能 定义 MVC 底层组件 |
全手动 | @Configuration + 配置
WebMvcConfigurer |
标注@EnableWebMvc |
禁用自动配置效果 全手动设置 |
场景 | 方式 | 注解 | 接口 / 组件 |
---|---|---|---|
扩展默认配置(如添加拦截器) | 扩展配置 | @Configuration |
WebMvcConfigurer |
替换核心组件(如自定义请求映射) | 自定义组件 | @Configuration |
WebMvcRegistrations |
完全控制 MVC 配置(如使用 JSP 视图) | 完全接管 | @Configuration +@EnableWebMvc |
WebMvcConfigurer |
总结:所有的自定义模式,给容器类放一个配置类
@Configuration
实现
WebMvcConfigurer
,不要标注@EnableWebMvc
注解,实现了手自一体的模式。
两种模式
前后分离模式:
@RestController
响应 JSON 数据将前端和后端作为两个独立的应用进行开发和部署。前端专注于页面展示和用户交互,通过 API 与后端进行数据交互;后端专注于业务逻辑处理、数据存储与读取,仅提供 RESTful API 接口给前端调用。
- 前端:使用现代前端框架如 Vue.js、React、Angular 等构建单页应用(SPA)或多页应用(MPA) 。以 Vue.js 为例,通过 Vue Router 进行路由管理,利用 Axios 等工具发起 HTTP 请求获取后端数据,然后在组件中进行数据渲染和交互逻辑处理。
- 后端:使用
@RestController
注解标识控制器类,该注解组合了@Controller
和@ResponseBody
,表示方法返回值会直接序列化为 JSON 等格式响应给前端。后端基于 Spring Boot 等框架搭建 RESTful API,例如定义接口/api/user/login
用于用户登录验证,返回包含用户信息的 JSON 数据。
前后不分离模式:
@Controller
+ Thymeleaf 模板引擎前端页面的渲染由后端直接处理,后端将数据填充到模板中,然后返回完整的 HTML 页面给浏览器。这种模式下,前后端的耦合度较高。
- 后端:使用
@Controller
注解标识控制器类,配合 Thymeleaf、Freemarker 等模板引擎。以 Thymeleaf 为例,在控制器方法中获取业务数据,如查询用户信息,然后将数据模型传递给 Thymeleaf 模板。Thymeleaf 模板中通过特定语法(如th:text
、th:each
等)将数据渲染到 HTML 页面中,最终返回完整渲染后的 HTML 页面给前端浏览器。 - 前端:主要负责页面的基本样式和简单交互,如 HTML 结构搭建、CSS 样式编写,JavaScript 实现简单的表单验证等。相比前后分离模式,前端的逻辑处理相对简单。
- 后端:使用
Spring Boot 对静态资源的映射配置规则
先来讲解一下 Spring Boot 对于静态资源的相关配置规则,我们现在暂时选择来开发一个前后端没有分离的很彻底的应用,如果前后端分离的很彻底,我们只用 Spring Boot 来做后端接口,就不涉及到 Spring Boot 是如何管理静态资源方面的内容了。
WebMvcAutoConfiguration 原理
这个自动配置类的写法如下
生效条件
1 |
|
以下是详细解释
@AutoConfiguration(after = {DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
- 含义:
@AutoConfiguration
是 Spring Boot 用于标识自动配置类的注解 。after
属性指定了该自动配置类的加载顺序,即WebMvcAutoConfiguration
会在DispatcherServletAutoConfiguration
、TaskExecutionAutoConfiguration
和ValidationAutoConfiguration
之后进行加载。这确保了在配置 Spring MVC 相关功能时,其依赖的前置组件(如DispatcherServlet
相关配置、任务执行配置、验证配置)已经完成配置。 - 作用:保证配置顺序正确,避免因依赖组件未配置而导致的错误,使整个自动配置流程有序进行。
- 含义:
@ConditionalOnWebApplication(type = Type.SERVLET)
- 含义:
@ConditionalOnWebApplication
是条件注解,只有当应用是 Web 应用时才会生效。type = Type.SERVLET
限定了仅在 Servlet 类型的 Web 应用场景下该自动配置类才会起作用,像基于 Spring WebFlux 的响应式 Web 应用(Type.REACTIVE
)则不会触发此配置。 - 作用:精准定位适用场景,避免在非 Servlet 类型的 Web 应用中加载不必要的 Spring MVC 配置,提升应用启动性能和配置准确性。
- 含义:
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
- 含义:该条件注解表示只有当类路径下存在
Servlet.class
、DispatcherServlet.class
和WebMvcConfigurer.class
这几个类时,WebMvcAutoConfiguration
才会生效。Servlet
是 Java Web 开发基础规范类;DispatcherServlet
是 Spring MVC 中负责接收请求并分发到对应处理器的核心 servlet;WebMvcConfigurer
是用于自定义 Spring MVC 配置的接口。这意味着只有引入了相关依赖(如 Spring MVC 依赖),确保这些类存在于项目中,才会进行 Spring MVC 的自动配置。 - 作用:根据项目实际引入的依赖来判断是否进行 Spring MVC 相关配置,防止在没有相关依赖的项目中错误加载配置,保证配置的有效性和针对性。
- 含义:该条件注解表示只有当类路径下存在
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
- 含义:此注解规定当 Spring 容器中不存在
WebMvcConfigurationSupport
及其子类的 Bean 时,WebMvcAutoConfiguration
才会生效。如果开发者自定义了继承WebMvcConfigurationSupport
的配置类,Spring Boot 认为开发者要对 Spring MVC 进行全面自定义,就会跳过WebMvcAutoConfiguration
的自动配置。 - 作用:平衡自动配置和开发者自定义配置的关系,让开发者有能力完全接管 Spring MVC 配置,同时在未进行深度自定义时享受自动配置带来的便利。
- 含义:此注解规定当 Spring 容器中不存在
@AutoConfigureOrder(-2147483638)
- 含义:
@AutoConfigureOrder
用于指定自动配置类的加载顺序,数值越小优先级越高。这里设置为-2147483638
,表明它在自动配置类加载顺序中处于较高优先级,能在一些依赖它的配置之前完成加载。 - 作用:保证在整个自动配置体系中,Spring MVC 的相关配置能按照预期顺序加载,避免因顺序问题导致的配置冲突或错误。
- 含义:
@ImportRuntimeHints({WebResourcesRuntimeHints.class})
- 含义:
@ImportRuntimeHints
注解用于引入运行时提示相关的配置类。WebResourcesRuntimeHints.class
会提供关于 Web 资源(如静态资源)在运行时的一些提示信息,帮助应用在运行时更高效地处理和管理这些资源,比如优化资源的查找、加载等操作。 - 作用:提升应用在运行时对 Web 资源的处理效率和性能,确保资源相关功能的正确执行。
- 含义:
效果
那么生效之后是什么效果
放了两个 Filter
:
1 |
|
HiddenHttpMethodFilter
:页面表单可以提交 Rest 请求(GET,POST,PUT,DELETE)FormContentFilter
:表单内容 Filter,只有 GET(数据发url后) POST(数据放请求体) 请求可以携带数据,PUT,DELETE的请求体数据会被忽略
效果的第一个是这个
该类作为 Spring Boot 自动配置和开发者自定义配置的桥梁,既加载默认的
MVC 配置(通过
EnableWebMvcConfiguration
),又允许开发者通过实现
WebMvcConfigurer
接口进行扩展。
1 | // 声明该类是一个配置类,不代理 Bean 方法,即每次调用配置类中的 Bean 方法时,直接创建新实例,而非从 Spring 容器中获取 |
- 实现接口
WebMvcConfigurer
: 提供自定义 Spring MVC 配置的回调方法(如添加拦截器、配置消息转换器)。通过实现该接口,可在不使用@EnableWebMvc
的情况下定制 MVC 功能。ServletContextAware
: 允许 Bean 获取ServletContext
引用,用于访问 Servlet 容器相关信息(如获取应用上下文路径)。
给容器中放了WebMvcConfigurer
组件:给 SpringMVC
添加各种定制功能
- 所有的功能最终会和配置文件进行绑定
WebMvcProperties
:spring.mvc
配置文件WebProperties
:spring.web
配置文件
WebMvcConfigurer
这里是 WebMvcConfigurer
这个接口的源码,提供了配置
Spring MVC 底层的所有组件入口
1 | // WebMvcConfigurer接口用于对Spring MVC进行自定义配置 |
- 其中
addResourceHandlers
就是专门处理静态资源规则的资源处理器,就是来做静态资源映射
addResourceHandlers
分析
默认的静态资源规则源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35/**
* 配置静态资源处理器,用于处理Web应用中的静态资源请求(如CSS、JS、图片等)
* @param registry 资源处理器注册器,用于注册静态资源处理规则
*/
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 检查是否启用默认静态资源映射(通过spring.web.resources.add-mappings属性控制)
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
// 1. 配置WebJars资源映射
// WebJars是将前端依赖(如jQuery、Bootstrap)打包成JAR的标准,可通过Maven/Gradle引入
this.addResourceHandler(
registry,
this.mvcProperties.getWebjarsPathPattern(), // 请求路径模式,默认是"/webjars/**"
"classpath:/META-INF/resources/webjars/"// 资源存放位置,WebJars规范定义的默认路径
);
// 2. 配置普通静态资源映射
this.addResourceHandler(
registry,
this.mvcProperties.getStaticPathPattern(), // 请求路径模式,默认是"/**"
(registration) -> {
// 添加静态资源的物理位置(可通过spring.web.resources.static-locations配置)
// 默认位置包括:classpath:/static/、classpath:/public/等
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
// 如果存在ServletContext(即非测试环境),添加ServletContext根路径资源
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
}
);
}
}
规则一:可以看到其中的webjars
,这是一种重要的配置规则,访问/webjars/**
路径就去classpath:/META-INF/rescources/webjars/
下找资源
规则二:访问/**
,就去
classpath:/static/
等静态资源的默认的四个位置找
1
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
规则三:静态资源默认都有缓存规则的设置
- 如果说浏览器访问了一个静态资源,服务器这个资源没有发生变化,下次访问的时候可以直接让浏览器用自己缓存中的东西,就不用给浏览器发请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/**
* 注册静态资源处理器,将指定URL模式映射到对应资源位置,并应用缓存配置
*
* @param registry 资源处理器注册器
* @param pattern 请求路径模式(如"/webjars/**"或"/**")
* @param customizer 自定义资源位置的回调函数
*/
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, Consumer<ResourceHandlerRegistration> customizer) {
// 检查是否已有相同模式的映射,避免重复注册
if (!registry.hasMappingForPattern(pattern)) {
// 创建资源处理器注册,将URL模式映射到资源位置
ResourceHandlerRegistration registration = registry.addResourceHandler(new String[]{pattern});
// 应用自定义资源位置(如classpath:/static/或ServletContext根路径)
customizer.accept(registration);
// 配置缓存策略:
// 1. 设置缓存周期(秒),对应配置项spring.web.resources.cache.period
registration.setCachePeriod(this.getSeconds(this.resourceProperties.getCache().getPeriod()));
// 2. 设置HTTP缓存控制头(如Cache-Control: max-age=3600)
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
// 3. 启用Last-Modified时间戳支持(基于文件修改时间验证缓存)
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
// 应用自定义配置(如Gzip压缩、资源链处理器等)
this.customizeResourceHandlerRegistration(registration);
}
}
所有缓存的设置,直接通过配置文件:
spring.web
cachePeriod
:缓存周期;多久不用找服务器要新的。默认没有,以 s 为单位cacheControl
:HTTP 缓存控制;https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CachinguseLastModified
:是否使用最后一次修改。也适用自定义:
- 配置文件覆盖默认值
1
2
3
4
5
6
7
8
9# 禁用缓存(开发环境常用)
spring.web.resources.cache.period=0
# 启用缓存并设置1小时有效期(生产环境)
spring.web.resources.cache.period=3600
# 自定义静态资源路径和缓存控制
spring.web.resources.static-locations=classpath:/custom-static/
spring.web.resources.cache.cachecontrol.max-age=86400- Java 代码自定义 通过实现
WebMvcConfigurer
手动配置:
1
2
3
4
5
6
7
8
9
10
public class WebConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/custom/**")
.addResourceLocations("classpath:/custom-resources/")
.setCachePeriod(3600) // 覆盖配置文件设置
.setUseLastModified(true);
}
}
HTTP 缓存机制详解
缓存配置的参数
配置项 | 对应属性 | 默认值 | 作用 |
---|---|---|---|
spring.web.resources.cache.period |
resourceProperties.getCache().getPeriod() |
null |
缓存过期时间(秒),设置后响应头添加
Cache-Control: max-age=xxx |
spring.web.resources.cache.cachecontrol.* |
resourceProperties.getCache().getCachecontrol() |
见下方 | 细粒度控制 HTTP 缓存头(如
no-cache 、must-revalidate ) |
spring.web.resources.cache.use-last-modified |
resourceProperties.getCache().isUseLastModified() |
true |
是否使用文件修改时间(Last-Modified 头)验证缓存 |
继续上述在addResourceHandler
部分关于缓存的内容中,此方法通过以下方式控制缓存:
强缓存(Cache-Control)
当设置
cachePeriod
时,响应头添加Cache-Control: max-age=xxx
,浏览器直接使用本地缓存,无需请求服务器。1
spring.web.resources.cache.period=3600 # 缓存1小时
协商缓存(Last-Modified)
- 默认启用
useLastModified
,响应头添加Last-Modified
时间戳。 - 下次请求时,浏览器发送
If-Modified-Since
头,服务器比较时间戳决定是否返回新资源。
- 默认启用
细粒度控制 通过
spring.web.resources.cache.cachecontrol.*
配置:1
2
3spring.web.resources.cache.cachecontrol.max-age=3600 # 等同 cache.period
spring.web.resources.cache.cachecontrol.no-cache=true # 禁用强缓存
spring.web.resources.cache.cachecontrol.must-revalidate=true # 缓存过期前必须验证
EnableWebMvcConfiguration 源码
1 | // Spring Boot给容器放了WebMvcConfigurationSupport组件 |
DelegatingWebMvcConfiguration
是 Spring MVC 的核心配置类,它实现了WebMvcConfigurationSupport
并聚合了所有WebMvcConfigurer
实例的配置。- 允许开发者通过实现
WebMvcConfigurer
接口自定义配置,而无需完全接管 MVC 配置(即不使用@EnableWebMvc
)。
- 允许开发者通过实现
- 通过实现
ResourceLoaderAware
接口,该类可获取ResourceLoader
实例,用于加载类路径或文件系统中的资源。在配置静态资源处理器时,可通过ResourceLoader
定位资源位置(如classpath:/static/
)。
使用 webjars
首先 Spring Boot 的有个叫 webjars 的东西,所有通过 pom.xml
引入的静态资源,都在/webjars/**
下(这个在静态资源的自动配置类中可以找到),也就是说
Spring Boot 会自动去 classpath:/META-INF/resources/webjars/
找资源,webjars 以 jar
包的方式引入静态资源(也就是说,我们都可以通过http://localhost:8080/webjars/xx
访问对应的静态资源)
各种静态资源 jar 都可以通过 pom.xml 依赖的方式引入 ,我们引入 JQuery 看看,引入的 JQuery 的依赖包下边,可以看到 webjars 内容长这样
现在我们引入了 jQuery 的静态资源,我们启动项目,来试一下能不能通过对应的路径访问
所以通过 SpringBoot 来开发相关的静态资源,非常方便,我们只要引入对应的 webjars 就可以了,Spring Boot 不需要我们进行过多的配置,有自己默认配置的规则。
就是用 pom.xml 中导入依赖,然后可以用
classpath:/META-INF/resources/webjars/
找资源
使用resources
当然如果我们想要用自己的静态资源,不想使用webjars的东西,这个时候就需要另外一个映射规则就是/**
(也就是说,我们通过http://localhost:8080/xxx.js
访问静态资源,这时候就是使用
resources 规则了。
默认静态资源路径
静态资源映射规则此事在WebMvcAutoConfigurationAdapter
亦有记载
除了使用 webjars
,Spring Boot
默认提供了更直接的静态资源管理方式——直接将静态文件放在项目的
resources
目录下。以下是详细的配置规则和使用案例:
Spring Boot 默认会在以下位置查找静态资源(优先级从高到低):
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
ServletContext
根目录(如src/main/webapp/
)
当浏览器发起 /xxx
请求时,Spring Boot
会依次在这些目录中查找名为 xxx
的文件。
1 | src/main/resources/ |
访问静态资源
假设在 static/images
目录下放置
logo.png
,访问方式为:
1 | http://localhost:8080/images/logo.png |
无需在 URL 中添加 static
,直接通过资源路径访问。
例如:在 src/main/resources/static
下创建
index.html
:
1 |
|
将图片 spring-logo.png
放入 static/images/
目录。
启动应用后:
访问首页:
http://localhost:8080/index.html
访问图片:
http://localhost:8080/images/spring-logo.png
注意存在的问题:
缓存问题
修改静态资源后,浏览器可能缓存旧文件。可通过以下方式解决:
- 强制刷新(
Ctrl + F5
) - 在资源URL中添加版本号:
/css/style.css?v=1.0
自定义静态资源路径
默认静态资源位置:
1 | classpath:/META-INF/resources/ |
自定义单个位置:
1 | # application.yml |
如果默认路径不满足需求,可在
application.properties
中自定义多个位置:
1 | # 修改静态资源访问前缀 |
- 创建
resources/custom-static/hello.html
- 配置后访问:
http://localhost:8080/assets/hello.html
通过 Java 配置自定义:
实现 WebMvcConfigurer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class WebConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 添加自定义静态资源映射
registry.addResourceHandler("/assets/**")
.addResourceLocations("classpath:/custom-assets/")
.setCachePeriod(3600); // 设置缓存时间
// 保持默认的静态资源映射
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/",
"classpath:/public/",
"classpath:/custom/");
}
public void addViewControllers(ViewControllerRegistry registry) {
// 自定义欢迎页控制器
registry.addViewController("/").setViewName("forward:/index.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}自定义
ResourceHttpRequestHandler
ResourceHttpRequestHandler
是 Spring MVC 中的一个类,它是HttpRequestHandler
的实现类,主要作用是处理静态资源请求,根据配置的资源位置查找请求对应的静态资源文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class CustomResourceConfig {
public SimpleUrlHandlerMapping customResourceHandlerMapping() {
// 创建一个SimpleUrlHandlerMapping实例,用于处理URL映射
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
// 创建一个HashMap来存储URL和对应的处理器
Map<String, ResourceHttpRequestHandler> urlMap = new HashMap<>();
// 创建一个ResourceHttpRequestHandler实例,用于处理资源请求
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
// 设置处理器查找资源的位置,这里指定了两个路径
handler.setLocationValues(Arrays.asList(
"classpath:/custom/",
"classpath:/static/"
));
// 将"/**"路径映射到创建的处理器
urlMap.put("/**", handler);
// 设置URL映射关系
mapping.setUrlMap(urlMap);
// 设置该映射的顺序,值越大优先级越低,这里设置为Integer.MAX_VALUE - 1
mapping.setOrder(Integer.MAX_VALUE - 1);
return mapping;
}
}
注意路径匹配规则问题:
- 避免Controller的请求路径与静态资源名称冲突。例如,若存在
/user
接口,则无法通过/user.html
访问静态页面。
配置欢迎页映射
静态资源文件夹下的所有index.html
页面,会被/
映射;
也就是说我们直接访问http://localhost:8080/
就直接访问静态资源文件夹中的index.html
,相当于我们以前Spring
MVC 下面的index.jsp
,比如我们现在随机选 public
的静态资源文件夹下创建index.html
源码:
Bean 配置入口
1 |
|
这个 Bean 配置方法创建了 WelcomePageHandlerMapping
实例,该实例负责处理欢迎页的路径映射。Spring Boot
通过自动配置机制在容器启动时创建此映射器。
进入到其中的 WelcomePageHandlerMapping
类
1 | WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource indexHtmlResource, String staticPathPattern) { |
欢迎页解析部分
1 | static WelcomePage resolve(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource indexHtmlResource, String staticPathPattern) { |
源码分析:
HandlerMapping
:根据请求路径/a
找那个 handler 能处理请求- 是 Spring MVC 中负责根据请求路径找到对应处理器(Handler)的组件
WelcomePageHandlerMapping
:- 访问
/**
路径下的所有请求,都在以前四个静态资源路径下找,欢迎页也一样 - 找
index.html
:只要静态资源的位置有一个index.html
页面,项目启动默认访问
- 访问
欢迎页解析:
WelcomePage.resolve()
方法会按照以下优先级查找欢迎页:首先检查是否存在
index
模板文件(如 index.html, index.ftl, index.jsp 等)如果没有模板,则查找静态资源目录下的
index.html
文件当存在模板引擎和对应的
index
模板时,会优先使用模板渲染。1
2src/main/resources/templates/index.html (Thymeleaf)
src/main/resources/templates/index.ftl (FreeMarker)
控制器创建: 如果找到欢迎页,创建
ParameterizableViewController
来处理根路径请求
配置自定义
当然,如果我们不想要使用SpringBoot默认的静态资源文件夹,我们还可以定义静态资源的映射
默认情况下,静态资源路径模式为 /**
如需自定义欢迎页行为,可以通过以下方式:
1 | # application.yml |
当
static-path-pattern
不是/**
时,欢迎页功能会被禁用,这是因为WelcomePage.resolve()
方法中有明确的检查,如果必须修改静态资源路径模式,可以通过自定义控制器来实现欢迎页自定义控制器的
@RequestMapping("/")
会覆盖默认的欢迎页映射完全禁用欢迎页:
1
2
3
4
5# application.yml
spring:
web:
resources:
add-mappings: false # 禁用所有静态资源映射使用 profile 特定的欢迎页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ProductionWelcomeController {
public String productionWelcome() {
return "production-index";
}
}
public class DevelopmentWelcomeController {
public String developmentWelcome() {
return "dev-index";
}
}要注意了,如果自己定义了静态资源映射之后,默认的文件夹就都不生效了,相当于原来的那些访问方式都不生效了。
Favicon 规则
这个和欢迎页规则差不多,默认情况下在静态资源目录下找favicon.ico
当然,如果我们不想要使用SpringBoot默认的静态资源文件夹,我们还可以定义静态资源的映射
但是这是一个隐形规则,是根据浏览器实现的,不是 Spring Boot让他变的