上一篇 Spring Boot 之 Configuration 了解了自动配置的基本原理。默认配置可以满足很多场景,但实际项目中还是会修改端口、数据源等配置,而且开发、测试和生产环境的配置通常也不一样。

Spring Boot 支持命令行参数、Java 系统属性、环境变量、JNDI 和配置文件等多种外置配置方式。先用修改 Tomcat 监听端口做个简单测试。

启动项目时增加命令行参数:

java -jar target/spring-boot-hello-1.0-SNAPSHOT.jar --server.port=8081

启动日志中可以看到端口已经变成 8081:

Tomcat started on port(s): 8081 (http)

最常用的方式还是配置文件。在 src/main/resources 下创建 application.yml:

server:
  port: 9090

如果仍然带着前面的 --server.port=8081 启动,监听端口还是 8081。删除命令行参数后再次启动,端口才会变成 9090。这是因为命令行参数的优先级高于配置文件。

配置优先级

同一个配置项出现在多个位置时,优先级高的值会覆盖优先级低的值。Spring Boot 1.5.4 中,主要顺序由高到低如下:

  1. Devtools 用户目录下的全局配置
  2. 测试中的 @TestPropertySource
  3. @SpringBootTest 的 properties 属性
  4. 命令行参数
  5. SPRING_APPLICATION_JSON
  6. ServletConfig 初始化参数
  7. ServletContext 初始化参数
  8. java:comp/env 中的 JNDI 属性
  9. Java 系统属性
  10. 操作系统环境变量
  11. random.* 随机属性
  12. Jar 包外部的 application-{profile}.properties 或 YAML 文件
  13. Jar 包内部的 application-{profile}.properties 或 YAML 文件
  14. Jar 包外部的 application.properties 或 YAML 文件
  15. Jar 包内部的 application.properties 或 YAML 文件
  16. @Configuration 类上的 @PropertySource
  17. SpringApplication.setDefaultProperties() 指定的默认属性

平时开发主要会接触命令行参数、环境变量和配置文件。临时覆盖某个配置时可以使用命令行参数,固定配置则放在配置文件中。

application.properties 和 application.yml 默认可以放在以下四个位置,顺序同样由高到低:

  1. 应用运行目录下的 /config 子目录
  2. 应用运行目录
  3. Classpath 下的 /config 包
  4. Classpath 根目录

例如,运行目录的 config/application.yml 会覆盖 Jar 包内部 application.yml 中的同名配置。

使用 Profile

程序部署到不同环境时通常使用不同配置。例如开发环境关闭 Thymeleaf 缓存,测试环境和生产环境使用不同的数据源。

在一个 YAML 文件中,可以使用三个减号分隔不同环境的配置,再通过 spring.profiles 指定环境名称。下面的 server.port 没有指定 Profile,所以在所有环境中都会生效:

server:
  port: 9090

---
spring:
  profiles: development
  thymeleaf:
    cache: false

---
spring:
  profiles: production
  thymeleaf:
    cache: true

配置项较多时,把多个环境都放在一个文件里不太容易维护。也可以分别创建 application-development.yml 和 application-production.yml,文件名中的 development、production 就是 Profile 名称,文件内部不需要再声明 spring.profiles。

application-development.yml:

spring:
  thymeleaf:
    cache: false

application-production.yml:

spring:
  thymeleaf:
    cache: true

除了配置文件,还可以直接在配置类上使用 @Profile:

@Configuration
@Profile("production")
public class ProductionConfiguration {
    // ...
}

配置项通常放在 application-{profile}.yml 中更直观,@Profile 更适合控制某组 Bean 是否加载。

最后激活开发环境。在 application.yml 中增加:

spring:
  profiles:
    active: development

也可以在启动时指定:

java -jar target/spring-boot-hello-1.0-SNAPSHOT.jar \
  --spring.profiles.active=development

在 IDEA 中启动项目,修改 Thymeleaf 模板后执行一次 Build Project(Ctrl + F9),开发环境关闭缓存时再次访问就能看到修改;切换到 production 后模板缓存开启,需要重启应用才能生效。

外置配置解决的是同一份程序在不同环境下使用不同参数的问题,Profile 则把一组相关配置组织起来。完整的优先级和 Profile 规则可以对照 Spring Boot 1.5.4 外置配置文档。

最后修改:2017 年 08 月 29 日
如果觉得我的文章对你有用,请随意赞赏