二、Spring Boot配置文件
1. 配置文件
Spring Boot使用一个全局配置文件,配置文件名固定
- application.properties
- application.yml
配置文件存放路径
- 配置文件是放在src/main/resources目录或者类路径/config下
配置文件作用
- .yml是YAML语言的文件,以数据为中心,比json,xml等更适合做配置文件
- 参考语法规范
- 全局配置文件可以对一些默认配置值进行修改
YAML配置端口号:
server:
port: 8081
XML:
<server>
<port>8081</port>
</server>
2. YAML语法
基本语法
- **Key: Vaule: ** 表示键值对,key:和Vaule:后有空格
- 以空格的缩进控制层级关系,只要左对齐的一列数据都是同一层级的
- 属性和值的大小写敏感
值的写法
-
字面量: 普通的值(数字,字符串,布尔)
K:V:字面直接来写,字符串默认不用加引号
加上“”:不会转义特殊字符,特殊字符会作为本身想表示的意思
加上‘’:会转义特殊字符,如‘\n’会展示位字符串
-
对象、Map(属性和值)(键值对)
K:V:在下一行写队形的属性和值的关系,注意缩进
对象还是k: v: 的方式
friends: name: 张三 age:20
行内写法:
friends:{name: 张三,age: 20}
-
数组(List、Set)
用**- 值**表示数组中的一个元素
pets: - cat - dog - pig
行内写法
pets: [cat,dog,pig]
3. 配置文件值注入
3.1 创建Person类和Dog类
编写类中属性,setter & getter方法和toString()方法
Persong.java
public class Person {
private String lastName;
private Integer age;
private boolean boos;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public boolean isBoos() {
return boos;
}
public void setBoos(boolean boos) {
this.boos = boos;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boos=" + boos +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
}
Dog.java
public class Dog {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
3.2 配置属性文件
3.2.1 YAML属性文件配置
person:
lastName: zhangsan
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: v2}
lists:
- lisi
- zhaoliu
dog:
name: 小狗
age: 2
3.2.2 properties属性文件配置
person.last-name=张三
person.age=18
person.birth=2017/12/15
person.boos=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=dog
person.dog.age=15
注意:
- properties中文显示可能会出现乱码
- 解决办法:
3.3 获取属性文件的值
在Persong类上添加:
- @Component
- @configurationProperties(prefix = “person”)
@ConfigurationProperties(prefix = “person”)
-
告诉Spring Boot将本类中的所有属性和配置文件中相关配置进行绑定
-
prefix = “person”:配置文件中哪个下面的所有属性进行一一映射
-
添加这个注释可能会报出警告,此时添加下面依赖,并重新运行项目
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
@Component
- 只有这个组件是容器中的组件,才能提供@ConfigurationProperties(prefix = “person”)功能,故加上@Component
3.4 测试
- 在SpringBoot02ConfigApplicationTests中进行测试
- Spring Boot单元测试,可以在测试期间很方便的类似编码一样自动注入的容的功能
3.5. @value获取值和@ConfurationProperties区别
使用@Value获取值
-
加载配置文件的值
@Value("${person.last-name}") private String lastName;
-
@Value还可以直接写入值,不需要加载配置文件
@Value("12") private Integer age;
@value获取值和@ConfurationProperties比较
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
配置文件yml还是properties他们都能获取到值;
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
3.6 配置文件注入值数据校验
pom.xml文件添加以下依赖:
<!-- 数据校验依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Person类通过配置文件注入值时只能用**@ConfigurationProperties**,并且添加**@Validated**注解
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
/**
* <bean class="Person">
* <property name="laseName" value="字面量/${key}从环境变量、配置文件中获取值/#{spEL}“></property>
* </bean>
*/
// @Value("${person.last-name}")
@Email
private String lastName;
@RestController是**@ResponseBody和@Controller**的结合,用于返回jison数据
3.7. @PropertiesSource、@ImportResource和@Bean
3.7.1 @ProperttySource
-
加载指定的配置文件
-
@ConfigurationProperties:默认从全局配置文件中获取值,数据多时,会造成难以处理
-
package com.why.springboot.bean; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Email; import java.util.Date; import java.util.List; import java.util.Map; /** * @Description TODO 将配置文件中配置的值映射到Person中 * @ConfigurationProperties: 告诉Spring Boot将本类中的所有属性和配置文件中相关的配置进行绑定 * prefix = "person": 配置文件中那个下面的所有属性进行一一映射 * 只有这个组件是容器中的组件,才能提供@ConfigurationProperties(prefix = "person")功能,故加上@Component * @Author why * @Date 2020/12/9 10:53 * Version 1.0 **/ @Component @ConfigurationProperties(prefix = "person") @Validated @PropertySource(value = {"classpath:person.properties"}) public class Person { /** * <bean class="Person"> * <property name="laseName" value="字面量/${key}从环境变量、配置文件中获取值/#{spEL}“></property> * </bean> */ // @Value("${person.last-name}") // @Email private String lastName; // @Value("12") private Integer age; private boolean boos; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog; public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public boolean isBoos() { return boos; } public void setBoos(boolean boos) { this.boos = boos; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public Map<String, Object> getMaps() { return maps; } public void setMaps(Map<String, Object> maps) { this.maps = maps; } public List<Object> getLists() { return lists; } public void setLists(List<Object> lists) { this.lists = lists; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } @Override public String toString() { return "Person{" + "lastName='" + lastName + '\'' + ", age=" + age + ", boos=" + boos + ", birth=" + birth + ", maps=" + maps + ", lists=" + lists + ", dog=" + dog + '}'; } }
-
其value值还可作为数组,传入多个配置文件
3.7.2 @ImportResource
-
作用:导入Spring的配置文件,让配置文件里面的内容生效
-
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别
自己的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 自定义Bean --> <bean id="helloService" class="com.why.springboot.service.HelloService"></bean> </beans>
-
想让Spring的配置文件生效,加载进来,需让**@ImportSource**标注在一个配置类上
-
//导入Spring配置文件让其生效 @ImportResource(locations = {"classpath:beans.xml"})
此时Spring配置文件可用
SpringBoot推荐给容器中添加组件的方式,推荐使用全注解
-
配置类**@Configuration** - - - - - - >Spring配置文件
-
使用**@Bean**给容器中添加组件
-
@Configuration //指明当前类是配置类,替代之前Spring的配置文件 public class MyAppConfig { @Bean public HelloService helloService(){ System.out.println("配置类@Bean给容器中添加组件"); return new HelloService(); } }
-
**@Configuration:**指明当前类是配置类,替代之前的Spring配置文件
-
**@Bean:**原来在配置文件中使用bean标签添加组件,现在使用@Bean将方法的返回值添加到容器中,容器默认的id就是方法名
3.8 配置文件占位符
3.8.1 随机数
astName: 张三${random.uuid}
age: ${random.int}
3.8.2 占位符
- 获取之前配置的值
- 如果之前没有配置也可以设置默认值
person:
lastName: 张三${random.uuid}
age: ${random.int}
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: v2}
lists:
- lisi
- zhaoliu
dog:
name: ${person.hello:hello}_dog
age: 2
4. Profile多环境支持
Profile是Spring对不同环境提供不同功能的支持,可以通过激活、指定参数等方式形成快速切换环境
多Profile文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
例如此时创建application-dev.properties和application-prod.properties两个配置文件
默认使用application.properties
此时若激活哪个配置文件则使用那个配置文件
application-dev.properties
#开发环境下的配置文件
server.port=8081
application-prod.properties
#生产环境下的住配置文件
server.port=8082
YAML支持多文档块方式
server:
port: 8081
spring:
profiles:
active: prod
---
server:
port: 8082
spring:
config:
activate:
on-profile: dev
---
server:
port: 8083
spring:
config:
activate:
on-profile: prod
激活指定的profile
-
在application.properties文件中指定激活的配置文件
spring.profiles.active=dev
-
YAML文档激活时使用
spring: profiles: active: prod
-
命令行方式激活
- - spring.profiles.active=dev
也可以将项目打包后运行jar文件,使用命令行形式修改激活环境
-
虚拟机参数;
-Dspring.profiles.active=dev
5. Spring Boot配置文件加载位置
Spring Boot启动会扫描一下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件
–file:./config/
–file:./
–classpath:/config/
–classpath:/
优先级由高到低,高优先级的配置会覆盖低优先级的配置
Spring Boot会从这四个位置全部加载配置文件,最终会形成互补配置的效果
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后可以使用命令行参数的形式,启动项目的时候指定配置文件的新位置。指定配置文件和默认加载的这些配置文件会共同起作用,形成互补配置
spring.config.location=文件路径
6. 外部配置加载顺序
SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
1.命令行参数
所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
多个配置用空格分开; --配置项=值
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找;
优先加载带profile
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
再来加载不带profile
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性
所有支持的配置加载来源;