全面接管 SpringMVC 的思路
SpringBoot 默认配置好了 SpringMVC 的所有常⽤特性。
在 SpringBoot 中,全面接管 SpringMVC 配置的思路是通过禁用默认配置并完全自定义所有 MVC 行为。这是一个高级用法,适用于需要对 SpringMVC 进行深度定制的场景。
全面接管 SpringMVC 的核心步骤如下:
- 创建一个配置类,实现
WebMvcConfigurer
接口 - 使用
@EnableWebMvc
注解禁用 SpringBoot 的默认 MVC 配置 - 重写
WebMvcConfigurer
接口中的方法来定义所有需要的 MVC 行为,WebMvcConfigurer
组件定义MVC的底层行为
回忆一下配置类的三种自定义方式
全自动 | 直接编写控制器逻辑 | 全部使用自动配置默认效果 | |
---|---|---|---|
手自一体 | @Configuration + 配置 WebMvcConfigurer +
配置 WebMvcRegistrations |
不要标注@EnableWebMvc |
自动配置效果 手动设置部分功能 定义 MVC 底层组件 |
全手动 | @Configuration + 配置
WebMvcConfigurer |
标注@EnableWebMvc |
禁用自动配置效果 全手动设置 |
例如,如下就是一个全面接管 SpringMVC 配置的示例代码:
1 | import org.springframework.context.annotation.Bean; |
- @EnableWebMvc 注解:这个注解是全面接管的关键,它会禁用 SpringBoot 的自动 MVC 配置,让你完全控制所有 MVC 行为。
- WebMvcConfigurer
接口:实现这个接口并重写其方法,可以自定义各种 MVC 行为:
- 静态资源处理
- 视图控制器配置
- 拦截器注册
- 跨域支持
- 路径匹配策略
- 内容协商
- 消息转换器
- 异常处理器
- 参数解析器
- 返回值处理器
- 数据格式化
- 自定义 Bean:除了实现接口方法外,还可以通过
@Bean
注解提供自定义的组件,如RequestMappingHandlerMapping
、Validator
等。
WebMvcConfigurer 接口分析及方法详解
源码分析
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
是 Spring MVC 提供的一个接口,用于自定义 Web MVC 的配置。它是一个
标记接口(marker
interface),它本身没有任何抽象方法,但提供了一组默认为空实现的方法(Java
8+ 的 default 方法),开发者可以选择性地覆盖这些方法来定制 Spring MVC
的行为。
来看看WebMvcConfigurer
接口的源代码,对应方法我编写了注释
1 | package org.springframework.web.servlet.config.annotation; |
总结下来就是:
方法名 | 描述 | 常用场景 |
---|---|---|
configurePathMatch |
配置路径匹配选项,如后缀模式匹配、尾部斜杠匹配等 | 自定义 URL 匹配规则,如禁用.html 后缀匹配 |
configureContentNegotiation |
配置内容协商策略,用于确定请求和响应的媒体类型 | 设置默认响应格式为 JSON,配置基于 URL 扩展名的内容协商 |
configureAsyncSupport |
配置异步请求处理选项,如异步请求超时时间、任务执行器等 | 设置异步请求超时时间,配置 DeferredResult 处理 |
configureDefaultServletHandling |
配置默认 Servlet 处理,用于处理静态资源请求 | 启用默认 Servlet 处理静态资源 |
addFormatters |
注册自定义的格式化器和转换器,用于类型转换和格式化 | 添加日期格式化器,注册自定义类型转换器 |
addInterceptors |
注册自定义的拦截器,用于处理请求的预处理和后处理 | 添加身份验证拦截器,实现请求日志记录 |
addResourceHandlers |
注册自定义的资源处理器,用于处理静态资源请求 | 配置静态资源路径,设置缓存控制头 |
addCorsMappings |
配置跨域资源共享 (CORS) 映射,允许跨域请求 | 允许特定域名访问 API,配置跨域请求头 |
addViewControllers |
注册视图控制器,用于直接映射 URL 到视图而不需要控制器方法 | 简化登录页面、主页等简单视图的映射 |
configureViewResolvers |
配置视图解析器,用于将逻辑视图名称解析为实际的视图实现 | 配置 JSP、Thymeleaf 等视图解析器 |
addArgumentResolvers |
注册自定义的处理器方法参数解析器,用于处理控制器方法的参数 | 添加自定义参数解析器,如用户会话参数 |
addReturnValueHandlers |
注册自定义的处理器方法返回值处理器,用于处理控制器方法的返回值 | 添加自定义返回值处理器,如统一 API 响应格式 |
configureMessageConverters |
配置 HTTP 消息转换器列表,会替换默认转换器 | 完全自定义消息转换器,如使用自定义 JSON 序列化器 |
extendMessageConverters |
扩展默认的 HTTP 消息转换器列表 | 在默认转换器基础上添加自定义转换器 |
configureHandlerExceptionResolvers |
配置处理器异常解析器列表,会替换默认解析器 | 完全自定义异常处理机制 |
extendHandlerExceptionResolvers |
扩展默认的处理器异常解析器列表 | 添加自定义异常处理器 |
addErrorResponseInterceptors |
添加错误响应拦截器,用于自定义错误响应的处理 | 自定义错误响应格式,添加额外错误信息 |
getValidator |
提供自定义的 Validator 实现,用于数据验证 | 提供自定义验证器,如使用 Hibernate Validator |
getMessageCodesResolver |
提供自定义的 MessageCodesResolver 实现,用于解析验证错误代码 | 自定义错误代码解析逻辑 |
接下来我会挑出其中重要的进行分析和讲解
configureMessageConverters
vs extendMessageConverters
Spring MVC 默认提供了一系列消息转换器,如
MappingJackson2HttpMessageConverter
(JSON)、StringHttpMessageConverter
等
这两个方法都用于配置 HTTP 消息转换器,但作用不同
configureMessageConverters
: 完全自定义消息转换器列表,会替换默认的转换器extendMessageConverters
: 在默认转换器的基础上添加自定义转换器
1 |
|
建议使用 extendMessageConverters
和
extendHandlerExceptionResolvers
而不是完全替换默认配置
底层实现差异:
1 | // 在RequestMappingHandlerAdapter初始化时调用 |
addInterceptors(InterceptorRegistry registry)
用于注册自定义拦截器,可以在请求处理前后执行特定逻辑,如身份验证、日志记录等。
拦截器很像 Servlet 中的过滤器(Filter),但拦截器提供了更精细的控制和更丰富的功能,允许你在请求处理的不同阶段执行特定逻辑
拦截器是实现横切关注点的好方法,如认证、日志、性能监控等,在这里写一些登录常用的逻辑很不错
1 |
|
拦截器链的执行原理
sequenceDiagram
participant DispatcherServlet
participant Interceptor1
participant Interceptor2
participant Handler
DispatcherServlet->>Interceptor1: preHandle()
Interceptor1->>Interceptor2: preHandle()
Interceptor2->>Handler: 执行控制器方法
Handler-->>Interceptor2: postHandle()
Interceptor2-->>Interceptor1: postHandle()
Interceptor1-->>DispatcherServlet: afterCompletion()
拦截器与过滤器对比:
特性 | 拦截器(Interceptor) | 过滤器(Filter) |
---|---|---|
作用域 | Spring MVC上下文 | Servlet容器层面 |
依赖 | 依赖Spring框架 | 仅需Servlet API |
执行时机 | 控制器方法前后 | 请求进入Servlet之前 |
异常处理 | 可接入ControllerAdvice | 只能跳转错误页面 |
addResourceHandlers
用于配置静态资源处理器,如 CSS、JavaScript、图片等文件的访问路径。
1 |
|
addCorsMappings
用于配置跨域资源共享 (CORS),允许浏览器从不同域名访问 API。
CORS 原理:
- 浏览器实施同源策略,跨域请求需服务器明确允许
- 简单请求直接发送,预检请求(复杂请求)先发送 OPTIONS 请求
- Spring MVC
通过设置响应头(如
Access-Control-Allow-Origin
)实现 CORS 支持
1 |
|
configureHandlerExceptionResolvers
vs extendHandlerExceptionResolvers
默认异常解析器:
ExceptionHandlerExceptionResolver
- 处理带@ExceptionHandler
注解的方法ResponseStatusExceptionResolver
- 处理带@ResponseStatus
注解的异常DefaultHandlerExceptionResolver
- 处理 Spring MVC 标准异常
这两个方法用于配置异常处理器:
configureHandlerExceptionResolvers
: 完全自定义异常处理器列表extendHandlerExceptionResolvers
: 在默认处理器的基础上添加自定义处理器
1 |
|
configureContentNegotiation(ContentNegotiationConfigurer configurer)
配置内容协商策略,根据请求头或 URL 参数决定返回的数据格式(如 JSON、XML)。
1 |
|
configureAsyncSupport(AsyncSupportConfigurer configurer)
异步请求类型:
Callable
- 控制器返回Callable
,在单独线程中执行DeferredResult
- 控制器返回DeferredResult
,在另一个线程中设置结果ResponseBodyEmitter
- 流式响应SseEmitter
- 服务器发送事件StreamingResponseBody
- 流式响应体
配置异步请求支持,例如设置任务执行超时时间、线程池等。
1 |
|
configurePathMatch(PathMatchConfigurer configurer)
关键配置项:
setUseSuffixPatternMatch
- 是否启用后缀模式匹配(如/users.html
匹配/users
)setUseTrailingSlashMatch
- 是否启用尾部斜杠匹配(如/users/
匹配/users
)setUseRegisteredSuffixPatternMatch
- 仅匹配已注册的后缀setPathMatcher
- 设置自定义路径匹配器setUrlPathHelper
- 设置自定义 URL 路径帮助器
1 |
|
WebMvcAutoConfiguration 到底自动配置了哪些规则
SpringMVC 自动配置场景给我们配置了如下所有默认行为,其中的过程和涉及到的细节内容我也一起讲解,因为东西太多,只是过一遍会很混乱
WebMvcAutoConfiguration
web 场景的自动配置类支持 RESTful 的 filter:
HiddenHttpMethodFilter
- 作用:在浏览器表单仅支持
GET
、POST
原生请求方法的限制下,通过请求参数(默认参数名为_method
),将POST
请求转换为PUT
、DELETE
、PATCH
等符合 RESTful 规范的请求方法,让普通表单也能适配 RESTful 风格接口。 - 例如:前端页面要发送一个删除资源的
DELETE
请求,但浏览器无法直接发起,就可以用POST
表单携带_method=DELETE
参数,经此 Filter 转换后,后端控制器就能用@DeleteMapping
接收处理。
- 作用:在浏览器表单仅支持
支持非 POST 请求,请求体携带数据:
FormContentFilter
- 作用:对于
PUT
、PATCH
等非POST
请求,解决浏览器默认不会像POST
请求那样自动携带表单数据(请求体内容 )的问题。它会解析请求体中的表单参数,并将这些参数填充到请求对象中,使后端控制器方法能像处理POST
请求参数一样,正常获取PUT
、PATCH
等请求携带的表单数据。比如前端用PUT
请求更新用户信息,携带表单形式的用户姓名、年龄等参数,后端通过@RequestParam
等注解就能顺利拿到这些参数进行业务处理。 - 生效逻辑:自动注册到 Filter 链,针对
PUT
、PATCH
等方法的请求,在请求处理前期解析请求体表单数据,为后续控制器方法执行做准备。
- 作用:对于
导入
EnableWebMvcConfiguration
:EnableWebMvcConfiguration
是WebMvcAutoConfiguration
内部类,继承自DelegatingWebMvcConfiguration
,它借助 Spring 框架的配置机制,进一步初始化和配置一系列 Spring MVC 核心组件,具体如下:RequestMappingHandlerAdapter
:- 作为 Spring MVC 中处理请求的重要适配器,负责调用被
@RequestMapping
(及衍生的@GetMapping
、@PostMapping
等 )标注的控制器方法。在调用过程中,它会处理请求参数的绑定(比如将 HTTP 请求参数转换为控制器方法的入参类型 )、返回值的处理(把控制器方法返回结果转换为合适的响应数据格式,如 JSON、视图名等 ),是连接请求、控制器方法、响应的关键桥梁。 - 初始化:由
EnableWebMvcConfiguration
依据 Spring 容器的 Bean 管理机制,结合默认配置和用户可能的自定义配置(若有实现WebMvcConfigurer
相关参数处理定制 ),完成创建和初始化,确保能适配各种常见的参数、返回值处理场景。
- 作为 Spring MVC 中处理请求的重要适配器,负责调用被
WelcomePageHandlerMapping
:欢迎页功能支持(模板引擎目录、静态资源目录放 index.html)- 当访问应用根路径(
/
)时,它会按照一定优先级顺序去查找欢迎页资源。优先在模板引擎可解析的目录(如使用 Thymeleaf 时的classpath:/templates/
)下查找index.html
,若未找到,会到静态资源目录(classpath:/META-INF/resources/
、classpath:/resources/
、classpath:/static/
、classpath:/public/
等 )中寻找index.html
文件,找到后就会将该页面作为欢迎页展示,让访问根路径的请求能直接呈现友好的首页内容。
- 当访问应用根路径(
RequestMappingHandlerMapping
:找每个请求由谁处理的映射关系- 负责扫描 Spring 容器中所有被
@Controller
、@RestController
标注的控制器类,以及这些类中被@RequestMapping
及其衍生注解(@GetMapping
、@PostMapping
等 )标注的方法,然后建立并维护 “请求路径 ↔︎ 控制器方法” 的映射关系。后续当有 HTTP 请求到达时,能依据请求路径快速找到对应的控制器方法进行处理,是 Spring MVC 实现请求路由的核心基础。 - 扫描与构建:在应用启动时,它会遍历符合条件的 Bean ,解析注解信息,构建起庞大的请求路径映射注册表,并且在应用运行过程中,若有 Bean 动态加载(如通过 Bean 定义注册器新增控制器 Bean ),也能适时更新映射关系。
- 负责扫描 Spring 容器中所有被
ExceptionHandlerExceptionResolver
:默认的异常解析器- 作为 Spring MVC
默认的异常解析器,用于处理控制器方法执行过程中抛出的异常。它会查找被
@ExceptionHandler
标注的异常处理方法(可以是当前控制器类中的方法,也能是通过@ControllerAdvice
全局配置的方法 ),将异常交由对应的处理方法进行逻辑处理(比如返回自定义错误提示、错误码等 ),最终生成合适的响应(可以是 JSON 数据、错误页面等 )返回给客户端,保证应用遇到异常时能有统一、友好的错误处理表现。 - 异常处理流程:当控制器方法抛出异常后,
DispatcherServlet
会将异常交给ExceptionHandlerExceptionResolver
,它依据异常类型去匹配对应的@ExceptionHandler
方法,执行方法得到处理结果后,再转换为响应发送给客户端,若未找到匹配的处理方法,会按默认的异常处理逻辑(如返回 500 错误等 )处理。
- 作为 Spring MVC
默认的异常解析器,用于处理控制器方法执行过程中抛出的异常。它会查找被
LocaleResolver
:国际化解析器- 用于处理 Web 应用的国际化(多语言
)需求,解析请求中的语言区域信息。默认情况下,它会根据 HTTP 请求头中的
Accept-Language
字段来判断客户端期望的语言类型(如zh-CN
表示中文 - 中国,en-US
表示英文 - 美国 ),然后结合应用中配置的国际化资源文件(如messages_zh_CN.properties
、messages_en_US.properties
等 ),为后续的视图渲染、消息提示等提供对应的语言环境支持,让应用能根据不同地区用户展示合适的语言内容。 - 若默认的基于
Accept-Language
的解析方式不能满足需求(比如想通过请求参数?lang=zh
来切换语言 ),可通过实现LocaleResolver
接口自定义解析逻辑,再配置到 Spring MVC 环境中替换默认实现。
- 用于处理 Web 应用的国际化(多语言
)需求,解析请求中的语言区域信息。默认情况下,它会根据 HTTP 请求头中的
ThemeResolver
:主题解析器- 主要用于处理 Web 应用的主题切换需求,比如不同的页面风格、样式主题等。它会依据一定的规则(默认可通过请求参数、Session 等方式 )确定当前请求对应的主题,后续视图解析、资源加载等环节就能根据主题信息,使用对应的主题资源(如不同主题的 CSS 样式文件、页面模板等 ),实现应用界面主题的灵活切换和展示。
- 应用场景:在一些需要让用户自定义界面风格(如浅色主题、深色主题
)的系统中,通过
ThemeResolver
配合主题相关的视图解析、资源管理,能很好地实现不同主题的切换和呈现。
FlashMapManager
:临时数据共享实现重定向时临时数据的共享功能。当控制器方法处理完请求,需要重定向到另一个 URL ,并且希望在重定向后能获取到一些 “一次性” 的数据(如提示信息 “操作成功,请查看详情” )时,可通过
FlashMap
存储这些数据,FlashMapManager
负责管理FlashMap
的创建、存储(通常存储在 Session 中 )和获取。重定向前将数据存入FlashMap
,重定向后的请求处理时,FlashMapManager
会取出数据供后续使用,使用完后这些数据会被清除,保证是 “一次性” 的。1
2
3
4
5
6
7
public String saveData(RedirectAttributes redirectAttributes) {
// 业务处理...
redirectAttributes.addFlashAttribute("msg", "数据保存成功");
return "redirect:/list";
// 在重定向后的 /list 对应的控制器方法或视图中,就能获取到 msg 这个一次性提示数据。
}
FormattingConversionService
:数据格式化、类型转化- 职责:承担着数据格式化和类型转换的重要职责。在请求参数绑定阶段,它会将
HTTP
请求中的字符串参数,按照一定规则转换为控制器方法入参的对应类型(比如把请求参数中的字符串
“2024-10-01” 转换为
java.util.Date
类型 );在响应数据处理时,也能将一些复杂类型(如自定义的枚举类型 )格式化为合适的字符串或其他可传输的格式。同时,它默认集成了对 JSR303 校验相关的支持,在数据转换、绑定过程中,能配合校验注解(如@DateTimeFormat
结合@Valid
)进行数据格式的校验和转换。 - 扩展能力:用户可通过实现
Formatter
、Converter
接口,自定义数据格式化和类型转换规则,然后注册到FormattingConversionService
中,实现对特殊类型数据(如自定义的日期格式、自定义业务枚举 )的个性化转换和格式化。
- 职责:承担着数据格式化和类型转换的重要职责。在请求参数绑定阶段,它会将
HTTP
请求中的字符串参数,按照一定规则转换为控制器方法入参的对应类型(比如把请求参数中的字符串
“2024-10-01” 转换为
Validator
:数据校验 JSR303 提供的数据校验功能- 职责:提供数据校验功能,基于 JSR303(Java Bean Validation 规范
)及后续的 JSR349、JSR380 等规范,支持使用
@Valid
、@NotBlank
、@Size
等校验注解,对控制器方法的入参(如@RequestBody
接收的对象、@RequestParam
绑定的参数等 )、实体类的属性进行校验。当校验不通过时,会抛出对应的校验异常,可结合ExceptionHandlerExceptionResolver
进行统一的异常处理和错误提示返回,保证输入数据的合法性和规范性。
- 职责:提供数据校验功能,基于 JSR303(Java Bean Validation 规范
)及后续的 JSR349、JSR380 等规范,支持使用
WebBindingInitializer
:请求参数的封装与绑定- 在 Spring MVC
请求参数绑定的过程中,负责初始化数据绑定的相关设置。它会参与到请求参数转换为控制器方法入参的整个流程,比如设置默认的类型转换器(关联到
FormattingConversionService
)、初始化数据绑定的一些基础规则(如是否允许空值、日期格式的默认处理等 ),确保请求参数能准确、合理地绑定到控制器方法的参数上,为控制器方法正确执行提供数据基础。 - 关联关系:与
FormattingConversionService
紧密协作,FormattingConversionService
提供具体的类型转换和格式化能力,WebBindingInitializer
则在绑定流程中运用这些能力,同时进行一些初始化、规则设置的工作。
- 在 Spring MVC
请求参数绑定的过程中,负责初始化数据绑定的相关设置。它会参与到请求参数转换为控制器方法入参的整个流程,比如设置默认的类型转换器(关联到
ContentNegotiationManager
:内容协商管理器- 职责:实现内容协商功能,决定客户端请求期望的响应数据格式,以及服务端实际返回的响应数据格式。它会综合考虑多个因素来确定响应格式,包括请求头中的
Accept
字段(客户端期望接收的媒体类型,如application/json
、text/html
等 )、请求参数(可通过设置参数如?format=json
来指定响应格式 )等。根据协商结果,Spring MVC 会选择合适的消息转换器(如MappingJackson2HttpMessageConverter
用于转换 JSON 格式 )来处理响应数据,保证返回给客户端的数据格式是其期望或可接受的。 - 应用场景:在一个同时提供 JSON 数据接口和 HTML 页面展示的 Web
应用中,通过
ContentNegotiationManager
,就能根据客户端不同的请求(如浏览器直接访问返回 HTML 页面,手机端接口调用返回 JSON 数据 ),灵活返回对应的响应格式,提升应用的兼容性和适用性。
- 职责:实现内容协商功能,决定客户端请求期望的响应数据格式,以及服务端实际返回的响应数据格式。它会综合考虑多个因素来确定响应格式,包括请求头中的
WebMvcAutoConfigurationAdapter
配置生效,它是一个WebMvcConfigurer
,定义 mvc 底层组件WebMvcAutoConfigurationAdapter
是WebMvcAutoConfiguration
内部的静态类,它实现了WebMvcConfigurer
接口,作为 Spring Boot 自动配置的具体实现,用来定义 Spring MVC 底层组件的默认配置,以下是其关键配置点:定义好
WebMvcConfigurer
底层组件默认功能;所有功能详见下面或者上面的列表视图解析器:
InternalResourceViewResolver
- 主要用于解析 JSP 等 “内部资源视图”。当控制器方法返回一个视图名(如
return "userInfo"
)时,它会按照配置的前缀(如prefix = "/WEB-INF/views/"
)和后缀(如suffix = ".jsp"
)规则,拼接出完整的视图资源路径(即/WEB-INF/views/userInfo.jsp
),然后找到对应的 JSP 文件进行渲染,将动态数据填充到 JSP 页面中,最终返回给客户端呈现。在WebMvcAutoConfigurationAdapter
中,会依据 Spring Boot 的默认配置策略,设置合适的前缀和后缀(也可通过application.properties
等配置文件进行自定义调整 ),适配常见的 JSP 视图存储目录结构,让基于 JSP 的 Web 应用能便捷地进行视图解析和渲染。
- 主要用于解析 JSP 等 “内部资源视图”。当控制器方法返回一个视图名(如
视图解析器:
BeanNameViewResolver
, 视图名(controller 方法的返回值字符串)就是组件名- 将控制器方法返回的视图名,直接作为 Spring 容器中
View
类型 Bean 的名称去查找对应的视图组件。也就是说,若控制器方法返回视图名 “customView” ,那么 Spring 容器中需要存在一个名为 “customView” 且类型为View
的 Bean(可以是自定义的View
实现类 ),BeanNameViewResolver
会找到该 Bean 并使用它来渲染视图,实现灵活的视图定制。
- 将控制器方法返回的视图名,直接作为 Spring 容器中
内容协商解析器:
ContentNegotiatingViewResolver
- 它本身并不直接解析视图,而是结合
ContentNegotiationManager
的内容协商结果,从多个视图解析器(如InternalResourceViewResolver
、BeanNameViewResolver
等 )中选择合适的视图解析器来解析视图。例如,内容协商确定需要返回 HTML 格式的视图,它就会在能解析 HTML 视图的解析器中挑选(如InternalResourceViewResolver
若配置了解析 JSP 生成 HTML ),然后使用该解析器进行视图解析和渲染,是一个 “协调者” 角色,整合多种视图解析器和内容协商功能。 - 工作流程:先通过
ContentNegotiationManager
确定响应数据格式需求,再遍历其管理的视图解析器列表,找到第一个能满足该格式需求且能解析对应视图名的解析器,交由其进行视图解析和渲染,保证在内容协商的基础上,能正确找到并使用合适的视图资源。
- 它本身并不直接解析视图,而是结合
请求上下文过滤器:
RequestContextFilter
:任意位置直接获取当前请求- 为应用中任意位置(包括非 Web 层的 Service、Component 等
)提供获取当前 HTTP
请求上下文(
HttpServletRequest
、HttpServletResponse
)的能力。它会在请求处理过程中,将当前的请求和响应对象绑定到线程局部变量(ThreadLocal
)中,后续在同一线程的任意位置,都可以通过RequestContextHolder.currentRequestAttributes()
等方式获取到当前请求的上下文信息,方便一些非 Web 层组件在需要时使用请求相关的数据(如获取请求头信息、Session 数据等 )。 - 注意事项:因为是基于
ThreadLocal
实现,所以要注意线程安全和资源释放问题,在异步处理场景中,若不正确处理,可能会导致获取到错误的请求上下文或资源泄漏,不过 Spring Boot 对常见的异步场景也有相应的处理机制来保障其正确性。
1
2
3
4
5
6
7
8
9
10
11public class aService {
public void getRequest(){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// 任意位置通过 RequestContextHolder 获取到当前请求和响应的信息
HttpServletRequest request = attributes.getRequest();
HttpServletResponse response = attributes.getResponse();
String url = request.getRequestURI();
}
}- 为应用中任意位置(包括非 Web 层的 Service、Component 等
)提供获取当前 HTTP
请求上下文(
静态资源链规则
ProblemDetailsExceptionHandler
:错误详情- 统一处理 Spring MVC
内部抛出的异常,生成标准化的错误详情响应。当控制器方法抛出异常(如参数校验失败的
MethodArgumentNotValidException
、资源未找到的NoSuchRequestHandlingMethodException
等 )时,它会将异常信息封装成包含type
(错误类型标识 )、title
(错误标题 )、status
(HTTP 状态码 )、detail
(错误详情 )等字段的 JSON 响应,让客户端能更清晰、规范地识别错误。
- 统一处理 Spring MVC
内部抛出的异常,生成标准化的错误详情响应。当控制器方法抛出异常(如参数校验失败的
定义了 MVC 默认的底层行为:
WebMvcConfigurer
WebMvcAutoConfigurationAdapter
本身就是WebMvcConfigurer
的实现类,它为 Spring MVC 的所有底层行为提供了 “开箱即用” 的默认配置
核心总结
WebMvcAutoConfiguration
作为 Spring Boot
自动配置的核心,通过以下方式为 Web 应用搭建 MVC 基石:
- Filter 层:通过
HiddenHttpMethodFilter
、FormContentFilter
补全浏览器请求能力,适配 RESTful 风格和非 POST 请求的表单处理。 - 核心组件层:借助
EnableWebMvcConfiguration
初始化RequestMappingHandlerMapping
、ExceptionHandlerExceptionResolver
等 MVC 核心组件,构建 “请求路由 → 处理 → 异常处理” 的完整流程。 - 默认配置层:通过
WebMvcAutoConfigurationAdapter
实现WebMvcConfigurer
,为视图解析、资源处理、错误详情等提供开箱即用的默认规则,同时预留WebMvcConfigurer
扩展点,支持用户按需覆盖。
理解这些后,再看 Spring Boot 中的 Web 应用:大部分 MVC
需求(如静态资源、视图解析、异常处理 )都能 “零配置”
运行,这背后正是 WebMvcAutoConfiguration
的功劳;而当需要定制(如修改 JSON 序列化规则、添加自定义拦截器
)时,只需实现 WebMvcConfigurer
,就能在默认配置基础上
“微创” 调整,既享受自动配置的便捷,又保留定制化的灵活性 。
使用表格总结如下
方法名 | 默认规则 | 核心参数 | 常用场景 |
---|---|---|---|
configurePathMatch |
默认启用后缀模式匹配(如/users.html 匹配/users )和尾部斜杠匹配(如/users/ 匹配/users ) |
- setUseSuffixPatternMatch : 是否启用后缀模式匹配 -
setUseTrailingSlashMatch : 是否启用尾部斜杠匹配 -
setPathMatcher : 设置自定义路径匹配器 |
自定义 URL 匹配规则,如禁用.html 后缀匹配 |
configureContentNegotiation |
默认基于请求的 Accept 头确定响应内容类型,支持 JSON、XML 等 | - defaultContentType : 设置默认内容类型 -
favorPathExtension : 是否优先使用 URL 扩展名进行内容协商 -
mediaTypes : 注册媒体类型映射 |
设置默认响应格式为 JSON,配置基于 URL 扩展名的内容协商 |
configureAsyncSupport |
默认异步请求超时时间为 30 秒,使用 SimpleAsyncTaskExecutor 执行异步任务 | - setDefaultTimeout : 设置异步请求超时时间 -
setTaskExecutor : 设置异步任务执行器 -
registerCallableInterceptors : 注册 Callable 拦截器 |
设置异步请求超时时间,配置 DeferredResult 处理 |
configureDefaultServletHandling |
默认不启用默认 Servlet 处理,静态资源由 Spring MVC 处理 | - enable : 启用默认 Servlet 处理 -
enableDispatcherTypes : 指定 DispatcherType |
启用默认 Servlet 处理静态资源 |
addFormatters |
默认注册 JSR-310 日期时间格式化器、数字格式化器等 | - FormatterRegistry :
用于注册格式化器和转换器的注册表 |
添加日期格式化器,注册自定义类型转换器 |
addInterceptors |
默认不注册任何拦截器 | - InterceptorRegistry : 用于注册拦截器的注册表 -
addPathPatterns : 指定拦截路径 -
excludePathPatterns : 指定排除路径 - order :
设置拦截器顺序 |
添加身份验证拦截器,实现请求日志记录 |
addResourceHandlers |
默认从classpath:/META-INF/resources/ ,
classpath:/resources/ , classpath:/static/ ,
classpath:/public/ 加载静态资源,缓存控制头为 365 天 |
- addResourceHandler : 指定 URL 路径 -
addResourceLocations : 指定资源位置 -
setCacheControl : 设置缓存控制头 -
setCachePeriod : 设置缓存时间(秒) |
配置静态资源路径,设置缓存控制头 |
addCorsMappings |
默认不配置任何 CORS 映射 | - addMapping : 指定 CORS 映射路径 -
allowedOrigins : 允许的源 - allowedMethods :
允许的 HTTP 方法 - allowedHeaders : 允许的请求头 -
allowCredentials : 是否允许发送 Cookie -
maxAge : 预检请求的有效期(秒) |
允许特定域名访问 API,配置跨域请求头 |
addViewControllers |
默认不注册任何视图控制器 | - ViewControllerRegistry : 用于注册视图控制器的注册表 -
addViewController : 添加视图控制器 -
setViewName : 设置视图名称 |
简化登录页面、主页等简单视图的映射 |
configureViewResolvers |
默认根据依赖自动配置视图解析器,如 Thymeleaf、FreeMarker 等 | - ViewResolverRegistry : 用于配置视图解析器的注册表 -
jsp : 配置 JSP 视图解析器 - thymeleaf : 配置
Thymeleaf 视图解析器 - freemarker : 配置 FreeMarker
视图解析器 |
配置 JSP、Thymeleaf 等视图解析器 |
addArgumentResolvers |
默认注册 RequestParamMethodArgumentResolver、PathVariableMethodArgumentResolver 等 | - HandlerMethodArgumentResolver :
自定义参数解析器列表 |
添加自定义参数解析器,如用户会话参数 |
addReturnValueHandlers |
默认注册 RequestResponseBodyMethodProcessor、ViewNameMethodReturnValueHandler 等 | - HandlerMethodReturnValueHandler :
自定义返回值处理器列表 |
添加自定义返回值处理器,如统一 API 响应格式 |
configureMessageConverters |
默认注册 MappingJackson2HttpMessageConverter、StringHttpMessageConverter 等 | - HttpMessageConverter :
自定义消息转换器列表(将替换默认转换器) |
完全自定义消息转换器,如使用自定义 JSON 序列化器 |
extendMessageConverters |
默认注册 MappingJackson2HttpMessageConverter、StringHttpMessageConverter 等 | - HttpMessageConverter :
自定义消息转换器列表(添加到默认转换器之后) |
在默认转换器基础上添加自定义转换器 |
configureHandlerExceptionResolvers |
默认注册 ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver 等 | - HandlerExceptionResolver :
自定义异常解析器列表(将替换默认解析器) |
完全自定义异常处理机制 |
extendHandlerExceptionResolvers |
默认注册 ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver 等 | - HandlerExceptionResolver :
自定义异常解析器列表(添加到默认解析器之后) |
添加自定义异常处理器 |
addErrorResponseInterceptors |
默认不注册任何错误响应拦截器 | - ErrorResponse.Interceptor : 错误响应拦截器列表 |
自定义错误响应格式,添加额外错误信息 |
getValidator |
默认使用 Spring 的 LocalValidatorFactoryBean,支持 JSR-303/349 验证 | - 返回实现 Validator 接口的自定义验证器 | 提供自定义验证器,如使用 Hibernate Validator |
getMessageCodesResolver |
默认使用 DefaultMessageCodesResolver | - 返回实现 MessageCodesResolver 接口的自定义解析器 | 自定义错误代码解析逻辑 |
@EnableWebMvc 禁用默行为的原理
@EnableWebMvc
的作用
核心逻辑:
@EnableWebMvc
会向 Spring 容器中导入DelegatingWebMvcConfiguration
组件。- 而
DelegatingWebMvcConfiguration
是WebMvcConfigurationSupport
的子类 ,这意味着一旦使用@EnableWebMvc
,本质上就是让WebMvcConfigurationSupport
相关逻辑进入容器。
- 而
Spring Boot 中 Spring MVC 自动配置的条件
关键注解:
WebMvcAutoConfiguration
(Spring Boot 对 Spring MVC 的自动配置类)上有一个条件注解:1
含义是:当 Spring 容器中没有
WebMvcConfigurationSupport
类型的 Bean 时,WebMvcAutoConfiguration
才会生效,进而启用 Spring Boot 对 Spring MVC 的默认自动配置。
@EnableWebMvc
禁用默认自动配置的原因
- 因为
@EnableWebMvc
导入了WebMvcConfigurationSupport
(通过DelegatingWebMvcConfiguration
间接引入 ),此时容器中存在WebMvcConfigurationSupport
类型的 Bean。 - 这就触发了
WebMvcAutoConfiguration
的条件注解@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
不满足条件,导致WebMvcAutoConfiguration
失效,最终禁用了 Spring Boot 对 Spring MVC 的默认自动配置行为。
所以,@EnableWebMvc
的影响体现在,一旦在配置类上标注
@EnableWebMvc
,会让 Spring Boot 中 Spring MVC
的自动配置失效,需要你自己通过 WebMvcConfigurer
(或直接继承
WebMvcConfigurationSupport
)手动配置 Spring MVC
的底层组件(如拦截器、消息转换器、视图解析器等 。
而WebMvcConfigurer
的角色就充当是一个定义 Spring MVC
底层组件功能的接口,你可以实现它来定制 Spring MVC 行为。即使不用
@EnableWebMvc
(即保留 Spring Boot 自动配置),也能通过
WebMvcConfigurer
做定制化扩展;但用了
@EnableWebMvc
后,自动配置失效,更需要实现
WebMvcConfigurer
接口或更底层的
WebMvcConfigurationSupport
接口来手动搭建 MVC
功能,实现自己的 WebMvcConfigurer
配置类。