1、Spring Boot配置文件
Spring Boot支持两种形式的配置文件,分别是.properties、和.yml,而且配置文件的名字是固定不可变的: * application.properties * application.yml
配置文件的作用是修改Spring Boot自动配置的默认值。相对于properties文件而言,yml文件更年轻,也有很多的坑。下面我们就来一一学习一下。 注意:当application.properties文件和application.yml同时存在的时候,application.properties会优先加载,application.yml则后加载,而且在applicatin.properties中已经加载的属性如果在application.yml中再次出现会被忽略,如果是application.yml中的独有的属性则会加载。
2、YAML/YML文件简介
2.1 什么是YAML/YML文件
YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递回缩写。YAML 是一个可读性高,用来表达资料序列的编程语言。YAML是一种直观的能够被电脑识别的的数据数据序列化格式,容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP等。YAML以数据为中心,比json、xml等更适合做配置文件。
2.2 YAML/YML的基本语法
基本语法:
key: value
,key: 和value中间要有一个空格,而且key: value的形式可以写无限层。还有一下规则: 1.大小写敏感 2.使用缩进表示层级关系 3.缩进时不允许使用Tab键,只允许使用空格。 4.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 5.只有一种注释方式,使用#
2.3 YAML/YML支持的数据结构
YML支持3中类型的数据结构类型
1.字面量 2.对象(属性和值),Map(键值对) 3.数组(List、Set)
1、字面量具体包括:字符串、布尔值、整数、浮点数、Null、时间、日期 字面量可以直接使用,但是特别注意字符串的字面量在写的时候是不需要引号的(无论单引号还是双引号)。单/双引号在yml语法中有特殊的含义: * “”:双引号;会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思 name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi * ”:单引号;不会转义特殊字符,特殊字符最终只是一个普通的字符串数据 name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
2.对象(属性和值),Map(键值对) 基本的语法还是key:value
,以一个例子来说明:
friends:
lastName: zhangsan
age: 20
对应的行内写法:
friends: {lastName: zhangsan,age: 18}
3.数组(List、Set) 用- 值表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
举个栗子:配置一个Person的信息
package com.xust.iot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
* 但是要特别注意:只有这个组件是容器中的组件,容器才能提供@ConfigurationProperties的功能;
*/
@Component
@ConfigurationProperties(prefix="person")
public class Person {
private String name;
private Integer age;
private Address address;
private Map<String,Object> map;
private List<String> list;
//省略getter setter和toStrig方法
package com.xust.iot.bean;
public class Address {
private String province;
private String city;
private String county;
private String street;
//省略getter setter和toStrig方法
}
我们可以导入配置文件处理器,编写配置的时候就有提示了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
在application.yml配置文件中配置preson信息:
#写yml配置的时候要特别注意key和value之间要有一个空格,同级属性左对齐
person:
name: 李四
age: 20
map:
key1: value1
key2: value2
list:
- hello
- hi
- bye
address:
province: 陕西
city: 西安
county: xx
street: xx
在SpringBoot测试类中测试IOC是否可以拿到在配置文件中配置的信息
package com.xust.iot;
import com.xust.iot.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootConfigApplicationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
测试结果:

3、properties文件简介
properties文件大家经常用,这里就简单介绍一下。其语法结构形如:key=value。注意中文乱码问题,需要转码成ASCII。在IDEA中可以设置自动转换把uft-8格式自动转成ASCII,设置方式是:依次点击【File】=>【Other Settings】=>【settigs for new projects】,搜索File Encodings,然后做如下配置:

上面Person信息的properties配置如下:
person.name=小明
person.age=20
person.address.province=陕西
person.address.city=西安
person.address.county=xx
person.address.street=xx
person.map.key1=value1
person.map.key2=value2
person.list=hello,hi,bye
4、配置文件值注入
4.1 @Value获取值和@ConfigurationProperties获取值比较
Spring Boot通过ConfigurationProperties注解从配置文件中获取属性。从上面的例子可以看出ConfigurationProperties注解可以通过设置prefix指定需要批量导入的数据。支持获取字面值,集合,Map,对象等复杂数据。ConfigurationProperties注解还有其他特么呢?它和Spring的Value注解又有什么区别呢?带着这些问题,我们继续往下看。
比较 | @ConfigurationProperties | @Value |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties。
4.1 配置文件注入值数据校验
使用@Vaildatad可以给配置的属性数据校验功能。可以用在类、方法、参数上。可以加的验证注解如下:
@Null //限制只能为null
@NotNull //限制必须不为null
@AssertFalse //限制必须为false
@AssertTrue //限制必须为true
@DecimalMax(value) //限制必须为一个不大于指定值的数字
@DecimalMin(value) //限制必须为一个不小于指定值的数字
@Digits(integer,fraction) //限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future //限制必须是一个将来的日期
@Max(value) //限制必须为一个不大于指定值的数字
@Min(value) //限制必须为一个不小于指定值的数字
@Past //验证注解的元素值(日期类型)比当前时间早
@Pattern(value) //限制必须符合指定的正则表达式
@Size(max,min) //限制字符长度必须在min到max之间
@NotEmpty //验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank //验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank //只应用于字符串且在比较时会去除字符串的空格
@Email //验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
下面举个例子:
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@NotEmpty
@Size(max = 5, min = 2)
private String name;
@Max(70)
@Min(10)
private Integer age;
@Past
private Date birth;
@NotEmpty
private Address address;
@NotEmpty
private Map<String, Object> map;
@NotEmpty
private List<String> list;
//省略getter setter和toStrig方法
}
4.2 @PropertySource&@ImportResource&@Bean
- @PropertySource:加载指定的配置文件;
person.properties
person.name=小明
person.age=20
person.address.province=陕西
person.address.city=西安
person.address.county=xx
person.address.street=xx
person.map.key1=value1
person.map.key2=value2
person.list=hello,hi,bye
person.birth=2019/04/5
package com.xust.iot.bean;
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.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
//使用PropertySource注解指定配置文件的路径,SpringBoot就会在启动的时候加载,然后把配置中的值赋给这个配置类的对应属性。
@PropertySource(value = {"classpath:personInfo.properties"})
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@NotEmpty
@Size(max = 5, min = 2)
private String name;
@Max(70)
@Min(10)
private Integer age;
@Past
private Date birth;
private Address address;
@NotEmpty
private Map<String, Object> map;
@NotEmpty
private List<String> list;
//省略getter setter和toStrig方法
}
- @ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
在src/main/resources下新建一个Spring配置文件applicationContext.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="address" class="com.xust.iot.bean.Address">
<property name="province" value="陕西"/>
<property name="city" value="汉中"/>
<property name="county" value="xxx"/>
<property name="street" value="xxx"/>
</bean>
</beans>
在Spring Boot的主程序类中使用@ImportResource引入配置这个配置文件

然后在测试类中自动注入ApplicationContext来拿这个组件
package com.xust.iot;
import com.xust.iot.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootConfigApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
public void contextLoads() {
System.out.println(ioc.containsBean("address"));
System.out.println(ioc.getBean("address").toString());
}
}
测试结果:

虽然这种方式可以用,但是一般我们不这么用,而且Spring Boot也不推荐这么使用,Spring Boot推荐使用全注解的方式来添加配置文件。 * 1、配置类**@Configuration**------>Spring配置文件
- 2、使用**@Bean**给容器中添加组件
接下类,我们在com.xust.iot基包下新建配置类ApplicationConfig.java
package com.xust.iot;
import com.xust.iot.bean.Address;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//使用@Configuration告诉Spring这是配置
@Configuration
public class ApplicationConfig {
//@Bean注解相当于<bean></bean>标签,特别注意:方法名就是bean的id
@Bean
public Address address(){
System.out.println("在配置类中使用@Bean注解添加了组件");
Address address=new Address();
address.setProvince("陕西省");
address.setCity("西安");
address.setCounty("xxx");
address.setStreet("xxx");
return address;
}
}
运行后得到的效果一样:

5、配置文件占位符
在application.properties和application.yml文件可以使用${random}来设置随机值
5.1 常用随机设值如下
${random.value} //随机生成一个32位的字符串,如:b21d56d2f10d74f84608dfff01b25552
${random.int} //随机生成一个int范围的随机数
${random.long} //随机生成一个int范围的随机数
${random.int(10)} //随机生一个[0,10]之间的随机数
${random.int[1024,65536]} //随机生成一个[1024,65536]之间的随机数
${对象.属性} //使用某个已配置的属性的值
${对象.属性:默认值} //使用某个已配置的属性的值,如果没有就是用默认值
在application.yml文件中写如下配置:
person:
name: 李四${random.uuid}
age: ${random.int(45,70)}
birth: 2019/08/24
map:
key1: 232424@qq.com
key2: dad323@163.com
list:
- hello
- hi
- bye
address:
province: 陕西
city: 西安
county: ${person.name}
street: ${person.address.province}-${person.address.city}
在测试类中打印person的信息,结果如下:

6、Spring Boot profile
Spring支持对不同环境,提供不同配置,可以通过激活、指定参数等方式快速的切换环境 。环境profile可以是开发环境(develop)、测试环境(fuy)、生产环境(production)等
6.1 配置多个profile
在主配置文件编写的时候,文件名可以是 application-{profile_name}.properties/yml,比如下面分别编写的application-develop.properties和application-production.properties
application-develop.properties
debug=true
server.port=8081
server.servlet.acontext-path=/book
application-production.properties
debug=false
server.port=80
server.servlet.context-path=/book
目录结构:

在主配置文件application.properties中,使用spring.profiles.active=[profile]
来激活不同的环境,如下激活develop环境:

启动Spring Boot观察Tomcat启动的端口

激活生产环境:spring.profiles.active=production

6.2 YML配置多个profile
然而使用properties文件配置不同环境还是太麻烦了,YML对多profile的支持更加简单粗暴,直接通过连续的三个-
就可以划分出不同的文件,配置示例:
#主配置文件
server:
port: 8083
spring:
profiles:
active: production #激活生产环境
---
#开发环境
server:
port: 8083
servlet:
context-path: /boot
debug: true
spring:
profiles: develop #使用spring.profiles来指定这个环境名
--- #使用连续的三个横线分隔不同的profile(文档区)
#生产环境
server:
port: 80
servlet:
context-path: /boot
debug: true
spring:
profiles: production
注意:Spring Boot启动的时候会优先加载.properties的文件,然后才来加载.yml文件,如果要想使applicaton.yml中配置的信息可以使用,那么.properties中不能有和.yml相同的配置。
6.3 激活指定profile的不同方式
1、在主配置文件中指定 spring.profiles.active=dev,上面的配置方式就是这种。
2、命令行: 可以在IDEA中配置 --spring.profiles.active=develop 来启动开发环境,操作如下:



7、配置文件的加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
–file:./config/
–file:./
–classpath:/config/
–classpath:/

这些位置的配置文件加载的优先级由高到底,而且高优先级的配置如果在低优先即中出现,那么低优先优先级中重复配置不会生效。但是低优先级中独有的配置还是会生效。也就是说SpringBoot会从这四个位置全部加载主配置文件;并且会互补配置;
==我们还可以通过spring.config.location来改变默认的配置文件位置==
比如:项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置; 首先在硬盘的另一个地方(我这里在E://)创建application.properties。添加如下配置:
debug=false
server.port=8087
server.servlet.context-path=/book

