SpringBoot-SpringMVC自动配置(八)

1、Spring Boot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。

SpringBoot对SpringMVC的默认配置的源码目录
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

2、自动配置在Spring的默认值之上添加了以下功能:

  • 视图解析器: 包含ContentNegotiatingViewResolverBeanNameViewResolver
  • 静态资源文件夹路径:支持服务静态资源,包括对WebJars的支持(官方文档中有介绍)。
  • 转换器,格式化器:自动注册ConverterGenericConverterFormatterbeans。
  • SpringMVC用来转换Http请求和响应的(User---Json): 支持HttpMessageConverters官方文档中有介绍)。
  • 定义错误代码生成规则 :自动注册MessageCodesResolver官方文档中有介绍)。
  • 静态首页访问:静态index.html支持。
  • 网站图标:定制Favicon支持(官方文档中有介绍
  • 自动使用ConfigurableWebBindingInitializerbean(官方文档中有介绍)。

如果您想保留 Spring Boot MVC 的功能,并且需要添加其他 MVC 配置(拦截器,格式化程序和视图控制器等),可以添加自己的 WebMvcConfigurer 类型的 @Configuration 类,但不能@EnableWebMvc 注解。如果您想自定义 RequestMappingHandlerMappingRequestMappingHandlerAdapter 或者 ExceptionHandlerExceptionResolver 实例,可以声明一个 WebMvcRegistrationsAdapter 实例来提供这些组件。

如果您想全面接管 Spring MVC,可以添加自定义注解了 @EnableWebMvc 的 @Configuration 配置类。

逐一介绍上面的SpringBoot默认配置的功能

1、视图解析器

视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?)

  • 自动配置了ViewResolver
  • ContentNegotiatingViewResolver:组合所有的视图解析器的;


    image.png

视图解析器来源


image.png

所以我们可以自己给容器中添加一个视图解析器;自动的将其组合进来

@Component
public class MyViewResolver implements ViewResolver {

    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {
        return null;
    }
}

image.png

2、转换器,格式化器

  • Converter:转换器; public String hello(User user):类型转换使用Converter(表单数据转为user)
  • Formatter: 格式化器; 2017.12.17===Date;
        @Bean
        //在配置文件中配置日期格式化的规则
        @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")
        public Formatter<Date> dateFormatter() {
            return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
        }

自己添加的格式化器转换器,我们只需要放在容器中即可

3、HttpMessageConverters

  • HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User---Json;
  • HttpMessageConverters 是从容器中确定;获取所有的HttpMessageConverter;

自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)

4、MessageCodesResolver

我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)

5、扩展SpirngMVC配置

例:以前的配置文件中的配置,访问hello请求,重定向到success页面

<mvc:view-controller path="/hello" view-name="success"/>

现在,编写一个配置类(@Configuration),是WebMvcConfigurer类型;不能标注@EnableWebMvc

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("success");
    }
}

访问:http://localhost:8080/hi

原理:

我们知道WebMvcAutoConfiguration是SpringMVC的自动配置类
下面这个类是WebMvcAutoConfiguration中的一个内部类

image.png

看一下@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})中的这个类,
这个类依旧是WebMvcAutoConfiguration中的一个内部类


image.png

重点看一下这个类继承的父类DelegatingWebMvcConfiguration

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

    public DelegatingWebMvcConfiguration() {
    }

    //自动注入,从容器中获取所有的WebMvcConfigurer
    @Autowired(
        required = false
    )
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }

    }

    ......

    /**
     * 查看其中一个方法
      * this.configurers:也是WebMvcConfigurer接口的一个实现类
      * 看一下调用的configureViewResolvers方法 ↓
      */
    protected void configureViewResolvers(ViewResolverRegistry registry) {
        this.configurers.configureViewResolvers(registry);
    }

    public void configureViewResolvers(ViewResolverRegistry registry) {
        Iterator var2 = this.delegates.iterator();

        while(var2.hasNext()) {
            WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
            //将所有的WebMvcConfigurer相关配置都来一起调用;  
            delegate.configureViewResolvers(registry);
        }

    }

容器中所有的WebMvcConfigurer都会一起起作用;

我们的配置类也会被调用;

效果:SpringMVC的自动配置和我们的扩展配置都会起作用;


image.png

6、全面接管SpringMVC

SpringBoot对SpringMVC的自动配置不需要了,所有配置都是由我们自己来配置;所有的SpringMVC的自动配置都会失效了
我们只需要在配置类中添加@EnableWebMvc即可;
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer

image.png

原理:

为什么@EnableWebMvc自动配置就失效了;
我们看一下EnableWebMvc注解类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

重点在于@Import({DelegatingWebMvcConfiguration.class})

DelegatingWebMvcConfiguration是WebMvcConfigurationSupport的子类

我们再来看一下springmvc的自动配置类WebMvcAutoConfiguration

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})

//重点是这个注解,只有当容器中没有这个类型组件的时候该配置类才会生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})

@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration 

@EnableWebMvc将WebMvcConfigurationSupport组件导入进来;导致@ConditionalOnMissingBean这个注解判断失败就不会再加载自动配置 了;

7、如何修改SpringBoot的默认配置

SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;

  • 在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置
  • 在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容