properties我用了好多年,你卻讓我用yml,這是什麼鬼 —— Java面試必修
引言
上一篇介紹了Spring Boot的輕松入門項目建構,對Spring Boot的特性有了初步了解。但如果要想玩得很熟練的話就請看接下來的文章,這樣有助于後續我們快速的建構企業級應用,打怪咱得先熟悉地圖對吧
配置詳解
工具
- SpringBoot版本:2.0.4
- 開發工具:IDEA 2018
- Maven:3.3 9
- JDK:1.8
配置檔案類型
本文主要講解SpringBoot的配置檔案,常用的配置檔案類型有如下兩種,分為properties、yml,先甭管什麼檔案,SpringBoot都能正确加載讀取裡面的參數,配置檔案的路徑在:
src/main/resources
下
- properties結尾的檔案,這種想必大家都比較熟悉了,比如:
,或jdbc.properties
。log4j.properties
- yml結尾的檔案,YAML(Yet Another Markup Language)結構化的資料配置檔案,諧音(亞妹襖),ML和XML同音
動手嘗試
- 2種配置均可讀取的固定代碼,配置請往下看
@RestController
@SpringBootApplication
public class DemoApplication {
@Value("${com.demo.name}")
private String name;
@Value("${com.demo.url}")
private String url;
@RequestMapping("/index")
public String index(){
return "name:" + name +",url:" + url ;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
-
,先來個簡單的配置,代碼@Value注解直接綁定application.properties
com.demo.name="JAVA面試必修"
com.demo.url="www.itmsbx.com"
結果:成功傳回name:“Java面試必修”,url:"www.itmsbx.com"
- 換成
則内容如下application.yml
#注釋
com.demo.name: Java面試必修
com.demo.url: www.itmsbx.com
---- yml上下任選一種即可
com.demo:
name: Java面試必修
url: www.itmsbx.com
結果:name:Java面試必修,url:www.itmsbx.com
Spring架構提供兩個便利的類用于加載YAML文檔,
YamlPropertiesFactoryBean
會将YAML加載為
Properties
,
YamlMapFactoryBean
會将YAML加載為Map,後續講解
Bean對象綁定
認識了配置檔案後,我們發現yml中的資料綁定還挺好用的。但是問題來了,一個個綁定到屬性字段上太累,能換成對象,咱們就使用對象對吧,那也是可以的,我們建一個DemoBean.java類。
- Bean類中使用注解
來指明綁定配置檔案中哪個變量@ConfigurationProperties(prefix = “com.demo”)
@ConfigurationProperties(prefix = "com.demo")
public class DemoBean {
//省略getter和setter
private String name;
private String url;
}
- Controller中使用注解
來綁定實體類,并使用Autowired在成員變量處注入即可@EnableConfigurationProperties({DemoBean.class})
@RestController
@SpringBootApplication
@EnableConfigurationProperties({DemoBean.class})
public class DemoApplication {
@Autowired
DemoBean demoBean;
@RequestMapping("/index")
public String index(){
return "name:" + demoBean.getName() + ",url:" + demoBean.getUrl();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
結果:name:Java面試必修,url:www.itmsbx.com
參數與參數間的引用
# 注釋
com.demo:
name: Java面試必修
url: www.itmsbx.com
scope: ${com.demo.name}的網址是${com.demo.url}
這樣我們直接使用scope屬性就能看到效果了,注:properties和yml除了書寫格式上的差異外,使用方式基本類似,是以後續我們的講解中都建議使用yml檔案
随機參數生成
通常是用這些随機數我們得寫一段代碼生成,現在配置檔案中${random} 可以用來生成各種不同類型的随機值,進而簡化了代碼生成的麻煩,例如 生成 int 值、long 值或者 string 字元串
demo.secret: ${random.value}
demo.number: ${random.int}
demo.bignumber: ${random.long}
demo.uuid: ${random.uuid}
demo.number.less.than.ten: ${random.int(10)}
demo.number.in.range: ${random.int[1024,65536]}
大家仔細思考下,${}很熟悉,我們用自己的變量也是${}包含起來的對不對,那其實這是SpringBoot已經封裝好的配置變量啦,類似于jsp中的隐式對象request一樣,拿來即用
指令行參數配置
Spring Boot是基于jar包運作的,打成jar包的程式可以直接通過下面指令運作:
java -jar demo-0.0.1-SNAPSHOT.jar
可以使用下指令修改tomcat端口号:
java -jar demo-0.0.1-SNAPSHOT.jar --server.port=9090
等價于在yml中配置server.port: 9090,或properties中配置server.port=9090
java -jar demo-0.0.1-SNAPSHOT.jar
控制台輸出
$ java -jar myapp.jar --debug
但前提是你需要在yml或properties中指明 debug=true
設定Spring profiles參數啟動
$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
指令啟動參數用 --xxx=xxx 的形式傳遞。指令行參數在demo.jar的後面,如果你擔心指令行有風險,則可以使用
SpringApplication.setAddCommandLineProperties(false)
禁用它。
運作或系統參數擷取
Spring Boot應用程式有多種設定途徑,Spring Boot能從多重屬性源獲得屬性,包括如下幾種(優先級從高到低排序):
- 指令行參數
-
中的屬性(環境變量或系統屬性中的内聯JSON嵌入)。SPRING_APPLICATION_JSON
-
初始化參數。ServletConfig
-
初始化參數。ServletContext
- 來自
的JNDI屬性java:comp/env
- Java系統屬性(
)System.getProperties()
- 作業系統環境變量
-
配置的random.*屬性值,比如${random.long}RandomValuePropertySource
- jar包外部的
或application-{profile}.properties
配置檔案application.yml(帶spring.profile)
- jar包内部的
或application-{profile}.properties
配置檔案application.yml(帶spring.profile)
- jar包外部的
或application.properties
配置檔案application.yml(不帶spring.profile)
- jar包内部的
或application.properties
配置檔案application.yml(不帶spring.profile)
-
注解類上的@Configuration
@PropertySource
- 通過
指定的預設屬性SpringApplication.setDefaultProperties
任何在高優先級屬性源裡設定的屬性都會覆寫低優先級的相同屬性,列如我們上面提到的指令行屬性就覆寫了
application.properties
的屬性。
配置檔案的優先級
application.properties
和
application.yml
檔案可以放在以下四個位置:
- 外置,在相對于應用程式運作目錄的/congfig子目錄裡。
- 外置,在應用程式運作的目錄裡
- 内置,在config包内
- 内置,在Classpath根目錄
同樣,這個清單按照優先級排序,也就是說,
src/main/resources/config/application.properties
覆寫
src/main/resources/application.properties
中相同的屬性,如圖:

此外,如果你在相同優先級位置同時有
application.properties
和
application.yml
,那麼
application.properties
裡的屬性裡面的屬性就會覆寫
application.yml
使用自定義的配置檔案
對于同時加載多個properties配置檔案,
SpringBoot
有注解
@PropertySource
支援,而yml多配置檔案需要單獨用程式讀取,官方提供了
YamlPropertySourceLoader.java
類來支援,是以**
@PropertySource隻能支援properties配置檔案
**,如下:
@Configuration
@ConfigurationProperties(prefix = "com.custom")
@PropertySource("classpath:application-test.properties")
public class CustomBean {
//省略getter和setter
private String sex;
private String age;
private String desc;
}
若對于yml多配置檔案,建議寫到一個裡面,但如果分成多個環境加載不同配置,那接下來我們就講解下如何通過指令參數調用不同的yml
Profile-多環境配置
普通springmvc項目解決方案
在普通的springmvc的tomcat項目中,我們也可以指定JVM的運作參數,在啟動服務的時候通過System.getProperty(“JVM配置key”)擷取到這個參數,然後初始化不同的Properties檔案,操作如下:
<!-- 從properties檔案加載配置資訊 -->
<bean id="propertyPlaceholderConfigurer" class="com.xx.xx.common.spring.CustomizedPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- 此處配置檔案需要在tomcat運作參數中指定[develop|test|product]其中一個,若不指定,預設取develop -->
<value>classpath*:**/config/config-develop.properties</value>
<value>classpath*:**/config/config-test.properties</value>
<value>classpath*:**/config/config-product.properties</value>
</list>
</property>
<property name="configureClasses">
<list>
<value>com.xx.xx.common.util.Constants</value>
</list>
</property>
</bean>
tomcat 中 catalina.bat(.sh中不用“set”) 添加JAVA_OPS。通過設定active選擇不同配置檔案
set JAVA_OPTS="-Dspring.profiles.active=test"
上述的
CustomizedPropertyPlaceholderConfigurer
類實作了
PropertyPlaceholderConfigurer
,在初始化的時候通過擷取JVM的profile進行不同的properties選取
SpringBoot解決方案
對于多環境的配置,各種項目建構工具或是架構的基本思路是一緻的,通過配置多份不同環境的配置檔案,再通過打包指令指定需要打包的内容之後進行區分打包,Spring Boot也不例外,或者說更加簡單。
在Spring Boot中多環境配置檔案名需要滿足
application-{profile}.yml
的格式,其中{profile}對應你的環境辨別,如下圖:
至于哪個具體的配置檔案會被加載,需要在application.yml檔案中通過spring.profiles.active屬性來設定,其值對應{profile}值。如:
spring.profiles.active=prod
就會加載
application-prod.yml
配置檔案内容
application.yml内容如下
spring.profiles.active: dev
application-dev.yml内容如下
server:
port: 1000
application-prod.yml内容如下
server:
port: 1001
啟動的時候帶上參數:
java -jar xxx.jar --spring.profiles.active=dev
,就會發現啟動的端口不一樣,說明配置檔案生效了
代碼使用profile
除了可以用profile的配置檔案來分區配置我們的環境變量,在代碼裡,我們還可以直接用@Profile注解來進行配置,例如資料庫配置,這裡我們先定義一個接口
public interface DBConnector { public void dbConfig(); }
分别定義倆個實作類來實作它
/**
* 開發資料庫
*/
@Component
@Profile("devdb")
public class DevDBConnector implements DBConnector {
@Override
public void dbConfig() {
System.out.println("devdb");
}
}
/**
* 生産資料庫
*/
@Component
@Profile("prodb")
public class ProDBConnector implements DBConnector {
@Override
public void dbConfig() {
System.out.println("prodb");
}
}
通過在配置檔案激活具體使用哪個實作類
spring.profiles.active=prodb
然後具體調用如下
@RestController
@RequestMapping("/call")
public class CallController {
@Autowired DBConnector connector ;
@RequestMapping(value = {"/",""})
public String hellYml(){
connector.dbConfig(); //最終列印prodb
return "Hello yml";
}
}
總結
SpringBoot的配置檔案給我們帶來了極大的便利,properties和yml兩者各選一個吧,不過我更傾向于yml,其格式化的配置看起來很舒服,有點類似于json格式,更多的屬性及配置後續在使用的過程中慢慢講解。
作者有話說:喜歡的話就請移步Java面試必修網,請自備水,更多幹、幹、幹貨等着你