Springboot 对 Springmvc 的扩展
我们查看 Springboot 官方文档,里面有关于对 Springmvc 的扩展介绍
后面这段话的意思是: 如果你想保留 Spring Boot MVC 的功能,并且你希望添加其它的 MVC 配置(拦截器、格式化器、视图控制器、和其它的功能),你可以添加自己的 @Configuration 配置类,并且让该配置类实现 WebMvcConfigurer 接口,但是不要在该配置类上添加 @EnableWebMvc 注解,如果你想要 RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExeceptionHandlerExceptionResolver 的定制实例,可以声明一个 WebMvcRegistrationsAdapter 实例来提供上面这些组件.
如果你想全面接管 Spring MVC ,那么你可以添加带有 @EnableWebMvc、@Configuration 注解的配置类
关于 @EnableWebMvc 注解的作用,可以参考一下这篇博客 https://www.cnblogs.com/xiaomaomao/p/13998924.html
按照上面的提示,创建一个配置类并实现 WebMvcConfigurer 接口(当然也可以继承 WebMvcConfigurerAdapter 这个抽象类,其实是同一个意思,因为WebMvcConfigurerAdapter 也是 WebMvcConfigurer 的实现类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * 1、这里我们可以实现 WebMvcConfigurer 接口,并重写其中的方法来完成 springmvc 的扩展功能 * 2、也可以继承 WebMvcConfigurerAdapter 抽象类,其实 WebMvcConfigurerAdapter 也是实现了 * WebMvcConfigurer 接口 */ @Configuration public class MyWebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { // 浏览器访问 localhost:8080/ 时,会跳转到视图 resources/templates/success.html 页面 registry.addViewController( "/xiaomao" ).setViewName( "xiaomao/success" ); // 浏览器访问 localhost:8080/xiaomaomao 时,会跳转到视图 resources/templates/success.html 页面 registry.addViewController( "/xiaomaomao" ).setViewName( "xiaomao/success" ); } } |
下面这种方式也具有相同的作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Bean public WebMvcConfigurerAdapter webMvcConfigurerAdapter() { WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() { @Override public void addViewControllers(ViewControllerRegistry registry) { // 浏览器访问 localhost:8080/ 时,会跳转到视图 resources/templates/success.html 页面 registry.addViewController( "/" ).setViewName( "xiaomao/login" ); // 浏览器访问 localhost:8080/xiaomaomao 时,会跳转到视图 resources/templates/success.html 页面 registry.addViewController( "/xiaomao" ).setViewName( "xiaomao/login" ); } }; return adapter; } |
原理:
我们都知道 springboot 对 springmvc 的自动配置相关信息都在 WebMvcConfiguration 这个类里面,点进去这个类可以看到里面有一个静态内部类 WebMvcAutoConfigurationAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // 标记这是一个配置类 @Configuration // 如果当前是 web 应用 @ConditionalOnWebApplication // 如果存在 Servlet、DispatcherServlet、WebMvcConfigurerAdapter 这些类 @ConditionalOnClass ({ Servlet. class , DispatcherServlet. class ,WebMvcConfigurerAdapter. class }) // 如果应用中不存在 WebMvcConfigurationSupport 这个类 @ConditionalOnMissingBean (WebMvcConfigurationSupport. class ) // 自动配置顺序 @AutoConfigureOrder (Ordered.HIGHEST_PRECEDENCE + 10 ) @AutoConfigureAfter ({ DispatcherServletAutoConfiguration. class ,ValidationAutoConfiguration. class }) // springboot 对于 springmvc 的自动配置都在这个类里面 public class WebMvcAutoConfiguration { ... @Configuration @Import (EnableWebMvcConfiguration. class ) @EnableConfigurationProperties ({ WebMvcProperties. class , ResourceProperties. class }) // WebMvcAutoConfigurationAdapter 是 WebMvcAutoConfiguration 的静态内部类 // 它继承了 WebMvcConfigurerAdapter 这个抽象类,看到这个类是不是有点熟悉,我们对 springmvc 进行扩展的 // 时候也是继承的这个类 public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { ... } } |
那么 WebMvcAutoConfigurationAdapter 这个配置类起作用的应该是 @Import(EnableWebMvcConfiguration.class),点进去 EnableWebMvcConfiguration 这个类看一下
1 2 3 4 5 6 7 | @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final WebMvcRegistrations mvcRegistrations; ... } |
发现这个类继承了 DelegatingWebMvcConfiguration ,继续点进去看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { // WebMvc 配置综合类 private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); // 方法上使用 @Atuowired 注解,如果该方法有参数,那么参数会从 IOC 容器中去取 @Autowired (required = false ) // 那么容器中所有的 WebMvcConfigurer 都会赋值给 configurers 这个参数 public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { // 调用 WebMvcConfigurerComposite 的 addWebMvcConfigurers() 方法 this .configurers.addWebMvcConfigurers(configurers); } } |
点进去 addWebMvcConfigurers(List<WebMvcConfigurer configurers) 方法进行查看
1 2 3 4 5 6 7 8 9 10 11 | class WebMvcConfigurerComposite implements WebMvcConfigurer { private final List<WebMvcConfigurer> delegates = new ArrayList<WebMvcConfigurer>(); public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { // 将 IOC 容器中所有的 WebMvcConfigurer 都赋值给了 delegates 这个 List 集合 this .delegates.addAll(configurers); } } } |
我们可以在 DelegatingWebMvcConfiguration 类中去寻找一个我们刚才设置的 addViewControllers() 当做参考,发现它调用了 WebMvcConfigurerComposite 的addViewControllers()方法
1 2 3 4 5 6 7 8 | @Override public void addViewControllers(ViewControllerRegistry registry) { // delegates 就是我们从 IOC 容器中取出来的所有的 WebMvcConfigurer for (WebMvcConfigurer delegate : this .delegates) { // 对每个 WebMvcConfigurer 都执行 addViewControllers 操作 delegate.addViewControllers(registry); } } |
这样,所有的 WebMvcConfigurer 都执行了 addViewControllers 操作(包括我们自定义的和 springboot 默认对 mvc 的配置)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?