1.准备环境
有如下配置文件,yml格式和properties格式
yml格式(经我测试发现,属性前面的空格两个不行,需要四个空格才能读出来,这应该是yml的语法,并且属性:后面必须有一个空格):
person:
name: 张三
age: 18
birth: 2020/10/1
maps: {k1: v1,k2: v2}
lists:
- item1
- item2
- item3
phone:
os: ios
model: iphone11
price: 9999
properties格式:
person.name= 张三
person.age= 18
person.birth= 2020/10/1
person.maps.k1= v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone11
person.phone.price= 9999
建立与之对应的类,并实现getter、setter和toString
Person类
public class Person {
private String name;
private int age;
private Date birth;
private HashMap<String,Object> maps;
private List<Object> lists;
private Phone phone;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", phone=" + phone +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public HashMap<String, Object> getMaps() {
return maps;
}
public void setMaps(HashMap<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
}
Phone类型:
public class Phone {
private String os;
private String model;
private double price;
@Override
public String toString() {
return "Phone{" +
"os='" + os + '\'' +
", model='" + model + '\'' +
", price=" + price +
'}';
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
2.使用@ConfigurationProperties获取配置文件
在Person类上面写注解:@ConfigurationProperties、@Component
@Component: 通过添加 @Component 注解让 Component Scan 扫描到
@ConfigurationProperties(prefix = "person"): # perfix表示通过指定的前缀,绑定配置文件中的配置
@Component
@ConfigurationProperties(prefix = "person") # perfix表示
public class Person {
}
这里配置完成后idea会有一个小提示:未配置 Spring Boot 配置注释处理器,此时我们可以将如下配置写入pom文件的dependencies中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
然后重新生成pom文件运行项目,就可以在配置文件中提示出我们定义的Person类
测试是否配置成功
我们在测试类中进行测试
@SpringBootTest
class ConfigurationDemoApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
运行测试会在控制台中打印出,表示已经配置成功
Person{name='张三', age=18, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v2}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone11', price=9999.0}}
如果我们使用的配置文件是properties,中文会出现乱码,如何解决?
打开idea,将透明的原生到 ASCII 转换勾选上就可以了
3.使用@Value注解获取配置文件
有如下配置:
@Component
public class Person {
@Value("${person.name}")
private String name;
@Value("#{10*2}")
private int age;
@Value("1999/1/1")
private Date birth;
private HashMap<String,Object> maps;
private List<Object> lists;
private Phone phone;
}
测试结果:
Person{name='张三', age=20, birth=Fri Jan 01 00:00:00 CST 1999, maps=null, lists=null, phone=null}
4.@ConfigurationProperties 和 @Value 获取值比较
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件的属性 | 单独指定 |
松散绑定 | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型(map、list) | 支持 | 不支持 |
松散绑定:
比如绑定person.firstName,配置文件中可以写:person.firstName、person.first-name、person.first_name、PERSON_FIRST_NAME
SpEL:
#{10*10} 数学计算
#{10>1?"是":"否"} 比较运算
#{field.toString()} 调用方法
#{T(java.lang.Math).PI} 调用静态方法
JSR303数据校验:
必须使用@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String name;
}
@Value相对来说更加灵活,有如下情况,我们只需要person.name
@Value("${person.name}")
private String personName;
@RequestMapping("/hello")
public String index(){
return "hello"+personName;
}
访问 /hello 可以返回:hello张三
5. 加载指定的配置文件 @PropertySource
有时候我们并不想把某些配置放在全局的配置文件下,比如我们将person配置放在 resource 目录下:
person.properties
person.name= 李四
person.age= 30
person.birth= 2020/10/1
person.maps.k1= v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone12
person.phone.price= 11111
那么应该如何读取呢?在配置类上新增:@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
@PropertySource(value = {"classpath:person.properties"})
public class Person {
}
运行测试,控制台打印如下:
Person{name='李四', age=30, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v1}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone12', price=11111.0}}
6. 通过@ImportResource实现xml配置的装载,导入Spring的配置文件,让配置文件里的内容生效
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;SpringBoot所有的bean装载全部通过java配置实现,那么一直以来习惯的xml配置是否就没有了用武之地呢,答案是否定的
在项目中增加一个services/HelloService类
在resource目录下增加一个配置文件
beans.xml
<?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 id="helloService" class="com.qingtian.configurationdemo.services.HelloService"></bean>
</beans>
编写单元测试方法
@Autowired
ApplicationContext context;
@Test
public void testHelloService(){
System.out.println(context.containsBean("helloService"));
}
运行单元测试,控制台打印是:false
SpringBoot中没有Spring的配置文件,而且我们自己写的配置文件,也不能自动识别,如何让配置文件生效呢?
@ImportResource(locations = {"classpath:beans.xml"})
public class ConfigurationDemoApplication {
}
再次运行测试方法,控制台打印:true
SpringBoot不推荐编写xml配置文件,更推荐使用全注解的方式
编写我们的配置类 config/MyConfig
@Configuration //指明当前类是一个配置类,就是来代替之前的Spring的配置文件
public class MyConfig {
//将方法的返回值添加到容器中,容器默认的id就是方法名
@Bean
public HelloService helloService(){
return new HelloService();
}
}
7.配置文件中的占位符
RandomValuePropertiSource:配置文件中可以使用随机数
${random.value} ${random.int} ${random.long} ${random.int(10)} ${random.int[1024,65535]}
属性配置占位符
app.name=myapp
app.description=${app.name} is a Spring Boot application
-- 可以在配置文件中引用前面配置过的属性
-- ${app.name:默认值}来指定找不到属性时的默认值
8.通过Profile配置SpringBoot项目的不同环境
当我们需要在开发、测试、生产系统不断切换时,如果只有一个配置文件,那会相当的麻烦,使用Profile对不同环境提供不同配置功能,可以通过激活、指定参数等方式快速切换环境
多profile文件形式:
--格式:application-{profile}.properties
- application-dev.properties
- application-prod.properties
多profile文档块模式(yml文件支持):
server:
port: 8000
spring:
profiles:
active: dev
---
server:
port: 8001
spring:
profiles: dev
---
server:
port: 80
spring:
profiles: prod
激活方式:
- 命令行 --spring.profiles.active=dev
- 配置文件 spring.profiles.active=dev
- jvm参数 -Dspring.profiles.active=dev
9.配置文件的加载位置
- SpringBoot启动会扫描以下位置的application.properties或application.yml文件作为SpringBoot的默认配置文件
- file: ./config/
- file: ./
- classpath: /config/
- classpath: /
- 以上是按照 优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容
- 我们也可以通过配置spring.config.location来改变默认配置
10.外部配置加载顺序
SpringBoot支持多种外部配置方式(优先级由高到低)
- 命令行参数
- 来自java:com/env的JNDI属性
- Java系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource配置的random.*属性值
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件
- @Configuration注解类上的@PropertySource
- 通过SpringApplication.setDefaultProperties指定的默认属性