我们在开发一个项目时,肯定会用到配置文件,spring boot为我们提供了丰富的外部配置,常见的有:
推荐使用YAML来写配置文件,因为相比与传统的json或者是properties格式的配置文件,YAML格式更简洁易读。YAML语法学习推荐一下阮一峰大神的YAML教程
核心配置文件是我们用的比较频率最高的一种配置方式,核心配置文件使用key-value的形式来进行配置。其中key主要分为两种:
以数据库配置为例,在application.yml配置文件中添加如下:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/douban?serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
在 application.yml配置文件中添加一个用户的信息如下:
user:
userName: 张三
age: 18
birthday: 1991/01/01
address: {province: 陕西, city: 西安, zone: 雁塔区}
skills: [Java, Python]
同时,spring boot也支持在系统加载的时候配置随机数:
user:
random:
secret: ${random.value} #随机32位MD5字符串
intNumber: ${random.int} #随机int数字
longNumber: ${random.long} #随机long数字
uuid: ${random.uuid} #随机uuid
lessTen: ${random.int(10)} #随机10以内的数字
range: ${random.int[1024,65536]} #随机1024~65536之内的数字
在需要读取配置文件的类上添加@ConfigurationProperties和@Component(或@Configuration),并提供getter和setter方法。以读取上面的用户信息为例,我们编写一个绑定的类:
@Component //让该类被spring的IOC容器管理,也可以使用@Configuration
@ConfigurationProperties(prefix = "user") // 通过prefix来绑定对应的属性
public class User {
private String userName;
private int age;
private Date birthday;
private Map<String, Object> address;
private String[] skills;
// 省略getter和setter方法
}
我们编写一个测试类打印一下这个User的值,可以看到已经读取到了配置文件中的值。
User{userName='张三', age=18, birthday=Tue Jan 01 00:00:00 CST 1991, address={province=陕西, city=西安, zone=雁塔区}, skills=[Java, Python]}
spring boot读取默认配置时也是使用了@ConfigurationProperties这个注解,具体原理可以参考之前的文章。
还是用上面那个用户信息的例子来说明如何使用@Value,我们编写一个绑定类。
@Component
public class User {
@Value("${user.userName}")
private String userName;
@Value("99")
private int age;
// 省略getter和setter方法
}
我们只需要在需要注入的属性或者setter方法上加上@Value("${xxx}")/@Value(“xxx”)这样就可以将配置文件中的值注入到绑定类中,并且还可以将任意值注入属性。我们打印一下User对象:
User{userName='张三', age=99}
注意:@Value不支持注入静态变量,可以间接通过Setter方法来注入
private static Date birthday;
@Value("${user.birthday}")
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
特性 | @Value | @ ConfigurationProperties |
---|---|---|
批量注入 | NO | YES |
支持松散语法 | NO | YES |
支持支持SpringEL | YES | NO |
支持JSR303数据校验 | NO | YES |
注入复杂类型1 | NO | YES |
松散语法:以本例来说,java文件中的属性名为userName,为标准的驼峰命名方式。我们在yml或者properties中可以不采用驼峰命名方式,而是使用user-name。这样也可以注入成功,这就是松散语法。
显然@ConfigurationProperties的功能更加强大,所以在开发中建议优先使用@ConfigurationProperties。
在项目开发中,我们有时会将与项目相关的一些配置信息保存到单独的配置文件中,这时我们可以使用@PropertySource注解来读取我们自定义的配置文件。
我们在resources下新建一个config.properties2文件,并写入以下内容:
user.user-name=李四
user.age=27
user.birthday=1991/02/01
user.address.province=陕西
user.address.city=西安
user.address.zone=新城区
user.skills[0]=Java
user.skills[1]=JavaScript
我们知道spring boot只会默认读取application.properties和application.yml中的配置,为了让spring boot读取到我们的配置,我们需要在绑定类上加一个@PropertySource注解,并指明我们自定义配置文件的位置。
@Component
@ConfigurationProperties(prefix = "user")
@PropertySource("classpath:config.properties") //读取自定义配置文件
public class User {
private String userName;
private int age;
private static Date birthday;
private Map<String, Object> address;
private String[] skills;
// 省略getter和setter方法
}
打印User对象可以看到自定义的配置文件已经正确读取到了。
User{userName='李四', age=27, birthday=Fri Feb 01 00:00:00 CST 1991, address={city=西安, zone=新城区, province=陕西}, skills=[Java, JavaScript]}
注意:如果要使用自定义配置文件,必须使用.properties文件格式,目前(2.1.2版本)@PropertySource还不支持读取.yml格式的自定义配置文件。
我们在实际工作中,会存在很多套环境,例如开发环境、测试环境、生产环境。程序在不同的环境下可能会有不同的配置,例如数据库的连接、日志的级别等等。
使用Spring Boot的Profile可以实现多场景下的配置切换,方便开发中进行测试和部署生产环境。 下面就大致介绍一下怎么使用profile配置不同环境的配置文件。
使用properties文件进行多个环境的配置,创建若干个application-{profile}.properties文件用于存放不同环境特有的配置,将与环境无关的配置存放在application.properties文件中。application.properties文件中通过spring.profiles.active=xxx
指定加载不同环境的配置。如果不指定,则默认加载application.properties的配置,不会加载带有profile的配置。
以配置端口号为例,假设我们在开发环境需要使用8081端口,生产环境需要使用8082端口,我们先出分别为开发环境和生产环境创建application-dev.properties和application-pro.properties文件。
在application-dev.properties中使用server.port=8081
设定端口号为8081,同理,在application-pro.properties中设置端口号为8082。需要切换端口时,只需要在application.properties中指定我们需要使用的配置文件即可:
spring.profiles.active=dev
使用yml文件配置多套环境的原理与properties相同,只是我们不需要在建多个配置文件,可以在application.yml配置文件中进行配置。
server:
port: 8081
spring:
profiles:
active: pro
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
spring:
profiles: pro
在yml文件中,我们使用---
来分隔不同环境的配置。当然,如果一个配置文件中写的内容太多,不利于我们后期的维护,我们也可以像properties文件一样,写多个yml,也按照application-{profile}.yml来命名,并且在application.yml中指定使用哪个配置文件即可。
在spring boot时,我们一般是将项目打成jar包部署到服务器上,启动时我们只要加上一行--spring.profiles.active=xxx
命令,就可以控制我们使用哪个环境的配置,非常方便。完整命令如下:
java -jar xxx.jar --spring.profiles.active=dev 表示使用开发环境的配置
java -jar xxx.jar --spring.profiles.active=pro 表示使用生产环境的配置
spring boot默认可以读取application.properties/application.yml这两个核心配置文件。核心配置文件可以存在与以下四个地方
注意:如果application.yml和application.properties文件同时存在,他们之间也是互补的关系,但是application.properties的优先级高于application.yml。
设想一个场景,我们的项目已经开发完成,并且打成jar包准备上线发布了,这时由于一些原因,之前的某些配置需要修改。按常规的做法,我们要去代码中改好后,重新打jar包,然后再部署。这样就显得非常繁琐,spring boot为我们提供了一些办法,可以使我们不修改原有代码的同时,更改配置。
如果我们需要修改的配置很少,可以通过命令行参数的方式。上文已经提过,参考3.3使用命令行切换环境。如果需要输入多个命令,中间用空格隔开。
如果我们需要修改的配置很多,用命令行参数修改明显是不好的。这时我们可以将所有需要修改的配置放到一个外部配置文件中。然后在启动项目时,通过
--spring.config.location=D:/xxx.application
这个命令来加载外部配置文件。
上面我们提到了spring boot支持的很多种配置方法。如果同一个配置出现在多个地方,优先级高的配置会覆盖优先级低的配置。现在来总结一下这些常用配置方式的优先级。
在spring boot中,8种基本数据类型,String,Date都是简单类型。 ↩︎
这段配置与1.2中的.yml的配置完全等价,可以看到明显使用.yml来写简洁了很多,这也是为什么推荐大家使用.yml来写配置文件的原因。 ↩︎