zoukankan      html  css  js  c++  java
  • 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、这里我们可以实现 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");
        }
    }
    

     下面这种方式也具有相同的作用

    @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

    // 标记这是一个配置类
    @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 这个类看一下

    @Configuration
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
    	private final WebMvcProperties mvcProperties;
    	private final ListableBeanFactory beanFactory;
    	private final WebMvcRegistrations mvcRegistrations;
    	...
    }
    

    发现这个类继承了 DelegatingWebMvcConfiguration ,继续点进去看

    @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) 方法进行查看

    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()方法 

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    	// delegates 就是我们从 IOC 容器中取出来的所有的 WebMvcConfigurer
    	for (WebMvcConfigurer delegate : this.delegates) {
    		// 对每个 WebMvcConfigurer 都执行 addViewControllers 操作
    		delegate.addViewControllers(registry);
    	}
    }
    

    这样,所有的 WebMvcConfigurer 都执行了 addViewControllers 操作(包括我们自定义的和 springboot 默认对 mvc 的配置)

  • 相关阅读:
    通过JavaMail发送(群发)邮件示例(内含附件图片) 代码复制可用
    需要把获取系统的当前时间存入库里 获取时是String类型,库里是Datetime类型 String 转化 Date
    用canvas和原生js写的一个笨鸟先飞的小游戏(暂时只有一个关卡)
    Svg和canvas的区别,伪类选择器有哪些(归类)
    微信web网页动态增减输入框,搜索框,基于jQuery weui、jQuery 实现无限插入数据,动态数据生成,外加高德地图POI和根据坐标获取位置信息的页面
    vue 使用tinymce富文本编辑器
    mamp环境下navicat无法链接本地mysql
    tp5 系统变量输出
    开始项目注意事项
    jQuery weui实现下拉刷新事件
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/14001668.html
Copyright © 2011-2022 走看看