SpringBoot基础学习之SpringBoot配置(下篇)

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个SpringBoot基础学习系列用来记录我学习SpringBoot框架基础知识的全过程 (这个系列是参照B站狂神的SpringBoot最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将会以一天一更的速度更新这个系列,还没有学习SpringBoot的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。
最后,希望能够和大家一同进步吧!加油吧!少年们!

由于SpringBoot配置内容比较多,所以这里分成了上下两篇,上篇博客链接: https://blog.csdn.net/weixin_45301250/article/details/120660970
废话不多说,让我们开始今天的学习内容吧,由于今天我们来到了SpringBoot基础学习的第四站: SpringBoot配置下篇

4.SpringBoot配置

4.3 不同位置配置文件优先级比较

4.3.1 配置yml文件位置和信息

1.基本项目结构

1-1 四个位置都存放文件

四个位置分别为: ./config/ 下、./下、 classpath:/ 下、classpath:./config/下

在这里插入图片描述

1-2 删除./config/ 下文件

此时还剩下: ./下、 classpath:/ 下、classpath:./config/下

在这里插入图片描述

1-3 删除./config/ 和./下文件

此时还剩下: classpath:/ 下、classpath:./config/下

在这里插入图片描述

2.编写yml配置文件信息

2-1 存放于classpath:/ 下
# 存放位置:classpath:/ 
server:
  port: 8080   
2-2 存放于./config/下
# 存放位置:./config/ 
server:
  port: 8081
2-3 存放于classpath:./config/下
# 存放位置:classpath:./config/
server:
  port: 8082
2-4 存放于./ 下
# 存放位置:./ 
server:
  port: 8083

3.测试结果

3-1 四个位置都存放文件

在这里插入图片描述

测试结果 Tomcat服务器的端口号为8081,因此 ./config/ 下的配置文件优先级最高!

3-2 删除./config/下文件

此时还剩下: ./下、 classpath:/ 下、classpath:./config/下

在这里插入图片描述

结果 Tomcat服务器的端口号为8083,因此 ./ 下的配置文件优先级第二高!

3-3 删除./config/和./下文件

此时还剩下: classpath:/ 下、classpath:./config/下

在这里插入图片描述

结果 Tomcat服务器的端口号为8082,因此 classpath:./config/ 下的配置文件优先级倒数第二高,而优先级最低的是 classpath:/ 下的配置文件

4. 使用总结

优先级顺序为 ./config/ > ./ > classpath:./config/ > classpath:/

4.3.2 使用properties文件配置多套环境

1.项目结构

在这里插入图片描述

2.编写配置文件

2-1 默认环境配置文件
# 默认使用的端口号
server.port=8080
2-2 开发环境配置文件
#开发环境端口号
server.port=8081
2-3 测试环境配置文件
# 测试环境端口号
server.port=8082
2-4 指定配置环境
# SpringBoot的多环境配置:可以选择激活指定的配置文件
# test:指定测试环境-8082
spring.profiles.active=test

3.测试结果

1-1 使用默认环境配置

在这里插入图片描述

1-2 指定配置环境

在这里插入图片描述

4.3.3 使用yaml文件配置多套环境

1.项目结构

在这里插入图片描述

2.编写配置文件

2-1 使用默认环境
# 默认环境
server:
  port: 8080
# 分隔符,用来区分多道环境
---
# 开发环境
server:
  port: 8081
# profiles表示文件名称
spring:
  profiles: dev
---
# 测试环境
server:
  port: 8082
spring:
  profiles: test
2-2 使用指定环境
# 默认环境
server:
  port: 8080
# active: dev表示指定默认环境为开发环境
spring:
  profiles:
    active: dev  
# 分隔符,用来区分多道环境
---
# 开发环境
server:
  port: 8081
# profiles表示文件名称
spring:
  profiles: dev
---
# 测试环境
server:
  port: 8082
spring:
  profiles: test

3.测试结果

3-1 使用默认环境

在这里插入图片描述

3-2 使用指定环境

在这里插入图片描述

4.使用总结

  • 在配置多道环境时,yml可以配置多个环境在一个文件内,十分简便,推荐使用!
  • 而使用properties进行配置,则需要分别配置多个环境,比较麻烦,根据实际开发环境使用

4.4 自动装配原理再解析

4.4.1 HttpEncodingAutoConfiguration解析

1.文件位置

文件路径为 :External Library / springframework-boot: spring-boot-autoconfiguration / spring-boot-autoconfiguration / META-INF / spring.factories

  • 在AutoConfiguration中找到HttpEncodingAutoConfiguration类

在这里插入图片描述

2.源码分析

2-1 HttpEncodingAutoConfiguration类初步分析

我们发现其 @EnableConfigurationProperties 注解中有一个 ServerProperties 类,那么这个对象的作用到底是什么呢?让我一同看一下它的源码吧

//表示这是一个配置类
@Configuration(proxyBeanMethods = false)
//能够自动配置属性:ServerProperties类
@EnableConfigurationProperties({ServerProperties.class})
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(prefix = "server.servlet.encoding",value = {"enabled"}, matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
  ......
}
2-2 查看ServerProperties类源码

原来这个 ServerProperties 类的作用就是配置常用的服务器参数:比如port端口号、addres路径和SSL安全传输协议等

//使用@ConfigurationProperties注解:从配置文件获取指定值和bean的属性进行绑定
@ConfigurationProperties(prefix = "server",ignoreUnknownFields = true)
//prefix = "server":将配置文件中的server对象下的所有属性一一对应
public class ServerProperties {
    private Integer port; //端口号
    private InetAddress address; //路径设置
    @NestedConfigurationProperty 
    private final ErrorProperties error = new ErrorProperties();
    private ServerProperties.ForwardHeadersStrategy forwardHeadersStrategy;
    private String serverHeader; //服务器响应头
    private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L);
    private Shutdown shutdown; //关机
    @NestedConfigurationProperty 
    private Ssl ssl; //ssl(安全套接字协议),为网络通信提供安全及数据完整性的安全协议
    @NestedConfigurationProperty
    private final Compression compression; //压缩属性
    @NestedConfigurationProperty
    private final Http2 http2;
    private final ServerProperties.Servlet servlet;
    private final ServerProperties.Tomcat tomcat;
    private final ServerProperties.Jetty jetty;
    private final ServerProperties.Netty netty;
    private final ServerProperties.Undertow undertow;
    ......
}
2-3 继续分析HttpEncodingAutoConfiguration类
//表示这是一个配置类
@Configuration(proxyBeanMethods = false)
//能够自动配置属性:Encoding类
@EnableConfigurationProperties({ServerProperties.class})
//下面三个都是Spring的底层注解:根据不同的条件,来判断当前配置或者类是否生效
//判断应用类型是否是Web应用,如果是生效,否则失效
@ConditionalOnWebApplication(type = Type.SERVLET)
//判断类是否存在字符集过滤器类,如果是生效,否则失效
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断是否存在server.servlet.encoding的配置,如果不存在设置为默认值
@ConditionalOnProperty(prefix = "server.servlet.encoding",value = {"enabled"}, matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
    //properties配置类
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }
    
    @Bean//添加Bean到容器中
    @ConditionalOnMissingBean //判断系统中有没有指定的Bean
    //有则执行下面的方法,没有就不生效
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();//字符集过滤器
        filter.setEncoding(this.properties.getCharset().name());
   filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));//请求过滤
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));//响应
        return filter;
    }
   ......
}

3.在配置文件中测试properties类封装的属性

3-1 编写application.yml配置文件
# 配置文件到底能写什么?其实与spring。factories有很大的联系
spring:
  rsocket:
    server:
      # port、address和ssl之所以能够被使用,是因为server类中定义了这些属性
      port:
      address:
      ssl:
      # name显然不能使用,因为server类根本就没有这个属性,这是我们自定义的
      name:        

server类的相关属性

在这里插入图片描述

3-2 测试结论

在配置文件中能配置的东西,都存在一个固有的规律:

  • 都会有大量的 xxxAutoConfiguration和xxxProperties
  • xxxAutoConfiguration :自动配置类中默认装配了一些类和属性,并且有默认值
  • xxxProperties :绑定配置文件,可以使用自定义的配置属性

4.@Conditonnal派生注解的使用

在初步了解自动装配的原理后,我们会发现一个细节问题: 自动配置类必须在一定的条件下才能生效

@Conditional派生注解作用 (Spring注解原生的@Conditional作用):

必须是@Conditional指定的条件成立,才给容器中添加组件,配置时需要配里面的所有内容才生效

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalJava 系统的Java版本是否符合要求
@ConditionnalBean 容器中存在指定的Bean
@ConditionalMissingBean 容器中不存在指定Bean
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

4.4.2 WebMvcAutoConfiguration类解析

1.文件位置

在这里插入图片描述

2.查看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})
//WebMvc自动配置类
public class WebMvcAutoConfiguration { 
      ...... 
@Configuration(proxyBeanMethods = false)
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})  
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
    @Order(0)
    //WebMvc自动配置适配器      
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    ......
   }
    ......
}    

3.查看WebMvcAutoConfigurationAdapter类源码

@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 { 
      .....
@Configuration(proxyBeanMethods = false)
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    //使用@EnableConfigurationProperties注解:自动配置属性 ,绑定WebMvcProperties类     
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
        private final WebMvcProperties mvcProperties;
        private final ListableBeanFactory beanFactory;
        private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
        private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;
        private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
        final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
   }
    ......
}    

4.查看WebMvcProperties类源码

//使用@ConfigurationProperties注解:与配置文件进行绑定,获取指定类的属性
@ConfigurationProperties(prefix = "spring.mvc")
//prefix = "spring.mvc":将配置文件中的mvc对象的所有属性一一对应
public class WebMvcProperties {
    private org.springframework.validation.DefaultMessageCodesResolver.Format messageCodesResolverFormat;
    private Locale locale;
    private WebMvcProperties.LocaleResolver localeResolver;
    private final WebMvcProperties.Format format;
    private boolean dispatchTraceRequest;
    private boolean dispatchOptionsRequest;
    private boolean ignoreDefaultModelOnRedirect;
    private boolean publishRequestHandledEvents;
    private boolean throwExceptionIfNoHandlerFound;
    private boolean logRequestDetails;
    private boolean logResolvedException;
    private String staticPathPattern;
    private final WebMvcProperties.Async async;
    private final WebMvcProperties.Servlet servlet;
    private final WebMvcProperties.View view;
    private final WebMvcProperties.Contentnegotiation contentnegotiation;
    private final WebMvcProperties.Pathmatch pathmatch;
	......
}

5.使用总结

简单来说就是,根据当前的不同条件判断,决定这个配置类是否生效!

  • 一旦这个配置类生效,这个配置类就会给容器添加各种组件,这些组件的属性是从对应的Properties类中获取的,这些类里面每一个属性又是和配置文件绑定的

  • 所有配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件配置什么就可以参照某个功能对应的这个属性类

4.4.3 自动装配原理核心

  • SpringBoot启动会加载大量的自动配置类

  • 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中

  • 我们再来看这个自动配置类中到底装配了哪些组件 (只要我们要用的组件在其中,我们就不需要手动配置了)

  • 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性 (我们只需要在配置文件中指定这些属性的值即可)

  • 核心注解

    xxxAutoConfiguration 自动装配类,给容器中添加组件

    xxxProperties 封装配置文件中相关属性

    Conditinnalxxx 判定是否满足指定的属性

4.4.4 配置文件中设置debug测试

1.编写application.yml配置文件

# 设置debug值为true,查看哪些自动配置类生效,哪些没有
debug: true

2.测试结果

debug后的信息可以分为四类来查看

2-1 debug信息的第一类
  • Postive matches :自动配置类启用并且生效了

在这里插入图片描述

2-2 debug信息的第二类
  • Negative matches :自动配置类中没有匹配成功的

在这里插入图片描述

2-3 debug信息的第三类
  • Exclusion :None表示没有表达式

在这里插入图片描述

2-4 debug信息的第四类
  • Unconditional classes :没有条件的类

在这里插入图片描述

4.4.5 配置文件中设置其他属性

1.编写application.yml配置文件

# activemq:消息队列
spring:
  # 提前分析:应该是有一个activemqProperties配置类
  # 其可能还使用了@configuratioProperties注解,来封装指定配置文件(spring.activemq)
  activemq: 
    non-blocking-redelivery:

2.查看ActiveMQProperties类源码

  • 查看源码后发现,与我们所猜想的结果基本一致
//使用@ConfigurationProperties注解,封装配置文件中类的相关属性
@ConfigurationProperties(prefix = "spring.activemq")
public class ActiveMQProperties {
    private String brokerUrl;
    private boolean inMemory = true;
    private String user;
    private String password;
    private Duration closeTimeout = Duration.ofSeconds(15L);
    private boolean nonBlockingRedelivery = false;
    private Duration sendTimeout = Duration.ofMillis(0L);
    @NestedConfigurationProperty
    private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties();
    private final ActiveMQProperties.Packages packages = new ActiveMQProperties.Packages();
    ......
}

3.查看ActiveMQAutoConfiguration类位置

在这里插入图片描述

4.查看ActiveMQAutoConfiguration类源码

@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore({JmsAutoConfiguration.class})
@AutoConfigureAfter({JndiConnectionFactoryAutoConfiguration.class})
@ConditionalOnClass({ConnectionFactory.class, ActiveMQConnectionFactory.class})
@ConditionalOnMissingBean({ConnectionFactory.class})
//使用@EnableConfigurationProperties,能够自动配置属性:通过ActiveMQProperties类
@EnableConfigurationProperties({ActiveMQProperties.class, JmsProperties.class})
@Import({ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class})
public class ActiveMQAutoConfiguration {
    public ActiveMQAutoConfiguration() {
    }
}

点击 @EnableConfigurationProperties 注解中的 ActiveMQProperties.class ,就又回到我们刚开始看到的 ActiveMQProperties 类了

//使用@ConfigurationProperties注解,封装配置文件中类的相关属性
@ConfigurationProperties(prefix = "spring.activemq")
public class ActiveMQProperties {
    private String brokerUrl;
    private boolean inMemory = true;
    private String user;
    private String password;
    private Duration closeTimeout = Duration.ofSeconds(15L);
    private boolean nonBlockingRedelivery = false;
    private Duration sendTimeout = Duration.ofMillis(0L);
    @NestedConfigurationProperty
    private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties();
    private final ActiveMQProperties.Packages packages = new ActiveMQProperties.Packages();
    ......
}

好了,今天的有关 SpringBoot配置下篇 的学习就到此结束啦,欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连,我们下期见,拜拜啦!


参考视频链接 :https://www.bilibili.com/video/BV1PE411i7CV(【狂神说Java】SpringBoot最新教程IDEA版通俗易懂)


版权声明:本文为weixin_45301250原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。