SpringBoot 是原生支持配置遷移的,可是官方文檔沒有看到這方面描述,在源碼中才看到此模塊,spring-boot-properties-migrator
,幸好我沒有跳過。看到這篇文章的各位,可算是撿到寶了,相信你繼續往下看下去,定會忍不住點贊、收藏、關注。java
先放個效果吸引你 :)git
從 SpringBoot 2.0.0
版本開始,配置服務上下文,不支持 server.context-path
,而須要server.servlet.context-path
配置。可是隻要加上如下一個官方依賴,就能夠支持使用 server.context-path
web
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-properties-migrator</artifactId> </dependency>
server.context-path
所對應的屬性 ServerProperties#contextPath
在 Java 代碼中已不存在,server.servlet.context-path 所對應的的屬性在內部類 Servlet
中才有,爲什麼加了此依賴就能實現如此神奇的效果呢。spring
SpringBoot 對外部化配置原生支持遷移功能,所謂遷移,具體是指對應配置的屬性名變更,仍可使用原來的屬性名配置。
在 spring-configuration-metadata.json
的信息能夠輔助 IDE 進行配置的提示,也能夠用來完成配置的遷移。很是的簡單。json
相關文章: SpringBoot 配置提示功能app
經過閱讀代碼,得到如下信息:spring-boot
ApplicationPreparedEvent
事件(即:環境已準備事件),執行如下操做並收集信息classpath*:/META-INF/spring-configuration-metadata.json
中載入全部配置environment
中過濾出提示的配置(知足條件:1. deprecation 不爲 null,且提示 level
爲 error)replacement
的 key,並將其屬性源命名爲:migrate-原名新屬性源
添加到 environment 中,且添加
到原屬性源以前
(優先級高)。根據元數據中定義的 type
判斷學習
environment
中取配置信息,理論上支持 SpringBoot 全部的配置方式。兼容效果:
棄用
屬性(若是還存在)與替換
後的屬性都會使用配置文件中的棄用的屬性名所對應的的值。this
使用配置遷移功能,須要如下步驟:spa
spring-boot-properties-migrator
(支持配置遷移)、spring-boot-configuration-processor
(生成元數據文件,若是已經有完整的,不須要此依賴)spring-configuration-metadata.json
中棄用屬性名對應的 properties 中必須有 deprecation
(在additional-spring-configuration-metadata.json
中添加,相關文章: SpringBoot 配置提示功能)deprecation
中需指定 level
爲 errordeprecation
中需指定 replacement
replacement
對應的屬性配置在元數據文件中存在,與棄用屬性兼容再說回一開始展現的配置上下文示例。
# 配置 servlet 服務上下文 server: context-path: test
從 SpringBoot 2.0.0
版本開始,以上配置不支持,點到配置元數據文件中(spring-configuration-metadata.json
),發現以下信息:
{ "properties": [ { "name": "server.context-path", "type": "java.lang.String", "description": "Context path of the application.", "deprecated": true, "deprecation": { "level": "error", "replacement": "server.servlet.context-path" } }, { "name": "server.servlet.context-path", "type": "java.lang.String", "description": "Context path of the application.", "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Servlet" }
替換屬性名爲:server.servlet.context-path
,此屬性在org.springframework.boot.autoconfigure.web.ServerProperties
中,且在類中能夠發現,server.context-path
所對應的屬性 ServerProperties#contextPath
在代碼中已不存在,而是在內部類 Servlet
中有,也就是對應 server.servlet.context-path 的屬性纔有。
可是其知足配置兼容的條件,爲何實際上使用卻好像不兼容呢?
實際上是由於沒有引入依賴,當引入依賴,就會發現此方式配置能夠起做用。
代碼示例見 https://gitee.com/lw888/spring-boot-source-example/tree/master/properties-migrator
一、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-properties-migrator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
二、Java 配置
此處故意保留棄用屬性
@Data @Configuration @ConfigurationProperties(prefix = "my") public class MyProperties { /** the project name */ private String name; private App app; @Data public static class App { private String name; } }
三、元數據配置,spring-configuration-metadata.json 由程序生成,自定義配置放在 additional-spring-configuration-metadata.json
中
{ "properties": [ { "name": "my.name", "type": "java.lang.String", "description": "the project name.", "deprecation": { "reason": "test the properties-migrator feature.", "replacement": "my.app.name", "level": "error" } }, { "name": "my.app.name", "type": "java.lang.String", "sourceType": "com.lw.properties.migrator.config.MyProperties$App", "description": "the project name." } ] }
四、在 properties 或 yml 文件中配置
my: name: lw app: name: app
五、打印配置信息
@Slf4j @SpringBootApplication public class PropertiesMigratorApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(PropertiesMigratorApplication.class, args); MyProperties myProperties = context.getBean(MyProperties.class); log.info("myProperties.name:{}", myProperties.getName()); log.info( "myProperties$app.name:{}", Optional.ofNullable(myProperties.getApp()).orElse(new App()).getName()); } }
六、打印信息以下:
2019-11-23 21:42:09.580 WARN 109408 --- [ main] o.s.b.c.p.m.PropertiesMigrationListener :
The use of configuration keys that have been renamed was found in the environment:
Property source 'applicationConfig: [classpath:/application.yml]':
Key: my.name
Line: 4
Replacement: my.app.name
Key: server.context-path
Line: 2
Replacement: server.servlet.context-path
Each configuration key has been temporarily mapped to its replacement for your convenience. To silence this warning, please update your configuration to use the new keys.
......... myProperties.name:lw
......... myProperties\(app.name:lw ......... serverProperties\)servlet.contextPath:/app
七、效果解析
在 yml 中棄用屬性名優先級更高,棄用屬性與新屬性都使用此棄用屬性名對應的值。
SpringBoot 2.2.1.RELEASE
源碼
公衆號:逸飛兮(專一於 Java 領域知識的深刻學習,從源碼到原理,系統有序的學習)