概览
Spring Boot设计的核心理念就是对配置信息的管理采用约定优于配置,基于此理念我们开发过程中会大量的采用Spring Boot提供的默认项,相比传统的Spring Framework框架大大降低的配置项的数量,本文将详细介绍基于Spring Boot 2.x的配置体系,包括配置文件的介绍、如何自定义配置项、如何获取配置文件中的配置项、以及如何通过Profile实现特定的环境使用特定的配置。
配置文件说明
Spring Boot 使用了一个全局的配置文件application.properties,该文件放置在src/main/resources目录下,同时还支持yaml语言的配置文件,对应的配置文件是application.yml。
yaml是强调以数据为中心,而不是以标记语言为重点,可以简单表达清单、散列表,标量等数据形态,特别适合用来表达或编辑数据结构、各种配置文件。
application配置文件有2个作用,第一可以对Spring Boot默认的配置项进行修改,第二可以自定义配置项。
例如,Spring Boot内嵌的Tomcat的默认端口8080修改成9000,将上下文默认路径“/”修改为"/configuration",可以在application.properties中添加:
server.port=9000
server.servlet.context-path=/configuration
或在application.yml中添加:
server:
port: 9000
servlet:
context-path: /configuration
从上面的配置可以看出,在Spring Boot中,context-path、contextPath、CONTEXT_PATH形式其实是通用的。采用yaml的配置功能更加强大,并且简洁清晰,在日常开发中,推荐使用yaml文件来配置。没有特殊情况说明,下文中的所涉及的配置项都会以yaml格式来说明。
如何自定义配置?
Spring Boot 内置的默认配置全面且强大,但不能够完全我们业务开发的需要,例如,我们对接微信公众号开发的过程中,需要配置微信公众号的appId和appSecret,这些配置项我们一般会配置到application.yml中。
创建自定义配置项
创建普通的配置项
创建自定义的配置项和上面修改Spring Boot的默认配置项的方式是一样的,例如,我们创建微信公众号的appId和appSecret两个配置项,在application.yml中添加:
wx: appId: 123 appSecret: xyz
使用占位符获取系统配置信息
想要获取系统配置信息,我们可以使用${},如下获取jdk版本号
java: verison: ${java.version}
同样我们可以使用相同的方式,通过${} 占位符引用配置文件中的其他配置项内容,如下
system: name: configuration system: domain=health description: The system ${name} is used for ${domain}.
使用占位符获取maven变量
再来看一种场景,假设我们使用 Maven 来构建应用程序,那么可以按如下所示的配置项来动态获取与系统构建过程相关的信息:
info: app: encoding: @project.build.sourceEncoding@ java: source: @java.version@ target: @java.version@
使用占位符获取随机值
有时候我们需要在项目中使用一些全局随机值,要求项目启动时自动生成,Spring Boot支持在properties、yaml配置文件中使用类似${random.int}的表达式来声明随机配置的参数:
random: #32位随机md5字符串 value: ${random.value} #随机int int: ${random.int} #随机long long: ${random.long} #随机uuid uuid: ${random.uuid} #随机10以内int int10: ${random.int[10]} #随机取1024和65535间的int intbetween1024and65535: ${random.int[1024,65535]}
使用@value注解读取配置项
在程序开发的过程中,如何在代码中使用配置文件中的配置项,我们可以通过@value注入值,如下在controller中获取微信公众号的appId和appSecret:
@RestController
public class ConfigurationController {
@Value("${wx.appId}")
private String appId;
@Value("${wx.appSecret}")
private String appSecret;
@RequestMapping("/wx-info")
public String wxInfo() {
return "appId: " + appId + ",appSecret:" + appSecret;
}
}
这种方法会造成contrller有太多的配置项,针对这种情况我们可以构建一个配置类WxConfig,如下:
@Component
@Data
public class WxConfig {
@Value("${wx.appId}")
private String appId;
@Value("${wx.appSecret}")
private String appSecret;
}
@RestController
public class WxConfigController {
@Resource
private WxConfig wxConfig;
@RequestMapping("/wx-config")
public String wxConfig() {
return "appId: " + wxConfig.getAppId() + ",appSecret:" + wxConfig.getAppSecret();
}
}
使用@ConfigurationProperties注解批量读取配置项
相较 @Value 注解,更为现代的一种做法是使用 @ConfigurationProperties 注解。在使用该注解时,我们通常会设置一个“prefix”属性用来指定配置项的前缀,如下所示:
@Component
@Data
@ConfigurationProperties(prefix = "wx")
public class WxConfig2 {
private String appId;
private String appSecret;
}
如何多环境配置?
通过上面的介绍,我们知道Spring Boot 默认的全局配置文件是application.yml,但是在实际的开发过程中,情况就比较复杂。多环境一般指的是开发环境、测试环境、生产环境等,不同的环境对应的配置项会有不用,如果发布环境的时候,去修改配置项,不仅会浪费大量时间而且还很容易配置出错。Spring Boot 提供Profile机制,Profile 本质上代表一种用于组织配置信息的维度,对不同环境提供不同配置功能,可以通过激活、指定参数方式快速切换环境。
配置文件和Profile
通过Profile来实现多环境的配置有2种方式,第一种多配置文件,第二种是yml多文档块。
- 多配置文件
通过这种方式来实现的多环境配置的话,配置文件如下:
/application.yml
/application-dev.yml
/application-test.yml
/application-prod.yml yml多文档块
如果你想把所有的 配置信息只保存在一个文件中而不是分散在多个配置文件中,Spring Boot也可以支持,需要做的事情只是对这些信息按 Profile 进行组织、分段,如下所示:
spring: profiles: dev #dev 环境相关配置信息 --- spring: profiles: test #test 环境相关配置信息 --- spring: profiles: prod #prod 环境相关配置信息 ---
尽管可以在同一个配置文件中,通过文档块的方式来配置,还是推荐你按多个配置文件的组织方法管理各个 Profile 配置信息,这样才不容易混淆和出错。
如何激活指定的Profile
我们可以在全局配置文件是application.yml,通过指定配置项来激活当前的Profile:
spring:
profiles: active: dev
还可以使用命令行的方式,在打包jar之后,我们可以直接在 java –jar 命令中添加“--spring.profiles.active”参数,如下所示:
java –jar configuration-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
这种实现方案在通过脚本进行自动化打包和部署的场景下非常有用。
代码控制和Profile
在Spring Boot中,Profie这个一概念的还可以动态的控制代码的执行流程,如下:
@Configuration
public class DataSourceConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
//创建 dev 环境下的 DataSource
}
@Bean
@Profile("test")
public DataSource devDataSource() {
//创建 test 环境下的 DataSource
}
@Bean()
@Profile("prod")
public DataSource prodDataSource(){
//创建 prod 环境下的 DataSource
}
}
可以看到,我们构建了一个 DataSourceConfig 配置类来专门管理各个环境所需的 DataSource。这里用@Profile注解来指定了不同的环境,执行创建DataSource的逻辑代码。
@Profile 注解的应用范围很广,我们可以将它添加到包含 @Configuration 和 @Component 注解的类及其方法,也就是说可以延伸到继承了 @Component 注解的 @Service、@Controller、@Repository 等各种注解中。
项目源码
github: https://github.com/dragon8844/springboot-learning/tree/main/configuration
最后说一句
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。
此外,关注公众号:黑色的灯塔,专注Java后端技术分享,涵盖Spring,Spring Boot,SpringCloud,Docker,Kubernetes中间件等技术。