SpringBoot3 基础教程之三 Web 开发
大纲
- SpringBoot3 基础教程之一快速入门
- SpringBoot3 基础教程之二常规配置
- SpringBoot3 基础教程之三 Web 开发
- SpringBoot3 基础教程之四 Web 开发
- SpringBoot3 基础教程之五基础特性
- SpringBoot3 基础教程之六场景整合
- SpringBoot3 基础教程之七场景整合
- SpringBoot3 基础教程之八场景整合
- SpringBoot3 基础教程之九核心原理
前言
本章节所需的案例代码,可以直接从 GitHub 下载对应章节 spring-boot3-04。
自动配置
自动配置的原理
- Web 场景的自动配置原理
- 1、导入
spring-boot-starter-web,会导入spring-boot-starter,也就会导入spring-boot-autoconfigure包。 - 2、
spring-boot-autoconfigure包里面有一个文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定了应用启动时所有要加载的自动配置类。 - 3、
@EnableAutoConfiguration会自动地将上面文件里写的所有自动配置类都导入进来,同时xxxAutoConfiguration是有声明条件注解的,目的是按需加载。 - 4、
xxxAutoConfiguration往容器中导入一堆组件,这些组件都是从xxxProperties中获取属性值。 - 5、
xxxProperties又是和配置文件进行了绑定。
- 1、导入
- Web 场景的所有自动配置类
1 | org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration |
- Web 场景下配置文件的前缀配置项说明
- 1、服务器的配置
server - 2、Web 场景通用配置
spring.web - 3、Spring MVC 的所有配置
spring.mvc - 4、文件上传配置
spring.servlet.multipart
- 1、服务器的配置
自动配置的默认效果
SpringBoot Web 场景自动配置的效果如下:
- 支持静态
index.html - 支持默认的静态资源处理机制,静态资源放在
static文件夹下即可直接访问 - 包含了
ContentNegotiatingViewResolver和BeanNameViewResolver组件,用于视图解析 - 自动注册了
Converter,GenericConverter,Formatter组件,适配了常见的数据类型转换和格式化需求 - 支持
HttpMessageConverters,可以方便返回 JSON 等数据类型 - 注册
MessageCodesResolver,方便国际化及错误消息处理 - 自动使用
ConfigurableWebBindingInitializer实现消息处理、数据绑定、类型转化、数据校验等功能
重点知识
- 如果想保持 SpringBoot MVC 的默认配置,并且自定义更多的 MVC 配置(如 interceptors,formatters,view controllers 等),可以使用
@Configuration标注一个配置类,让配置类实现WebMvcConfigurer接口,并不要使用@EnableWebMvc注解。 - 如果想保持 SpringBoot MVC 的默认配置,但要自定义核心组件的实例(如
RequestMappingHandlerMapping,RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver),往容器中放一个WebMvcRegistrations组件,并不要使用@EnableWebMvc注解。 - 如果想全面接管 SpringBoot MVC 的配置,可以使用
@Configuration标注一个配置类,让配置类实现WebMvcConfigurer接口,并加上@EnableWebMvc注解即可。
静态资源
默认静态资源规则
静态资源映射
静态资源映射规则都在 WebMvcAutoConfiguration 自动配置类中进行了定义。
- 访问
/webjars/**路径就会去classpath:/META-INF/resources/webjars/下找资源,一般用于访问通过 Maven 引入的第三方前端组件(如 Vue、Bootstrap) - 访问
/**路径就会去静态资源默认的四个位置找资源,包括classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/
静态资源缓存
所有静态资源都定义了缓存规则,浏览器访问过一次,就会缓存一段时间,但此功能的参数无默认值。
cachePeriod:缓存周期,多久不用找服务器要新的,默认值 0s,以秒为单位cacheControl: HTTP 缓存控制,参照 Mozilla 文档useLastModified:是否使用Last-Modified头,默认值false,配合 HTTP Cache 规则使用- 所有缓存参数的配置,都可以通过配置文件里的
spring.web前缀配置项指定(如下)
1 | # 缓存周期(秒) |
Favicon 图标
- 在默认的四个静态资源路径下查找
favicon.ico
欢迎页面
欢迎页面的映射规则在 WebMvcAutoConfiguration 中进行了定义:
- 首先会在默认的四个静态资源路径下查找
index.html - 如果静态资源路径下找不到,就会在
templates目录下找index模板页面
自定义静态资源规则
配置方式
spring.mvc:配置静态资源访问路径的前缀spring.web:配合静态资源目录、静态资源策略 (开启映射、处理链、缓存规则)、国际化的区域信息
1 | # 自定义静态资源访问路径的前缀 |
提示
- 当不使用
spring.mvc.static-path-pattern自定义静态资源访问路径的前缀时,静态资源默认的访问路径示例是http://127.0.0.1:8080/backgrond.png - 当使用
spring.mvc.static-path-pattern=/static/**自定义静态资源访问路径的前缀时,静态资源的访问路径示例是http://127.0.0.1:8080/static/backgrond.png
代码方式
提示
- 如果希望完全禁用 SpringBoot MVC 的自动配置,可以在配置类上添加
@EnableWebMvc注解,此时相当于采用全手动的方式配置 MVC。
- 第一种写法:实现
WebMvcConfigurer接口,同样可以自定义静态资源规则
1 | import org.springframework.context.annotation.Configuration; |
- 第二种写法:使用
@Bean注解,定义WebMvcConfigurer组件,同样可以自定义静态资源规则
1 | import org.springframework.context.annotation.Bean; |
错误处理
默认机制
SpringBoot 错误处理的自动配置都在 ErrorMvcAutoConfiguration 中,两大核心机制:
- 1、SpringBoot 会自适应处理错误,响应页面或 JSON 数据给客户端
- 2、SpringMVC 的错误处理机制依然保留,SpringMVC 处理不了的,才会交给 SpringBoot 进行处理

- 发生错误以后,请求转发给
/error路径,SpringBoot 在底层写好一个BasicErrorController组件,专门处理这个请求
1 | /** |
- 错误页面是这么解析到的
1 | // 解析错误的自定义视图地址 |
- 容器中专门有一个错误视图解析器
1 |
|
- SpringBoot 解析自定义错误页的默认规则
1 |
|
- 容器中有一个默认的名为
error的 View,提供了默认错误页面的功能
1 |
|
- 封装了 JSON 格式的错误信息
1 |
|
- 错误页面的解析规则
- 1、解析一个错误页
- a. 如果发生了 500、404、503、403 这些错误
- ⅰ. 如果有模板引擎,模板文件默认在
classpath:/templates/error/精确码.html - ⅱ. 如果没有模板引擎,在静态资源文件夹下找
精确码.html
- ⅰ. 如果有模板引擎,模板文件默认在
- b. 如果匹配不到
精确码.html这些精确的错误页,就去找5xx.html,4xx.html模糊匹配- ⅰ. 如果有模板引擎,模板文件默认在
classpath:/templates/error/5xx.html - ⅱ. 如果没有模板引擎,在静态资源文件夹下找
5xx.html
- ⅰ. 如果有模板引擎,模板文件默认在
- a. 如果发生了 500、404、503、403 这些错误
- 2、如果模板引擎路径
templates下有error.html页面,就直接渲染并返回给客户端
- 1、解析一个错误页
自定义错误响应
- 自定义 JSON 响应,使用
@ControllerAdvice+@ExceptionHandler进行统一异常处理
1 |
|
- 自定义页面响应,根据 SpringBoot 的错误页面解析规则,自定义错误页面。
错误处理的最佳实践
- 前后端分离开发模式
- 后台发生的所有错误,通过
@ControllerAdvice+@ExceptionHandler进行统一异常处理
- 后台发生的所有错误,通过
- 前后端不分离模式(服务端模板页面渲染)
- 一些不可预知的错误,如使用 HTTP 码表示的服务器或客户端错误
- 在
classpath:/templates/error/下面,存放常用精确的错误码页面,如500.html、404.html - 在
classpath:/templates/error/下面,存放通用模糊匹配的错误码页面,如5xx.html、4xx.html
- 在
- 发生业务错误
- 核心业务的每一种错误,都应该通过代码控制,跳转到定制的错误页
- 通用业务,可以通过
classpath:/templates/error.html错误页面,显示通用的错误信息
- 一些不可预知的错误,如使用 HTTP 码表示的服务器或客户端错误
- 在模板页面或者服务端返回的 JSON 数据中,可用的 Model 数据如下:

嵌入式容器
Servlet 容器指的是管理、运行 Servlet 组件(Servlet、Filter、Listener)的环境,一般指 Web 服务器。
自动配置原理
- SpringBoot 默认使用嵌入的 Tomcat 作为 Servlet 容器
- 嵌入式容器的自动配置类是
ServletWebServerFactoryAutoConfiguration,EmbeddedWebServerFactoryCustomizerAutoConfiguration ServletWebServerFactoryAutoConfiguration自动配置了嵌入式容器场景- 绑定了
ServerProperties配置类,所有和服务器相关的配置都使用server作为开始前缀 ServletWebServerFactoryAutoConfiguration默认导入了嵌入式的三大服务器,包括Tomcat、Jetty、Undertow- 导入
Tomcat、Jetty、Undertow时都有条件注解,系统中有对应的类才会生效(也就是导了包) - 在默认情况下,Tomcat 的配置会生效,SpringBoot 往容器中放了
TomcatServletWebServerFactory组件 - 往容器中放一个 Web 服务器工厂
ServletWebServerFactory后,可以创建 Web 服务器 - Web 服务器工厂都有一个功能,可以调用
getWebServer()获取 Web 服务器 TomcatServletWebServerFactory创建了 Tomcat Web 服务器
- 导入
ServletWebServerApplicationContextIOC 容器在启动的时候,会调用ServletWebServerFactory创建 Web 服务器- Spring 容器刷新(启动)的时候,会预留一个时机,调用
onRefresh()刷新子容器 refresh()容器刷新,十二大步的刷新子容器会调用onRefresh()
1 |
|
1 |
|
总结
- Web 场景的 Spring 容器启动,在调用
onRefresh()的时候,会调用创建 Web 服务器的方法。 - Web 服务器的创建是通过
WebServerFactory实现的,容器中又会根据条件注解,启动相关的服务器配置,默认EmbeddedTomcat会往容器中放一个TomcatServletWebServerFactory组件,导致项目启动后,自动创建出 Tomcat 服务器。
自定义嵌入式容器
- 嵌入式三大容器有
Tomcat、Jetty、Undertow,SpringBoot 默认使用 Tomcat 作为容器。若希望切换到其他容器,只需要更改 Maven 的配置即可,如下所示:
1 | <properties> |
- 最佳实践
- 修改以
server为开始前缀的相关配置,这样就可以修改服务器参数 - 通过往容器中放一个
ServletWebServerFactory组件,来禁用掉 SpringBoot 默认引入的 Web 服务器工厂,这样就可以实现自定义任意的嵌入服务器。
- 修改以
底层源码浅析
Web MVC 自动配置原理
自动配置生效的条件
1 | /** |
自动配置实现的效果
效果一:往容器中放了两个 Filter
HiddenHttpMethodFilter:页面表单提交 REST 请求(支持 GET、POST、PUT、DELETE 方法)FormContentFilter: 表单内容 Filter,GET(数据放 URL 后面)、POST(数据放请求体)请求可以携带数据,PUT、DELETE 的请求体数据会被忽略
效果二:往容器中放了 WebMvcConfigurer 组件,给 Spring MVC 添加各种定制功能,所有功能最终都会和配置文件的内容进行绑定
WebMvcProperties: 绑定了以spring.mvc为开始前缀的配置项WebProperties: 绑定了以spring.web为开始前缀的配置项
WebMvcConfigurer 接口
1 |
|

静态资源映射规则的源码
1 | public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware { |
规则一:访问 /webjars/** 路径就会去 classpath:/META-INF/resources/webjars/ 下找资源,一般用于访问通过 Maven 引入的第三方前端组件(如 Vue、Bootstrap)
规则二:访问 /** 路径就会去静态资源默认的四个位置找资源,包括 classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/
规则三:静态资源默认都有缓存规则的设置
- 所有缓存参数的配置,都可以通过配置文件里的
spring.web前缀配置项指定 cachePeriod:缓存周期,多久不用找服务器要新的,默认值 0s,以秒为单位cacheControl: HTTP 缓存控制,参照 Mozilla 文档useLastModified:是否使用Last-Modified头,默认值false,配合 HTTP Cache 规则使用
1 | registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod())); |
提示
当浏览器访问了一个静态资源文件 index.js,如果在服务器中这个资源文件没有发生变化,那么在用户下次访问的时候,就可以直接让浏览器用本地缓存中的资源文件,而不用给服务器发送请求。
EnableWebMvcConfiguration 的源码
EnableWebMvcConfiguration 继承了 DelegatingWebMvcConfiguration,而 DelegatingWebMvcConfiguration 则继承了 WebMvcConfigurationSupport。
1 |
|
1 |
|
SpringBoot 默认会往容器中放入 WebMvcConfigurationSupport 组件,如果开发者注册了 WebMvcConfigurationSupport 组件,那么 SpringBoot 的 WebMvcAutoConfiguration 组件就会失效。这相当于禁用 SpringBoot 的自动配置,采用全手动的方式配置 MVC。
1 |
|
- 欢迎页面的查找规则
HandlerMapping:根据请求路径找到能处理请求的 HandlerWelcomePageHandlerMapping:- 访问
/**路径下的所有请求,都会去默认的四个静态资源路径下查找页面,这也适用于欢迎页面 - 只要在任意一个静态资源路径下有一个
index.html页面,项目启动后就可以正常访问它
- 访问
为什么定义 WebMvcConfigurer 就能配置底层行为
WebMvcAutoConfiguration是一个自动配置类,它里面有一个EnableWebMvcConfiguration配置类EnableWebMvcConfiguration继承了DelegatingWebMvcConfiguration,且两者都会生效DelegatingWebMvcConfiguration利用 DI (自动注入) 将容器中所有的WebMvcConfigurer都注入进来- 别人调用
DelegatingWebMvcConfiguration的方法配置底层规则,而它自身则调用所有WebMvcConfigurer的底层配置方法。
1 | /** |
全面接管 Spring MVC
SpringBoot 默认配置好了 Spring MVC 的所有常用特性,如果需要全面接管 Spring MVC 的所有配置并禁用默认配置,仅需要编写一个 WebMvcConfigurer 配置类,并标注 @EnableWebMvc 即可。
WebMvcAutoConfiguration 自动配置了哪些规则
Spring MVC 自动配置场景给我们配置了如下所有默认行为:
WebMvcAutoConfigurationWeb 场景的自动配置类- 支持 RESTful 的 Filter:
HiddenHttpMethodFilter - 支持非 POST 请求体携带数据:
FormContentFilter - 导入
EnableWebMvcConfiguration配置类后:RequestMappingHandlerAdapterWelcomePageHandlerMapping: 欢迎页功能支持(模板引擎目录、静态资源目录放index.html页面),项目访问/就默认展示这个页面RequestMappingHandlerMapping:找每个请求由谁处理的映射关系ExceptionHandlerExceptionResolver:默认的异常解析器LocaleResolver:国际化解析器ThemeResolver:主题解析器FlashMapManager:临时数据共享FormattingConversionService: 数据格式化 、类型转化Validator:JSR303 提供的数据校验功能WebBindingInitializer:请求参数的封装与绑定ContentNegotiationManager:内容协商管理器
- 支持 RESTful 的 Filter:
WebMvcAutoConfigurationAdapter配置生效,它是一个WebMvcConfigurer,定义了 MVC 底层组件- 定义好
WebMvcConfigurer:底层组件的默认功能 - 视图解析器:
InternalResourceViewResolver - 视图解析器:
BeanNameViewResolver,视图名(Controller 方法的返回值字符串)就是组件名 - 内容协商解析器:
ContentNegotiatingViewResolver - 请求上下文过滤器:
RequestContextFilter,在任意位置直接获取当前请求 - 静态资源链规则
- 错误详情:
ProblemDetailsExceptionHandler,Spring MVC 内部场景的异常都会被它捕获
- 定义好
@EnableWebMvc 禁用默认行为
@EnableWebMvc往容器中导入了DelegatingWebMvcConfiguration组件,它继承自WebMvcConfigurationSupportWebMvcAutoConfiguration有一个核心的条件注解,@ConditionalOnMissingBean (WebMvcConfigurationSupport.class),当容器中没有WebMvcConfigurationSupport组件时,WebMvcAutoConfiguration才生效@EnableWebMvc导入了WebMvcConfigurationSupport,从而会导致WebMvcAutoConfiguration失效,即会导致 SpringBoot 禁用 MVC 自动配置的所有功能
WebMvcConfigurer 的功能
WebMvcConfigurer 定义并扩展了 Spring MVC 的底层功能,其中的功能列表如下:
| 提供方法 | 核心参数 | 功能 | 默认 |
|---|---|---|---|
| addFormatters | FormatterRegistry | 格式化器:支持属性上 @NumberFormat 和 @DatetimeFormat 的数据类型转换 | GenericConversionService |
| getValidator | 无 | 数据校验:校验 Controller 上使用 @Valid 标注的参数合法性。需要导入 spring-boot-starter-validator | 无 |
| addInterceptors | InterceptorRegistry | 拦截器:拦截收到的所有请求 | 无 |
| configureContentNegotiation | ContentNegotiationConfigurer | 内容协商:支持多种数据格式返回。需要配合支持这种类型的 HttpMessageConverter | 支持 JSON |
| configureMessageConverters | List<HttpMessageConverter<?>> | 消息转换器:标注 @ResponseBody 的返回值会利用 MessageConverter 直接写出去 | 支持 8 种数据类型,包括 byte,string,multipart,resource,json |
| addViewControllers | ViewControllerRegistry | 视图映射:直接将请求路径与物理视图映射。用于无 Java 业务逻辑的直接视图页渲染 | 无 |
| configureViewResolvers | ViewResolverRegistry | 视图解析器:逻辑视图转为物理视图 | ViewResolverComposite |
| addResourceHandlers | ResourceHandlerRegistry | 静态资源处理:静态资源路径映射、缓存控制 | ResourceHandlerRegistry |
| configureDefaultServletHandling | DefaultServletHandlerConfigurer | 默认 Servlet:可以覆盖 Tomcat 的 DefaultServlet。让 DispatcherServlet 拦截 / | 无 |
| configurePathMatch | PathMatchConfigurer | 路径匹配:自定义 URL 路径匹配。可以自动为所有路径加上指定前缀,比如 /api | 无 |
| configureAsyncSupport | AsyncSupportConfigurer | 异步支持 | TaskExecutionAutoConfiguration |
| addCorsMappings | CorsRegistry | 跨域支持 | 无 |
| addArgumentResolvers | List | 参数解析器 | MVC 默认提供 |
| addReturnValueHandlers | List | 返回值解析器 | MVC 默认提供 |
| configureHandlerExceptionResolvers | List | 异常处理器 | 3 个核心类:ExceptionHandlerExceptionResolver,ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver |
| getMessageCodesResolver | 无 | 消息码解析器:国际化使用 | 无 |
最佳实践
SpringBoot 已经默认配置好了 Web 开发场景常用的功能,一般情况下直接使用即可。
三种配置方式
在 SpringBoot Web 开发场景下,有以下三种方式可以配置 SpringBoot MVC。
| 方式 | 用法 | 重点 | 效果 |
|---|---|---|---|
| 全自动 | 直接编写控制器的业务逻辑 | 全部使用 SpringBoot 自动配置的默认效果 | |
| 手自一体 | @Configuration + 配置 WebMvcConfigurer 或者配置 WebMvcRegistrations | 不要标注 @EnableWebMvc 注解 | 保留 SpringBoot 自动配置效果,手动配置部分功能,自定义 MVC 底层组件 |
| 全手动 | @Configuration + 配置 WebMvcConfigurer | 标注 @EnableWebMvc 注解 | 禁用 SpringBoot 自动配置效果,全手动配置 |
两种开发模式
- 前后端分离模式:
@RestController直接响应 JSON 数据 - 前后端不分离模式:
@Controller+Thymeleaf模板引擎
