本篇文章介绍SpringBoot项目的配置文件相关内容
IDE:IntelliJ IDEA 2019.3.3
Java:jdk1.8
Spring Boot:2.3.5.RELEASE
在SpringBoot快速构建文章中,我们仅仅导入了一个web starter依赖便能够运行整个web工程。原因是starter启动器已经帮我们配置好了所有所需的最少配置项,我们只需要关注业务代码的编写即可。
**但在一些场合下,SpringBoot的默认配置无法满足业务的使用需求,开发人员需要根据不同场景配置不同的配置项。**这种情况下,我们可以使用SpringBoot为我们提供的全局配置文件进行解决。
SpringBoot为开发人员提供了 application
全局配置文件。在应用启动时,会加载该配置文件中的属性进入应用中,开发人员可以通过一些方式进行引用。配置文件有以下特点:
application
.properties
,.ymal
src/main/resources/application.yml
,src/main/resources/config/application.yml
下面对两中格式的配置文件进行简要说明。
application.properties
该文件就是通用的properties文件,其中存储的k-v键值对:
server.port=8081
application.yml
yml的全称为YAML(YAML Ain’t Markup Language),是一种以数据为中心的标记语言,比json/xml
更适合做配置文件。具体可以参考:ymal官方网站。其简单格式如下:
# 普通键值对形式,下面的配置等价于:
# server.port=8081
# server.address=localhost
person:
name: Tom
age: 20
person: {name: Tom, age: 20}
# 数组形式,下面的配置等价于
# arr=[1,2,3]
arr:
- 1
- 2
- 3
arr: [1,2,3]
ps:注意yml文件中的缩进要保持一致
配置文件占位符
在编写配置文件时,可以使用 类似于表达式的占位符 来获取已经写好了的配置、随机数、默认配置等。
person.last‐name=张三${random.uuid}
person.age=${random.int} # 随机数
person.birth=2017/12/15
person.boss=${person.last‐name} # 已经写好了的配置
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog # 默认值
person.dog.age=15
接下来我们就来快速实践下:
# application.yml
server:
port: 8081
可以从启动日志中看到应用启动端口已经改为8081,说明配置文件成功生效
Tomcat started on port(s): 8081 (http) with context path ''
上面的实践中我们使用的是SpringBoot的系统配置,这些配置是在引入starter依赖时随着依赖包中某些 ***Properties.java
配置类一起引入的。这些 ***Properties.java
通常被 @ConfigurationProperties
注解所注释,该注解也是配置类绑定配置文件的核心注解。配置类绑定配置文件后,开发人员便可以通过配置类引用配置文件中的配置。
接下来我们便实践下如何将配置类绑定配置文件:
首先快速搭建一个SpringBoot项目,并在application.yml中准备好如下配置:
# application.yml
person:
name: mike
age: 20
hobby:
- sleep
- eat
- football
在启动类所在路径下创建config文件夹,并在该文件夹中创建 PersonConfiguration.java
配置类。
prefix
指定配置文件中的顶层配置,即上述文件中 person
下的配置都会与配置类中的属性一一对应绑定。// PersonConfiguration.java
@Data // lombok 注解
@Configuration
@ConfigurationProperties(prefix = "person")
public class PersonConfiguration {
private String name;
private int age;
private List<String> hobby;
}
然后创建测试controller测试是否绑定成功,在postman中发起请求测试:
// TestController.java
@RestController
public class TestController {
@Resource
private PersonConfiguration personConfiguration;
@RequestMapping("/test")
public String test() {
return personConfiguration.toString();
}
}
测试结果如下,配置已经成功被业务类所引用。
除了第二章节所述的绑定配置的方法,SpringBoot还有第二种方法绑定配置,就是通过 @value
注解的形式。
我们可以在业务类(或其它被spring容器接管的bean)中声明属性,然后在属性上标记 @value
注解,spring会自动替我们绑定相应配置。这里有几点需要注意:
${obj.attr:defaultValue}
接下来我们快速实践下,配置还是使用第二章中的application.yml,我们只针对业务类修改,并通过postman发起请求测试:
// TestController.java
@RestController
public class TestController {
@Value(value = "${person.name:aaa}")
private String name;
@RequestMapping("/test")
public String test() {
return name;
}
}
当把 @Value
注解中的value值修改为 ${people.name:aaa}
时,测试结果如下,发现默认值已经生效
第二章我们用 @ConfigurationProperties
将配置类与配置文件绑定起来,但绑定的是系统配置文件。试想一下,如果将所有的配置全部放在系统配置文件中,一个文件将会巨大并且难以管理。因此我们需要一种手段能够将自定义配置文件与配置类绑定在一起,@PropertySource
注解便是解决方案。
@PropertySource
注解能够声明配置来源,然后通过 @ConfigurationProperties
注解标识当前配置类需要与哪些配置进行绑定。使用该注解时有几点需要注意:
@PropertySource
和 @ConfigurationProperties
必须共同使用,前者声明配置来源,后者指定配置内容具体实践如下:
// Person.java
@Data
@PropertySource(value = {"classpath:person.properties"})
@ConfigurationProperties(prefix = "Person")
@Configuration
public class Person {
private String name;
private int age;
private List<String> hobby;
}
# person.properties
person.name=mike
person.age=20
person.hobby=a,b,c
在实际开发中,往往会有多个环境。比如开发环境用于给程序员开发迭代使用;测试环境用于给测试人员测试或外部对接人员使用;预发环境用于模拟真实线上场景,为真实上线做准备使用;正式环境用于生产。
单个配置文件是很难顺利的满足这么多环境使用的。比如说配置数据库地址时,不同环境的数据库地址不同,在单个配置文件中就得花费很大的功夫进行区分。
好在SpringBoot配置文件具备profile机制,允许开发人员在不同环境激活不同profile配置。
先来说说文件分离形式,我们可以在classpath下创建 application-dev.properties、application-prod.properties 两个配置文件,用于标明文件分别在开发环境与生产环境使用。然后我们在主全局配置文件application.properties 中设置要激活的环境,即可激活相对应的配置文件。
# application.properties
spring.profiles.active=dev
# application-dev.properties
server.port=8081
# application-prod.properties
server.port=8082
启动应用后可以看见应用在8081端口,说明dev配置文件被激活。
这里需要注意几点:
yml文件把通过 ---
分割多个文档块,一个文档块相当于一个配置文件。基于此,我们可以将不同环境下的配置放置在不同文档块中。
# application.yml
server:
port: 8083
spring:
profiles:
active: prod
---
spring:
profiles: dev
server:
port: 8084
---
spring:
profiles: prod
server:
port: 8085
启动应用后可以看见应用在8085端口,说明prod配置文件被激活。
spring.profile.active=dev
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
-Dspring.profiles.active=dev
Spring Boot 应用启动时,会加载下面四个目录的application.properties
和applicatio.yml
文件作为应用的全局配置。以下目录由上到下优先级逐渐降低,即高优先级配置会覆盖低优先级配置。
rootpath:config/
rootpath:/
classpath:config/
classpath/
rootpath为项目的根路径,比如我创建了一个SpringBoot02_Config项目,项目所有文件都放置在SpringBoot02_Config文件夹下,则 SpringBoot02_Config/
为rootpath。
classpath为项目的类路径,一般在 rootpath/src/main/
下。
我们可以通过 spring.config.location
命令行参数来修改配置文件的位置。
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
这种方式的应用场景:项目已经迭代完成,并且成功打包,但后来发现漏了部分配置。此时可以通过这种方式指定外部配置文件,补充漏掉的配置。
SpringBoot可以从如下配置源加载配置,以下配置由上到下优先级逐渐降低,高优先级配置会覆盖低优先级配置。对于6/7/8/9条规则可以总结为:jar包外优先于jar包内,带profile优先于不带profile。
1、命令行参数:所有的配置都可以在命令行上进行指定,多个配置用空格分开,--spring.config.location=G:/application.properties
2、来自java:comp/env的JNDI属性
3、系统属性(System.getProperties())
4、操作系统环境变量
5、RandomValuePropertySource配置的random.*属性值
6、jar包外部的 application-{profile}.properties
或 application.yml
(带spring.profile)配置文件
7、jar包内部的 application-{profile}.properties
或 application.yml
(带spring.profile)配置文件
8、jar包外部的 application.properties
或 application.yml
(不带spring.profile)配置文件
9、jar包内部的 application.properties
或 application.yml
(不带spring.profile)配置文件
10、@Configuration
注解类上的@PropertySource
11、通过SpringApplication.setDefaultProperties
指定的默认属性
其他配置形式可以参考官方文档