前言 :
小伙伴们,大家好,我是狂奔の蜗牛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版通俗易懂)