文章目录
前言
Spring Boot使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。但是如果有些配置不符合我们的要求怎么办呢,这就需要了解Spring Boot的配置文件了。
正文
默认配置文件
SpringBoot使用一个全局的配置文件,配置文件支持properties和yml两种类型的配置,配置文件名是固定的application.properties/application.yml
,Sping Boot的全局配置文件的作用是对一些默认配置的配置值进行修改。
配置文件的优先级
springboot 启动会扫描以下位置的application.properties/application.yml
文件作为Spring boot的默认配置文件
-
–file:./config/ (项目的config文件夹下 )
-
–file:./ (直接放到项目路径下)
-
–classpath:/config/ (类路径下的config文件夹下)
-
–classpath:/ (直接放到类路径下)
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
配置文件占位符
1、随机数
配置文件中${random} 可以用来生成各种不同类型的随机值,从而简化了代码生成的麻烦,例如 生成 int 值、long 值或者 string 字符串。
randomtest:
value: ${random.value}
int: ${random.int}
intarr: ${random.int(10)}
long: ${random.long}
longstr: ${random.long(10)}
uuid: ${random.uuid}
2、占位符获取之前配置的值,如果没有可以s使用指定默认值
user:
user-name: 张三${random.uuid}
age: ${random.int}
birth: 2017/12/15
dog:
name=${user.hello:hello}_dog //如果有user.hello,使用前面配置的user.hello的值,没有则使用默认值hello
age=15
使用自定义配置文件
有时候我们不希望把所有配置都放在application.properties里面,那么我们就可以使用@PropertySource
注解来加载指定的配置文件
我们可以自定义一个配置文件,比如user.properties
,路径跟也放在src/main/resources下面。
我们就可以在配置类中使用@PropertySource
注解来指定加载user.properties
配置文件
@PropertySource(value = {"classpath:user.properties"})
@ConfigurationProperties(prefix = "user")
@Component
@Data
public class User {
private String userName;
private int age;
private Date birthday;
}
注:@PropertySource
注解不支持yml配置文件
外部配置-命令行参数配置
Spring Boot是基于jar包运行的,打成jar包的程序可以直接通过下面命令运行:
java -jar xx.jar
可以以下命令修改tomcat端口号:
java -jar xx.jar --server.port=8081
可以看出,命令行中连续的两个减号–就是对application.properties中的属性值进行赋值的标识。
所以java -jar xx.jar --server.port=8081等价于在配置文件中添加属性server.port=8081。
如果你怕命令行有风险,可以使用SpringApplication.setAddCommandLineProperties(false)禁用它。
实际上,Spring Boot应用程序有多种设置途径,Spring Boot能从多重属性源获得属性,包括如下几种:
-
命令行参数,所有的配置都可以在命令行上进行指定,多个配置用空格分开; --配置项=值
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
-
来自java:comp/env的JNDI属性
-
Java系统属性(System.getProperties())
-
操作系统环境变量
-
RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找;
优先加载带profile
-
jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
-
jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件**
再来加载不带profile
-
jar包外部的application.properties或application.yml(不带spring.profile)配置文件
-
jar包内部的application.properties或application.yml(不带spring.profile)配置文件
-
@Configuration注解类上的@PropertySource
-
通过SpringApplication.setDefaultProperties指定的默认属性
所有支持的配置加载来源;参考官方文档
配置文件值获取
SpringBoot有两种方式获取配置文件的值
使用@Value注解
配置文件中提供自定义属性的支持,这样我们就可以把一些常量配置在这里:
user:
user-name: 张三
age: 18
birthday: 2000/01/01
然后直接在要使用的地方通过注解@Value(value=”${config.name}”)
就可以绑定到你想要的属性上面
@Component
@Data
public class User{
@Value("${user.user-name}")
private String userName;
@Value("${user.age}")
private int age;
@Value("${user.birthday}")
private Date birthday;
}
测试运行,输出获取到的user
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootApplicationTests {
@Autowired
User user;
@Test
public void contextLoads() {
System.out.println(user);
}
}
输出结果如下
User(userName=张三, age=18, birthday=Sat Jan 01 00:00:00 CST 2000)
使用@ConfigurationProperties注解
有时候属性太多了,一个个绑定到属性字段上太累,我们可以使用@ConfigurationProperties
注解
该注解的含义是将配置文件中配置的每一个属性的值,映射到这个组件中,其属性prefix = "xxx"指定配置文件中哪个下面的所有属性进行一一映射
注:只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties
功能;所以类上必须有@Component
注解
这样我们就不必在每个属性上都配置@Value
注解,只需要在类上配置@ConfigurationProperties(prefix = "user")
SpringBoot就会自动将每个属性都映射上配置文件中对应的值
@Component
@ConfigurationProperties(prefix = "user")
@Data
public class User{
private String userName;
private int age;
private Date birthday;
}
测试运行,输出获取到的user
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootApplicationTests {
@Autowired
User user;
@Test
public void contextLoads() {
System.out.println(user);
}
}
输出结果如下
User(userName=张三, age=18, birthday=Sat Jan 01 00:00:00 CST 2000)
@Value和@ConfigurationProperties注解的区别
@ConfigurationProperties | @Value | |
---|---|---|
批量配置 | 支持 | 不支持 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
- 批量配置:如上面实例中所示,
@ConfigurationProperties
可以批量注入配置文件中的属性,@Value
只能一个一个注入 - 松散语法:
@ConfigurationProperties
支持松散语法,比如配置文件中user-name使用@ConfigurationProperties
可以给userName属性注入值,但是@Value("${user.userName}")
不能将配置文件中的user-name属性赋值给userName - SpEL语言:
@value
支持SpEL语言,比如:
但是如果在配置文件中age=#{11*2},@Value("#{11*2}") private int age;
@ConfigurationProperties
并不能将计算后的值注入给age属性 - JSR303数据校验:使用
@ConfigurationProperties
可以使用数据校验,比如:@Email private String email;
@ConfigurationProperties
支持复杂性封装,比如user: user-name: 张三 age: 18 birthday: 2000/01/01 map: {1:v1,k2:v2}
@Component @ConfigurationProperties(prefix = "user") @Data public class User{ private String userName; private int age; private Map map; }
@ConfigurationProperties
可以直接将配置文件中的map赋值给map属性
Profile-多环境配置
当应用程序需要部署到不同运行环境时,配置通常会有所不同,最简单的比如日志,生产日志会将日志级别设置为WARN或更高级别,并将日志写入日志文件,而开发的时候需要日志级别为DEBUG,日志输出到控制台即可。如果每次发布的时候替换掉配置文件,这样太麻烦了,Spring Boot的Profile就给我们提供了两种解决方案,命令带上参数就搞定。
1、多Profile文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
默认使用application.properties
的配置,可以在配置文件中使用spring.profiles.active= xxx
指定使用哪个配置文件
比如我们想使用application-dev.yml
这个配置文件就可以在主配置文件中配置
spring:
profiles:
active: dev
2、yml支持多文档块方式
yml可以使用---
来分割代码块,可以指定使用哪个代码块
server:
port: 8081
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
也可以使用外部参数激活使用哪个配置文件
java -jar spring-boot.jar --spring.profiles.active=dev;
或者使用虚拟机参数
-Dspring.profiles.active=dev