javascript
springboot 获取application参数_LOOK ! SpringBoot的外部化配置最全解析
本篇要點
- 介紹各種配置方式的優先級。
- 介紹各種外部化配置方式。
- 介紹yaml的格式及原理。
- 介紹如何綁定并測試類型安全的屬性配置。
- 介紹@ConfigurationProperties與@Value的區別。
一、SpringBoot官方文檔對于外部化配置的介紹及作用順序
SpringBoot支持多種外部化配置,以便于開發者能夠在不同的環境下,使用同一套應用程序代碼。外部化配置的方式有多種:properties文件,yaml文件,Environment變量已經命令行參數等等。
外部化配置的屬性值可以通過@Value注解自動注入,亦可以通過Spring的Environment抽象訪問,也可以通過@ConfigurationProperties注解綁定到結構化對象上。
SpringBoot支持很多種的外部化配置,待會我們會介紹到。在這之前,我們必須要知道如果多種配置同時出現,一定是按照特定的順序生效的。規則如下:
這里列表按組優先級排序,也就是說, 任何在高優先級屬性源里設置的屬性都會覆蓋低優先級的相同屬性 ,列如我們上面提到的命令行屬性就覆蓋了application.properties的屬性。
舉個例子吧:
如果在application.properties中設置 name=天喬巴夏 ,此時我用命令行設置 java -jar hyh.jar --author.name=summerday ,最終的name值將會是summerday,因為命令行屬性優先級更高。
二、各種外部化配置舉例
1、隨機值配置
配置文件中 ${random} 可以用來生成各種不同類型的隨機值,從而簡化了代碼生成的麻煩,例如 生成 int 值、long 值或者 string 字符串。原理在于, RandomValuePropertySource類重寫了 getProperty 方法,判斷以 random. 為前綴之后,進行了適當的處理。
my.secret=${random.value} my.number=${random.int} my.bignumber=${random.long} my.uuid=${random.uuid} my.lessThanTen=${random.int(10)} my.inRange=${random.int[1024,65536]}2、命令行參數配置
默認情況下,SpringApplication將所有的命令行選項參數【以 -- 開頭的參數,如 --server.port=9000 】轉換為屬性,并將它們加入SpringEnvironment中,命令行屬性的配置始終優先于其他的屬性配置。
如果你不希望將命令行屬性添加到Environment中,可以使用SpringApplication.setAddCommandLineProperties(false) 禁用它。
$ java -jar app.jar --debug=true #開啟debug模式,這個在application.properties文件中定義debug=true是一樣的3、屬性文件配置
屬性文件配置這一部分是我們比較熟悉的了,我們在快速創建SpringBoot項目的時候,默認會在resources目錄下生成一個application.properties文件。SpringApplication都會從配置文件加載配置的屬性,并最終加入到Spring的Environment中。除了resources目錄下,還有其他路徑,SpringBoot默認是支持存放配置文件的。
/config /config以上四個,優先級從上往下依次降低,也就是說,如果同時出現,上面配置的屬性將會覆蓋下面的。
關于配置文件,properties和yaml文件都能夠滿足配置的需求。
當然,這些配置都是靈活的,如果你不喜歡默認的配置文件命名或者默認的路徑,你都可以進行配置:
$ java -jar myproject.jar --spring.config.name=myproject $ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties4、指定profile屬性
通常情況下,我們開發的應用程序需要部署到不同的環境下,屬性的配置自然也需要不同。如果每次在發布的時候替換配置文件,過于麻煩。SpringBoot的多環境配置為此提供了便利。具體做法如下:
我們之前在介紹各種配置的優先級的時候說過, application-{profile}.properties或者application-{profile}.yml文件 的優先級高于 application.properties或application.yml 配置,這里的profile就是我們定義的環境標識:
我們在resource目錄下創建三個文件:
- application.properties:默認的配置,default。
- application-dev.properties:開發環境,dev。
- application-prod.properties:生產環境,prod。
我們可以通過指定 spring.profiles.active 屬性來激活對應的配置環境:
spring.profiles.active=dev或使用命令行參數的配置形式:
$ java -jar hyh.jar --spring.profiles.active=dev如果沒有profile指定的文件于profile指定的文件的配置屬性同時定義,那么指定profile的配置優先。
5、使用占位符
在使用application.properties中的值的時候,他們會從Environment中獲取值,那就意味著,可以引用之前定義過的值,比如引用系統屬性。具體做法如下:
name=天喬巴夏 description=${name} is my name6、加密屬性
Spring Boot不提供對加密屬性值的任何內置支持,但是,它提供了 修改Spring環境中的值所必需的掛鉤點。我們可以通過實現EnvironmentPostProcessor接口在應用程序啟動之前操縱Environment。
可以參考 howto.html ,查看具體使用方法。
7、使用YAML代替properties
YAML是JSON的超集,是一種 指定層次結構配置數據的便捷格式 ,我們以properties文件對比一下就知道了:
#properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=123456my.servers[0]=www.hyh.com my.servers[1]=www.yhy.com # yml spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8username: rootpassword: 123456 my:server:- www.hyh.com- www.yhy.com只要在類路徑上具有SnakeYAML庫,SpringApplication類就會自動支持YAML作為屬性配置的方式。SpringBoot項目中的 spring-boot-starter 已經提供了相關類庫: org.yaml.snakeyaml,因此SpringBoot天然支持這種方式配置。
關于yaml文件的格式,可以參考官方文檔: Using YAML Instead of Properties
8、類型安全的屬性配置
上面說到通過 @Value("${property}") 注解來注入配置有時會比較麻煩,特別是當多個屬性本質上具有層次結構的時候。SpringBoot提供了一種解決方案: 讓強類型的bean管理和驗證你的配置 。
直接來看具體的使用叭:
@ConfigurationPropertie定義一個綁定配置的JavaBean
這種方式依賴于默認的空構造函數,通過getter和setter方法賦值,因此getter和setter方法是必要的,且不支持靜態屬性的綁定。
如果嵌套pojo屬性已經被初始化值: private final Security security = new Security(); 可以不需要setter方法。如果希望綁定器使用其默認構造函數動態創建實例,則需要setter。
如果沒有配置Security實例屬性,那么最后結果:Security=null。如果我們想讓Security={username=null,password=null,roles=[USER]},可以在Security上加上@DefaultValue。public AcmeProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security)
通過@EnableConfigurationProperties注冊
已經定義好了JavaBean,并與配置屬性綁定完成,接著需要注冊這些bean。我們通常用的@Component或@Bean,@Import加載bean的方式在這里是不可取的,SpringBoot提供了解決方案: 使用@EnableConfigurationProperties ,我們既可以一一指定配置的類,也可以按照組件掃描的方式進行配置。
@SpringBootApplication @EnableConfigurationProperties({HyhConfigurationProperties.class, MyProperties.class,AcmeProperties.class}) public class SpringBootProfileApplication { } @SpringBootApplication @ConfigurationPropertiesScan({"com.hyh.config"}) public class SpringBootProfileApplication { }配置yaml文件
acme:remote-address: 192.168.1.1security:username: adminroles:- USER- ADMIN注入properties,測試
@Configuration public class Application implements CommandLineRunner {@Autowiredprivate AcmeProperties acmeProperties;@Overridepublic void run(String... args) throws Exception {System.out.println(acmeProperties);} } //輸出: AcmeProperties(security=AcmeProperties.Security(username=admin, password=null, roles=[USER, ADMIN]), enabled=false, remoteAddress=/192.168.1.1)寬松綁定
SpringBoot采用寬松的規則進行Environment和@ConfigurationProperties標注bean的匹配。如:
@ConfigurationProperties(prefix="acme.my-project.person") public class OwnerProperties {private String firstName;public String getFirstName() {return this.firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}}下面表格中的屬性名都可以匹配:
@ConfigurationProperties注解中的prefix值必須是kebab case形式的,以 - 為分割符。
Spring官方建議,屬性盡可能以lower-case kebab的形式:my.property-name=acme
Map如何綁定
綁定到Map屬性時,如果key包含 小寫字母數字字符或-以外的任何其他字符 ,則需要使用方括號包圍key,以便保留原始值。 如果鍵沒有被 [] 包圍,則所有非字母數字或-的字符都將被刪除。如下:
hyh:username: 天喬巴夏password: 123456map:"[/key1]": value1 #用引號包圍[],用[]包圍key/key3: value3key-4: value4key/5: value5 # 結果:"map":{/key1=value1,key5=value5, key-4=value4, key3=value3}環境變量如何綁定
遵循三條原則:
如: spring.main.log-startup-info 轉為: SPRING_MAIN_LOGSTARTUPINFO , my.acme[0].other 轉為 MY_ACME_0_OTHER 。
9、復雜類型
之前介紹yml文件,介紹了單純的數組形式或值的綁定,SpringBoot還支持復雜類型的綁定。
merge:list:- name: 天喬巴夏desc: 帥啊- name: tqbxdesc: 很帥啊map:key1:name: summerdaydesc: handsome!key2:name: summer @ToString @ConfigurationProperties(prefix = "merge") public class MergeProperties {private final List<User> list = new ArrayList<>();private final Map<String,User> map = new HashMap<>();public List<User> getList() {return list;}public Map<String, User> getMap() {return map;} }最后輸出:
MergeProperties(list=[User(name=天喬巴夏, desc=帥啊), User(name=tqbx, desc=很帥啊)], map={key1=User(name=summerday, desc=handsome!), key2=User(name=summer, desc=null)}a )10、參數校驗
對@ConfigurationProperties類使用Spring的 @Valid 注解時,Spring Boot就會嘗試對其進行驗證。
你可以直接在配置類上使用JSR-303 javax.validation 約束注解。這個做法的前提是,你的類路徑上有兼容的JSR-303實現:
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.0.18.Final</version></dependency>然后將約束注解加到字段上,如下:
@Data @Validated @ConfigurationProperties(prefix = "validate") public class ValidateProperties {@NotNullprivate String name;@Validprivate final SubProperties subProperties = new SubProperties();@Datapublic static class SubProperties {@Min(value = 10,message = "年齡最小為10")public Integer age;} }配置如下:
validate:name: hyhsub-properties:age: 5結果如下:
Description:Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'validate' to com.hyh.config.ValidateProperties failed:Property: validate.sub-properties.ageValue: 5Origin: class path resource [application.yml]:47:10Reason: 年齡最小為10Action: Update your application's configuration三、@ConfigurationProperties與@Value的區別
@Value注解是一個核心容器功能,它沒有提供和type-safe配置屬性相關的功能,下面這個表格總結了兩者分別支持的功能:
官方建議:
- 如果你為自己的組件定義了一套配置,建議使用@ConfigurationProperties和POJO綁定,這樣做能夠提供結構化且類型安全的對象。
- 如果硬要使用@Value,建議使用kebab-case形式,如@Value(" ${demo.item-price}")
總結
以上是生活随笔為你收集整理的springboot 获取application参数_LOOK ! SpringBoot的外部化配置最全解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女生学python可以做什么_学 Pyt
- 下一篇: javadrawstring设置字符大小