从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

    • SpringBoot教程-尚硅谷

      • SpringBoot 课程介绍
      • Spring 和 SpringBoot
      • HelloWorld
      • 了解自动配置原理
      • 底层注解-@Configuration 详解
      • 底层注解-@Import 导入组件
      • 底层注解-@Conditional 条件装配
      • 原生配置文件引入-@ImportResource
      • 底层注解-配置绑定 @ConfigurationProperties
      • 自动配置原理
      • 自动配置流程
      • Lombok 简化开发
      • DevTools
      • Spring-Initailizr
      • 配置文件-Yaml 用法
      • Web 开发简介
      • web 开发-静态资源规则于定制化
      • 静态资源配置原理
      • Rest 映射及源码解析
      • 请求映射原理
      • 常用参数注解使用
      • MatrixVariable:矩阵变量
      • 各种类型参数解析原理
      • Servlet-API 参数解析原理
      • Model、Map 参数解析原理
      • 自定义对象参数绑定原理
      • 自定义 Converter 原理
      • 数据响应原理
      • 内容协商原理
      • 基于请求参数的内容原理
      • 自定义 MessageConverter 原理
      • Thymeleaf 初体验
      • web 实验-后台管理系统
      • web 实验-抽取公共页面
      • web 实验-遍历数据
      • 源码分析-视图解析器与视图
      • 拦截器-登录检查与静态资源放行
      • 拦截器的执行时机和原理
      • 单文件和多文件上传的使用
      • 文件上传原理
      • 错误处理机制
      • 错误处理-底层组件源码分析
      • 异常处理流程
      • 几种异常处理原理
      • Web 原生对象注入
      • 嵌入式 Servlet 容器
      • 定制化原理
        • 几种定制化方式
        • @EnableWebMvc
        • 总结
      • 数据库场景的自动配置分析和整合测试
      • 自定义方式整合 Druid
      • 通过 starter 整合 Druid
      • 整合 Mybatis
      • 使用注解整合 Mybatis
      • 整合 MybatisPlus 操作数据库
      • MybatisPlus-列表分页展示
      • 整合 Redis
      • 单元测试-Junit5
      • 单元测试-断言机制
      • 单元测试-前置条件
      • 单元测试-嵌套测试
      • 单元测试-参数化测试
      • 指标监控-基本概念
      • 指标监控-配置 EndPoint
      • 指标监控-可视化
      • 原理解析-Profile 功能
      • 配置文件深入
      • 自定义 Starter
      • SpringApplication 初始化过程
      • SpringBoot 完整启动过程
  • Java
  • SpringBoot
  • SpringBoot教程-尚硅谷
2023-08-22
目录

定制化原理

# 470.定制化原理

这一小节主要对 Web 开发,做个总结

# 几种定制化方式

首先,我们的 SpringBoot 自动配置了很多东西,就算没做任何配置,也能运作良好;

自动配置的过程: 引入场景 starter --> 通过 xxxxAutoConfiguration 自动配置 --> 自动导入 xxx 组件 --> 绑定配置 xxxProperties --> 绑定配置文件里的内容

所以,一般要修改什么配置,只需增加一个配置文件即可。除此之外,还有其他方式:

  • 编写自定义的配置类(通过 @Configuration 注解),然后注入 Bean 进行组件注册,例如之前自定义过异常解析器 CustomerHandlerExceptionResolver
  • 如果是 web 项目,可以通过实现 WebMvcConfigurer 接口,完成定制化
  • 定制化器 xxxxCustomizer,后续我们会看到很多这样的设计

在文档中也有这样的描述:

4.7.1. The “Spring Web MVC Framework”

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

‍

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

‍

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc

大意:

  1. 如果想要自定义配置,只需写个配置类,实现 WebMvcConfigurer 接口(但是不实现 @EnableWebMvc)
  2. 如果想要修改一些比较底层的配置,但是不改动 SpringMVC 的默认配置,例如增加 RequestMappingHandlerMapping,RequestMappingHandlerAdapter,也是可以的,只需注入一个组件 WebMvcRegistrations 即可
  3. 如果想要完全接管 SpringMVC,可以写个配置类,然后使用注解 @EnableWebMvc

第二种方式示例:

@Bean
public WebMvcRegistrations webMvcRegistrations(){
   return new WebMvcRegistrations(){
	   @Override
	   public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
		   return null;
	   }
   };
}
1
2
3
4
5
6
7
8
9

注意,第二种方式是很底层的,如果不是很了解 HandlerMapping,不推荐使用。接下来讲讲 @EnableWebMvc

# @EnableWebMvc

在一个配置类使用该注解后,将全面接管 SpringMVC 的默认行为;想之前的静态资源,视图解析器,内容协商起,Converter,欢迎页.....全部都会失效,因此要慎用!接下来我们讲讲原理。

为什么会失效呢?我们可以看看 @EnableWebMvc 的源码,其有引入一个类 DelegatingWebMvcConfiguration:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
1
2
3
4
5
6

‍ DelegatingWebMvcConfiguration,继承自 WebMvcConfigurationSupport:

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
1
2

‍ 而自动配置类 WebMvcAutoConfiguration,要生效有一个条件:容器中没有 WebMvcConfigurationSupport,因此我们使用了 @EnableWebMvc 注解后,自动配置就失效了

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
public class WebMvcAutoConfiguration {
1
2

因此,之前的配置都需要我们手工配置,例如设置静态资源:

@EnableWebMvc
@Configuration
public class AdminWebConfig implements WebMvcConfigurer{

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
       /**
    	* 访问  /aa/** 所有请求都去 classpath:/static/ 下面进行匹配
    	*/
       registry.addResourceHandler("/aa/**")
    		   .addResourceLocations("classpath:/static/");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

‍ DelegatingWebMvcConfiguration,也定义一些默认行为,只保证 SpringMVC 最基本功能的使用。

除此之外,它会获取到所有的 Configurer,然后配置:

//................
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
	if (!CollectionUtils.isEmpty(configurers)) {
		this.configurers.addWebMvcConfigurers(configurers);
	}
}


@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	this.configurers.configureContentNegotiation(configurer);
}


@Override
protected void configureAsyncSupport(AsyncSupportConfigurer configurer) {
	this.configurers.configureAsyncSupport(configurer);
}


@Override
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
	this.configurers.configureDefaultServletHandling(configurer);
}


@Override
protected void addFormatters(FormatterRegistry registry) {
	this.configurers.addFormatters(registry);
}
//................
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

‍ 还记得第一种配置方式吗?写个配置类,实现 WebMvcConfigurer 接口。因此 DelegatingWebMvcConfiguration 的作用,就是将系统中所有的 WebMvcConfigurer,然后循环遍历,使其生效

# 总结

一般来说,我们都是改配置文件,最多实现个 WebMvcConfigurer 接口来完成配置,很少完全接管 SpringMVC 的配置。

通过 web 开发的源码分析,相信大家对于 SpringBoot 底层也有了一定的了解,后续学习数据访问、单元测试等,都是事半功倍 ‍ 已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo8 ,读者可以通过切换分支来查看本文的示例代码

上次更新: 2025/5/5 17:15:09
嵌入式 Servlet 容器
数据库场景的自动配置分析和整合测试

← 嵌入式 Servlet 容器 数据库场景的自动配置分析和整合测试→

最近更新
01
吐槽一下《僵尸校园》
05-15
02
2025 年 4 月记
04-30
03
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式