微服務(wù) SpringBoot 2.0(二):配置文件解析

properties我用了好多年梳星,你卻讓我用yml跟匆,這是什么鬼 —— 知碼學(xué)院

引言

上一篇介紹了Spring Boot的輕松入門項目構(gòu)建异袄,對Spring Boot的特性有了初步了解。但如果要想玩得很熟練的話就請看接下來的文章玛臂,這樣有助于后續(xù)我們快速的構(gòu)建企業(yè)級應(yīng)用烤蜕,打怪咱得先熟悉地圖對吧

配置詳解

工具

  • SpringBoot版本:2.0.4
  • 開發(fā)工具:IDEA 2018
  • Maven:3.3 9
  • JDK:1.8

配置文件類型

本文主要講解SpringBoot的配置文件,常用的配置文件類型有如下兩種迹冤,分為properties讽营、yml,先甭管什么文件泡徙,SpringBoot都能正確加載讀取里面的參數(shù)橱鹏,配置文件的路徑在:src/main/resources

  1. properties結(jié)尾的文件,這種想必大家都比較熟悉了,比如:jdbc.properties莉兰,或log4j.properties挑围。
  2. yml結(jié)尾的文件,YAML(Yet Another Markup Language)結(jié)構(gòu)化的數(shù)據(jù)配置文件糖荒,諧音(亞妹襖)杉辙,ML和XML同音

動手嘗試

  1. 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);

    }
}
  1. application.properties奏瞬,先來個簡單的配置,代碼@Value注解直接綁定
com.demo.name="知碼學(xué)院"
com.demo.url="www.it235.com"
結(jié)果:成功返回name:“知碼學(xué)院”泉孩,url:"www.it235.com"

  1. 換成 application.yml 則內(nèi)容如下
#注釋
com.demo.name: 知碼學(xué)院
com.demo.url: www.it235.com

---- yml上下任選一種即可

com.demo:
  name: 知碼學(xué)院
  url: www.it235.com
結(jié)果:name:Java面試必修硼端,url:www.it235.com

Spring框架提供兩個便利的類用于加載YAML文檔,YamlPropertiesFactoryBean會將YAML加載為Properties寓搬,YamlMapFactoryBean會將YAML加載為Map珍昨,后續(xù)講解

Bean對象綁定

認識了配置文件后,我們發(fā)現(xiàn)yml中的數(shù)據(jù)綁定還挺好用的句喷。但是問題來了镣典,一個個綁定到屬性字段上太累,能換成對象唾琼,咱們就使用對象對吧兄春,那也是可以的,我們建一個DemoBean.java類锡溯。

  1. Bean類中使用注解 @ConfigurationProperties(prefix = “com.demo”)來指明綁定配置文件中哪個變量
@ConfigurationProperties(prefix = "com.demo")
public class DemoBean {

    //省略getter和setter
    private String name;
    private String url;

}

  1. Controller中使用注解@EnableConfigurationProperties({DemoBean.class})來綁定實體類赶舆,并使用Autowired在成員變量處注入即可
@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);

    }
}
結(jié)果:name:Java面試必修祭饭,url:www.it235.com

參數(shù)與參數(shù)間的引用

# 注釋
com.demo:
  name: 知碼學(xué)院
  url: www.it235.com
  scope: ${com.demo.name}的網(wǎng)址是${com.demo.url}

這樣我們直接使用scope屬性就能看到效果了芜茵,注:properties和yml除了書寫格式上的差異外,使用方式基本類似倡蝙,所以后續(xù)我們的講解中都建議使用yml文件

隨機參數(shù)生成

通常是用這些隨機數(shù)我們得寫一段代碼生成九串,現(xiàn)在配置文件中${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已經(jīng)封裝好的配置變量啦,類似于jsp中的隱式對象request一樣眼坏,拿來即用

命令行參數(shù)配置

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

設(shè)置Spring profiles參數(shù)啟動

$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

命令啟動參數(shù)用 --xxx=xxx 的形式傳遞宰译。命令行參數(shù)在demo.jar的后面檐蚜,如果你擔(dān)心命令行有風(fēng)險,則可以使用SpringApplication.setAddCommandLineProperties(false)禁用它沿侈。

運行或系統(tǒng)參數(shù)獲取

Spring Boot應(yīng)用程序有多種設(shè)置途徑闯第,Spring Boot能從多重屬性源獲得屬性,包括如下幾種(優(yōu)先級從高到低排序):

  • 命令行參數(shù)
  • SPRING_APPLICATION_JSON中的屬性(環(huán)境變量或系統(tǒng)屬性中的內(nèi)聯(lián)JSON嵌入)缀拭。
  • ServletConfig初始化參數(shù)咳短。
  • ServletContext初始化參數(shù)。
  • 來自java:comp/env的JNDI屬性
  • Java系統(tǒng)屬性(System.getProperties()
  • 操作系統(tǒng)環(huán)境變量
  • RandomValuePropertySource配置的random.*屬性值蛛淋,比如${random.long}
  • jar包外部的application-{profile}.propertiesapplication.yml(帶spring.profile)配置文件
  • jar包內(nèi)部的application-{profile}.propertiesapplication.yml(帶spring.profile)配置文件
  • jar包外部的application.propertiesapplication.yml(不帶spring.profile)配置文件
  • jar包內(nèi)部的application.propertiesapplication.yml(不帶spring.profile)配置文件
  • @Configuration注解類上的@PropertySource
  • 通過SpringApplication.setDefaultProperties指定的默認屬性

任何在高優(yōu)先級屬性源里設(shè)置的屬性都會覆蓋低優(yōu)先級的相同屬性咙好,列如我們上面提到的命令行屬性就覆蓋了application.properties的屬性。

配置文件的優(yōu)先級

application.propertiesapplication.yml文件可以放在以下四個位置:

  • 外置褐荷,在相對于應(yīng)用程序運行目錄的/congfig子目錄里勾效。
  • 外置,在應(yīng)用程序運行的目錄里
  • 內(nèi)置叛甫,在config包內(nèi)
  • 內(nèi)置层宫,在Classpath根目錄

同樣,這個列表按照優(yōu)先級排序其监,也就是說萌腿,src/main/resources/config/application.properties覆蓋src/main/resources/application.properties中相同的屬性,如圖:

配置文件優(yōu)先級

此外抖苦,如果你在相同優(yōu)先級位置同時有application.propertiesapplication.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多配置文件贸伐,建議寫到一個里面,但如果分成多個環(huán)境加載不同配置怔揩,那接下來我們就講解下如何通過命令參數(shù)調(diào)用不同的yml

Profile-多環(huán)境配置

普通springmvc項目解決方案

在普通的springmvc的tomcat項目中捉邢,我們也可以指定JVM的運行參數(shù),在啟動服務(wù)的時候通過System.getProperty("JVM配置key")獲取到這個參數(shù)商膊,然后初始化不同的Properties文件伏伐,操作如下:


普通springmvc項目,properties文件
    <!-- 從properties文件加載配置信息 -->
    <bean id="propertyPlaceholderConfigurer" class="com.xx.xx.common.spring.CustomizedPropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <!-- 此處配置文件需要在tomcat運行參數(shù)中指定[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。通過設(shè)置active選擇不同配置文件
    set JAVA_OPTS="-Dspring.profiles.active=test"

上述的CustomizedPropertyPlaceholderConfigurer類實現(xiàn)了PropertyPlaceholderConfigurer,在初始化的時候通過獲取JVM的profile進行不同的properties選取

SpringBoot解決方案

對于多環(huán)境的配置吝镣,各種項目構(gòu)建工具或是框架的基本思路是一致的堤器,通過配置多份不同環(huán)境的配置文件,再通過打包命令指定需要打包的內(nèi)容之后進行區(qū)分打包末贾,Spring Boot也不例外闸溃,或者說更加簡單。

在Spring Boot中多環(huán)境配置文件名需要滿足application-{profile}.yml的格式拱撵,其中{profile}對應(yīng)你的環(huán)境標(biāo)識辉川,如下圖:

yml結(jié)構(gòu)

至于哪個具體的配置文件會被加載,需要在application.yml文件中通過spring.profiles.active屬性來設(shè)置拴测,其值對應(yīng){profile}值乓旗。如:spring.profiles.active=prod就會加載application-prod.yml配置文件內(nèi)容

application.yml內(nèi)容如下

spring.profiles.active: dev

application-dev.yml內(nèi)容如下

server:
  port: 1000

application-prod.yml內(nèi)容如下

server:
  port: 1001

啟動的時候帶上參數(shù):java -jar xxx.jar --spring.profiles.active=dev,就會發(fā)現(xiàn)啟動的端口不一樣昼扛,說明配置文件生效了


代碼使用profile

除了可以用profile的配置文件來分區(qū)配置我們的環(huán)境變量寸齐,在代碼里,我們還可以直接用@Profile注解來進行配置抄谐,例如數(shù)據(jù)庫配置渺鹦,這里我們先定義一個接口

public  interface DBConnector { public  void  dbConfig(); }

分別定義倆個實現(xiàn)類來實現(xiàn)它

/**
  * 開發(fā)數(shù)據(jù)庫
  */
@Component
@Profile("devdb")
public class DevDBConnector implements DBConnector {
    @Override
    public void dbConfig() {
        System.out.println("devdb");
    }
}
/**
 * 生產(chǎn)數(shù)據(jù)庫
 */
@Component
@Profile("prodb")
public class ProDBConnector implements DBConnector {
    @Override
    public void dbConfig() {
        System.out.println("prodb");
    }
}

通過在配置文件激活具體使用哪個實現(xiàn)類

spring.profiles.active=prodb

然后具體調(diào)用如下

@RestController
@RequestMapping("/call")
public class CallController {

    @Autowired DBConnector connector ;

    @RequestMapping(value = {"/",""})
    public String hellYml(){

        connector.dbConfig(); //最終打印prodb
        return "Hello yml";
    }
}

總結(jié)

SpringBoot的配置文件給我們帶來了極大的便利,properties和yml兩者各選一個吧蛹含,不過我更傾向于yml毅厚,其格式化的配置看起來很舒服,有點類似于json格式浦箱,更多的屬性及配置后續(xù)在使用的過程中慢慢講解吸耿。


作者有話說:喜歡的話就請移步知碼學(xué)院,請自備水酷窥,更多干咽安、干、干貨等著你

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蓬推,一起剝皮案震驚了整個濱河市妆棒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沸伏,老刑警劉巖糕珊,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異毅糟,居然都是意外死亡红选,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門姆另,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喇肋,“玉大人坟乾,你說我怎么就攤上這事」兜福” “怎么了糊渊?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慧脱。 經(jīng)常有香客問我,道長贺喝,這世上最難降的妖魔是什么菱鸥? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮躏鱼,結(jié)果婚禮上氮采,老公的妹妹穿的比我還像新娘。我一直安慰自己染苛,他們只是感情好鹊漠,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茶行,像睡著了一般躯概。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上畔师,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天娶靡,我揣著相機與錄音,去河邊找鬼看锉。 笑死姿锭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伯铣。 我是一名探鬼主播呻此,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼腔寡!你這毒婦竟也來了焚鲜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蹬蚁,失蹤者是張志新(化名)和其女友劉穎恃泪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犀斋,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡贝乎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叽粹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片览效。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡却舀,死狀恐怖祟霍,靈堂內(nèi)的尸體忽然破棺而出凶掰,到底是詐尸還是另有隱情砂吞,我是刑警寧澤骂远,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布庞钢,位于F島的核電站光稼,受9級特大地震影響诲锹,放射性物質(zhì)發(fā)生泄漏菩暗。R本人自食惡果不足惜状囱,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一术裸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亭枷,春花似錦袭艺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至升敲,卻和暖如春答倡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冻晤。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工苇羡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鼻弧。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓设江,卻偏偏與公主長得像,于是被迫代替她去往敵國和親攘轩。 傳聞我的和親對象是個殘疾皇子叉存,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容