1. 配置介绍
SpringBoot使用一个全局的配置文件 核心配置文件,配置文件名在约定的情况下 名字是固定的; 配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;
∙application.properties #最后加载,优先级最高
∙application.yml #最常用,最先加载,优先级最低
∙application.yaml
YAML(YAML Ain't Markup Language)
YAML A Markup Language:是一个标记语言
YAML isn't Markup Language:不是一个标记语言;
2. 配置格式
两种配置文件的格式 在springboot框架中,resource文件夹里可以存放配置的文件有两种:properties和yml。
2.1 application.properties的用法:扁平的k/v格式。
server.port=8081
server.servlet.context‐path=/test
2.2 application.yml的用法:树型结构。
server:
port: 8088
servlet:
context‐path: /test
建议使用后者,因为它的可读性更强。 可以看到要转换成YML我们只需把properies里按. 去拆分即可。
3. yml基本语法
k:(空格)v:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;
只要是左对齐的一列数据,都是同一个层级的 属性和值也是大小写敏感;
如果有特殊字符% & 记得用单引号(‘)包起来
4. 配置文件的加载顺序
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
加载顺序从上到下,由低到高
如果同时存在不同后缀的文件按照这个顺序加载主配置文件;互补配置;
5. 外部约定配置文件加载顺序
低↓
1. classpath根目录下
2. classpath根config/
3. 项目根目录
如果当前项目是继承/耦合 关系maven项目的话,项目根目录=父maven项目的根目录
4. 项目根目录/config
5. 直接子目录/config
1 java ‐jar configuration_file‐0.0.1‐SNAPSHOT.jar ‐‐spring.config.location=D:\config/
高↓
优先级由底到高,高优先级的配置会覆盖低优先级的配置;互补配置
官网:
1 optional:classpath:/
2 optional:classpath:/config/
3 optional:file:./
4 optional:file:./config/*/
5 optional:file:./config/
6 optional:classpath:custom‐config/ ‐‐spring.config.location
7 optional:file:./custom‐config/ ‐‐spring.config.location
6. Profile文件的加载
Profile的意思是配置,对于应用程序来说,不同的环境需要不同的配置。 SpringBoot框架提供了多profile的管理功能,我们可以使用profile功能来区分不同环境的配置。
1. 多Profile文件,Spring官方给出的语法规则是application-{profile}.properties(.yaml/.yml)。
2.如果需要创建自定义的的properties文件时,可以用application-xxx.properties的命名方式
如下图所示
配置环境:spring.profiles.active=prod
开发环境
生产环境
. 若我们需要在两种环境下进行切换,只需要在application.yml修改spring.profiles.active=prod值
1 先按照位置来读取优先级, 在同一位置下profile优先级最高, 如果没有指定profile, 先yml‐‐yaml‐‐properties
7. 所有配置文件顺序
优先级从低到高
1. 打包在jar中配置文件
2. 打包在jar中profile
3. 打包的jar之外的配置文件
4. 打包的jar之外的profile
1 java ‐jar configuration_file‐0.0.1‐SNAPSHOT.jar
2
3 jar包之外的配置文件 yml‐‐>yaml‐‐>properties
4 optional:classpath:/config/ yml‐‐>yaml‐‐>properties
5 optional:classpath:/ yml‐‐>yaml‐‐>properties
6
7
1 java ‐jar configuration_file‐0.0.1‐SNAPSHOT.jar ‐‐spring.profiles.active=dev
2
3 jar包之外的配置文件 profile‐dev ‐‐> yml‐‐>yaml‐‐>properties
4 optional:classpath:/config/ profile‐dev ‐‐> yml‐‐>yaml‐‐>properties
5 optional:classpath:/ profile‐dev ‐‐> yml‐‐>yaml‐‐>properties
6
7
1 java ‐jar configuration_file‐0.0.1‐SNAPSHOT.jar ‐‐spring.config.location=D:/application.properties
2
3 优先级最大, 因为指定了具体的配置文件。 所以不会和默认的约定配置文件进行互补
8. 配置文件值注入
字面量:普通的值(数字,字符串,布尔)
1. k: v:字面直接来写;
2. 字符串默认不用加上单引号或者双引号; "":双引号;
3. 不会转义字符串里面的特殊字符;
4. 特殊字符会作为本身想表示的意思 name: "zhangsan \n lisi":输出;zhangsan 换行 lisi '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据 name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
对象、Map(属性和值)(键值对):
#对象还是k: v的方式
1 friends:
2 lastName: zhangsan
3 age: 20
#行内写法:
1 friends: {lastName: zhangsan,age: 18}
数组:
#用- 值表示数组中的一个元素
1 pets:
2 ‐ cat
3 ‐ dog
4 ‐ pig
#行内写法
1 pets: [cat,dog,pig]
@Value获取值和@ConfigurationProperties获取值比较
使用场景
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value; 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
使用@PropertySource(value = {"classpath:person.properties"}) 加载指定的配置文件;
9. Spring Boot的配置和自动配置原理
1. @SpringBootApplication
Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot 需要运行这个类的main方法来启动SpringBoot应用;
1 @Target(ElementType.TYPE) #设置当前注解可以标记在哪
2 @Retention(RetentionPolicy.RUNTIME) #当注解标注的类编译以什么方式保留
#RetentionPolicy.RUNTIME 会被jvm加载
3 @Documented #java doc 会生成注解信息
4 @Inherited #是否会被继承
5 @SpringBootConfiguration #标注在某个类上,表示这是一个Spring Boot的配置类;内部
使用了@Configuration
6 @EnableAutoConfiguration #开启自动配置功能 告诉SpringBoot开启自动配置,会帮我们自动去加载
自动配置类
7 @ComponentScan(excludeFilters = { #扫描包
8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
2. @AutoConfigurationPackage
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage #将当前配置类所在包保存在BasePackages的Bean中。供Spring内部使用
@Import({AutoConfigurationImportSelector.class}) #关键点
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
1. @AutoConfigurationPackage
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class}) #保存扫描路径,提供给spring‐data‐jpa需要扫描@Entity
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
2. @Import(EnableAutoConfigurationImportSelector.class)
EnableAutoConfigurationImportSelector实现了DeferredImportSelector,内部在解析@Import时会去调用getAutoConfigurationEntry()方法,这个方法会去扫描具有META-INF/spring.factories的jar包
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
spring.factories文件是Key=Value形式,多个Value时使用,隔开,该文件中定义了关于初始化,监听器等信息,而真正使自动配置生效的key是
org.springframework.boot.autoconfigure.EnableAutoConfiguration :上图
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
所有的自动配置类
Auto-configuration Classes (spring.io)
3. 每一个自动配置类进行自动配置功能
@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在 SpringApplication.run(...)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的 class,然后将所有自动配置类加载到Spring容器中
10. 以HttpEncodingAutoConfiguration为例解释自动配置原理
1. 源码
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled",
matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
@Configuration(proxyBeanMethods = false)
标记了@Configuration Spring底层会给配置创建cglib动态代理。 作用:就是防止每次调用本类的Bean方法而重新创建对 象,Bean是默认单例的,优先从ioc容器中获取bean对象
@EnableConfigurationProperties(ServerProperties.class)
启用可以在配置类设置的属性对应的类
@ConfigurationProperties(
prefix = "server",
ignoreUnknownFields = true
)
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;
@NestedConfigurationProperty
private final Compression compression;
@NestedConfigurationProperty
private final Http2 http2;
private final ServerProperties.Servlet servlet;
private final ServerProperties.Reactive reactive;
private final ServerProperties.Tomcat tomcat;
private final ServerProperties.Jetty jetty;
private final ServerProperties.Netty netty;
private final ServerProperties.Undertow undertow;
@Conditional派生注解
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
过滤器
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean
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;
}
this.properties.getCharset().name properties=properties.getServlet().getEncoding()
上面类似于从配置文件读取 server.servelt.encoding.charset这个配置的值然后设置到filter中,内嵌的tomcat货拿到这个bean,最后实现自动配置