SpringBoot教程(三)(配置文件解析)_下

? ? ? 配置文件解析(下)

?????????????????????????????????????????????????????????????????????????????????????????????????原創(chuàng)者:文思

一、yml(YAML Ain’t Markup Language)基本用法

application.properties或application.yml

配置文件的作用:修改springboot的默認(rèn)配置系馆。

YAML:以數(shù)據(jù)為中心,比json遇汞,xml等更適合做配置文件

基本語法:

K:(空格)V :表示一對鍵值對宪哩。以空格的縮進(jìn)來控制層級關(guān)系褂策,只要是左對齊的一列數(shù)據(jù),都是一個層級的峭判。

值的寫法:

字面量:普通的值(數(shù)據(jù)、字符串棍好、布爾)仗岸,k: v形式直接來寫。如果有特殊字符借笙,不需要轉(zhuǎn)義可用雙引號爹梁,需要轉(zhuǎn)義可用單引號。

對象提澎、Map:k: v形式直接來寫姚垃,在下一行寫對象的屬性和值,注意縮進(jìn)盼忌。

還可以使用行內(nèi)寫法:friends:{name:zhangsan,age: 18}

數(shù)組(List积糯、Set):用- 值表示數(shù)組中的一個元素

示例:

新建一個yml配置文件:

server:

?????port: 8081

person:

?????lastName: zhangsan

?????age: 18

?????boss:??false

?????birth:? 2018/7/17

?map:? {t1:test1,t2:test2,t3:test3}

?map2:

???t1:? test11

???t2:? test22

???t3:? test33

list:

???-? lisi

???-? wangwu

???-? zhaoliu

?dog:

? ? name:? 小狗

????age:? 2

創(chuàng)建對應(yīng)的對象:

@Component//聲明為spring組件,讓spring容器管理

@ConfigurationProperties(prefix="person")//默認(rèn)從全局配置文件中獲取值,告訴springboot將此類的屬性與配置文件的配置綁定

public classPerson {

??? private String lastName;

??? private Integer age;

??? private Boolean boss;

??? private Date birth;

??? privateMap map;

??? privateMap map2;

??? private List list;

??? private Dog dog;

??? public String toString(){

?????? return "Person{"+

????????????? "lastName="+ lastName+

????????????? ",age="+ age+

????????????? ",boss="+ boss+

????????????? ",birth="+ birth+

????????????? ",map="+ map+

????????????? ",map2="+ map2+

????????????? ",list="+ list+

????????????? ",dog="+ dog+

????????????? "}";

??? }

?.....setter\getter方法略

}

package com.wensi.springbootdemo1.yml;

public classDog {

??? private String name;

??? private Integer age;

??? public String getName() {

?????? return name;

??? }

?.....setter\getter方法略

}

運行測試類:

package com.wensi.springbootdemo1;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

import com.wensi.springbootdemo1.yml.Person;

@RunWith(SpringRunner.class)

@SpringBootTest

public classAppTest{

??? @Autowired

??? Personperson;

??? @Test

??? public void contextLoads(){

?????? System.out.println(person);

??? }

}

運行結(jié)果:

Person{lastName=zhangsan,age=18,boss=false,birth=Tue Jul 17 00:00:00 CST 2018,map={t1=test1, t2=test2, t3=test3},map2={t1=test11,t2=test22, t3=test33},list=[lisi, wangwu,zhaoliu],dog=com.wensi.springbootdemo1.yml.Dog@796d3c9f}

使用properties格式的配置文件application.properties:

person.lastName=zhangsan

person.age=18

person.boss=false

person.birth=2018/7/17

person.map.t1=test1

person.map.t2=test2

person.map.t3=test3

person.list=lisi,wangwu,zhaoliu

person.dog.name=小狗

person.dog.age=2

運行測試類的結(jié)果:

Person{lastName=zhangsan,age=18,boss=false,birth=TueJul 17 00:00:00 CST 2018,map={t3=test3, t2=test2,t1=test1},map2=null,list=[lisi, wangwu,zhaoliu],dog=com.wensi.springbootdemo1.yml.Dog@6f8d7714}

使用@value:

@Component

public class PersonValue {

??? @Value("${person.lastName}")

??? private String lastName;

??? @Value("#{2*11}")

??? private Integer age;

??? @Value("true")

??? privateBooleanboss;

運行結(jié)果:

Person{lastName=zhangsan,age=22,boss=true,birth=null,map=null,map2=null,list=null,dog=null}

@value和@ConfigurationProperties區(qū)別:

例如:

@Component

@ConfigurationProperties(prefix="person")

@Validated

public class Person {

??? @Email

??? private String lastName;//lastName必須是郵箱格式

??? private Integer age;

??? private Boolean boss;

??? private Date birth;

運行結(jié)果:

Binding to targetPerson{lastName=zhangsan,age=18,boss=false,birth=Tue Jul 17 00:00:00 CST2018,map={t3=test3, t2=test2, t1=test1},map2=null,list=[lisi, wangwu,zhaoliu],dog=com.wensi.springbootdemo1.yml.Dog@7689ddef} failed:

??? Property:person.lastName

??? Value:zhangsan

? ? Reason: 不是一個合法的電子郵件地址

使用@value時:

@Component

@Validated

public class PersonValue {

??? @Email

??? @Value("${person.lastName}")

??? private String lastName;

運行結(jié)果:

Person{lastName=zhangsan,age=22,boss=true,birth=null,map=null,map2=null,list=null,dog=null}。說明@value不支持?jǐn)?shù)據(jù)校驗

對于復(fù)雜數(shù)據(jù)類型:

@Component

public class PersonValue {

??? @Value("${person.lastName}")

??? private String lastName;

??? @Value("#{2*11}")

??? private Integer age;

??? @Value("true")

??? private Boolean boss;

??? private Date birth;

??? @Value("${person.map}")

??? private Map map;

運行結(jié)果:

Caused by: java.lang.IllegalArgumentException:Could not resolve placeholder 'person.map' in value "${person.map}"

說明@value不支持復(fù)雜數(shù)據(jù)類型谦纱,如map看成。

使用建議:

如果說,我們只是在某個業(yè)務(wù)邏輯中需要獲取一下配置文件中的某項值跨嘉,使用@Value川慌。

如果說,我們專門編寫了一個javaBean來和配置文件進(jìn)行映射祠乃,我們就直接使用@ConfigurationProperties

@PropertySource和@importResource

根據(jù)名稱分析@PropertySource可加載非默認(rèn)的配置文件梦重,即加載指定的配置文件,當(dāng)我們想將一些特定業(yè)務(wù)所需要的配置與系統(tǒng)默認(rèn)配置分開維護(hù)時亮瓷,需要@PropertySource

@Component

@ConfigurationProperties(prefix="person")

@PropertySource(value={"classpath:person.properties"})

public class PersonPropertySource {

??? private String lastName;

??? privateInteger age;

運行結(jié)果:

Person{lastName=zhangsan,age=18,boss=false,birth=Tue Jul 17 00:00:00 CST 2018,map={t3=test3, t2=test2,

t1=test1},map2=null,list=[lisi, wangwu,zhaoliu],dog=com.wensi.springbootdemo1.yml.Dog@1b32cd16}


@importResource導(dǎo)入spring的配置文件琴拧,讓配置文件里面的內(nèi)容生效

因為springboot里面沒有spring的配置文件,自己編寫地配置文件也不能識別嘱支,所以需要使用@importResource加載進(jìn)來蚓胸。示例:

public class TestImportService {

}

bean.xml:

@SpringBootApplication

@ImportResource(locations = {"classpath:bean.xml"})

public class App

{

……

}

測試用例:

@Autowired

??? ApplicationContext ioc;

??? @Test

??? public void testImportSource(){

?????? System.out.println(ioc.containsBean("testImportService"));

??? }

運行結(jié)果:true

SpringBoot推薦給容器中添加組件的方式:推薦使用全注解的方式

1、配置類@Configuration------>Spring配置文件

2除师、使用@Bean給容器中添加組件,配置類這里使用@Bean注解

/**

* @Configuration:指明當(dāng)前類是一個配置類沛膳;就是來替代之前的Spring配置文件

** 在配置文件中用標(biāo)簽添加組件

*/

@Configuration

public class MyAppConfig {

//將方法的返回值添加到容器中;容器中這個組件默認(rèn)的id就是方法名

????????@Bean

????????public HelloService helloService02(){

????????????System.out.println("配置類@Bean給容器中添加組件了...");

????????????return new HelloService();

????????}

}

配置文件占位符

1汛聚、隨機(jī)數(shù):

${random.value}锹安、${random.int}、${random.long}

${random.int(10)}、${random.int[1024,65536]}

2八毯、占位符獲取之前配置的值搓侄,如果沒有可以是用:指定默認(rèn)值

person.last‐name=張三${random.uuid}

person.age=${random.int}

person.birth=2017/12/15

person.boss=false

person.maps.k1=v1

person.maps.k2=14

person.lists=a,b,c

person.dog.age=15

person.dog.name=${person.hello:hello}_dog?

如果${person.hello: hello}取不到值就默認(rèn)值hello


多profile文件

應(yīng)該對開發(fā)\測試\生產(chǎn)環(huán)境下切換

文件名可以是application-{profile}.properties/yml

默認(rèn)使用的是application.properties/yml

激活指定profile

在配置文件中指定spring.profile.activie=dev,示例瞄桨,新建application-dev.properties:

application.properties中增加spring.profile.activie=dev

Yml格式的多profile:yml支持文檔塊模式

spring:

? profiles:

??? active: prod

---

server:

? port: 8083

spring:

? profiles: prod

---

server:

? port: 8084

spring:

? profiles:dev

運行如圖:

spring.profiles.active是激活使用指定的配置文件话速。

另一種可以使用命令行的方式:java -jar ***.jar –spring.profiles.active=dev

還有一種虛擬機(jī)參數(shù):-Dspring.profiles.active=dev


配置文件加載位置

Spring

boot啟動會掃描以下位置的application.properties或yml作為spring

boot的默認(rèn)配置文件

-file:./config/

-file:./

-classpath:/config/

-classpath:/

以上是按照優(yōu)先級從高到低的順序,所有位置的文件都會被加載芯侥,高優(yōu)先級配置內(nèi)容會覆蓋低優(yōu)先級配置內(nèi)容泊交。


外部配置加載順序

SpringBoot也可以從外部以下位置加載配置; 優(yōu)先級從高到低柱查;高優(yōu)先級的配置覆蓋低優(yōu)先級的配置廓俭,所有的配置會形成互補(bǔ)配置

1.命令行參數(shù)

所有的配置都可以在命令行上進(jìn)行指定

java -jarspring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087--server.context-path=/abc

多個配置用空格分開;--配置項=值

2.來自java:comp/env的JNDI屬性

3.Java系統(tǒng)屬性(System.getProperties())

4.操作系統(tǒng)環(huán)境變量

5.RandomValuePropertySource配置的random.*屬性值由jar包外向jar包內(nèi)進(jìn)行尋找唉工;優(yōu)先加載帶profile

6.jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件

7.jar包內(nèi)部的application-{profile}.properties或application.yml(spring.profile)配置文件再來加載不帶profile

8.jar包外部的application.properties或application.yml(不spring.profile)配置文件

9.jar包內(nèi)部的application.properties或application.yml(不spring.profile)配置文件

10.@Configuration注解類上的@PropertySource

11.通過SpringApplication.setDefaultProperties指定的默認(rèn)屬性

示例:

java

-jar springbootdemo1-0.0.1-SNAPSHOT.jar -server.port=8088研乒,

啟動端口就覆蓋配置文件的里的端口設(shè)置了,啟動端口為8088

二淋硝、自動配置原理

配置文件能配置的屬性參照:

https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#common-application-properties

觀察@ SpringBootApplication源碼

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan(excludeFilters = {

? ? ? ?@Filter(type = FilterType.CUSTOM, classes =

TypeExcludeFilter.class),

?????? @Filter(type = FilterType.CUSTOM, classes =

AutoConfigurationExcludeFilter.class) })

public @interface SpringBootApplication

1)SpringBoot啟動時候加載主配置類雹熬,開啟了自動配置功能@EnableAutoConfiguration

2) @EnableAutoConfiguration利用EnableAutoConfigurationImportSelector選擇器給容器導(dǎo)入META-INF/Spring.factories中的默認(rèn)配置對應(yīng)的組件。(可查看selectImports()方法-->

List configurations = getCandidateConfigurations(annotationMetadata, attributes);獲取候選的配置-->

SpringFactoriesLoader.loadFactoryNames()//掃描所有jar包類路徑下META‐INF/spring.factories把掃描到的這些文件的內(nèi)容包裝成properties對象從properties中獲取到EnableAutoConfiguration.class類(類名)對應(yīng)的值谣膳,然后把他們添加在容器中)

3)如上每一個自動配置類進(jìn)行自動配置

4) 以HttpEncodingAutoConfiguration(Http編碼自動配置)為例解釋自動配置原理竿报;

@Configuration //表示這是一個配置類,以前編寫的配置文件一樣继谚,也可以給容器中添加組件

@EnableConfigurationProperties(HttpEncodingProperties.class)

//啟動指定類的

ConfigurationProperties功能烈菌;將配置文件中對應(yīng)的值和HttpEncodingProperties綁定起來;并把

HttpEncodingProperties加入到ioc容器中

@ConditionalOnWebApplication

//Spring底層@Conditional注解(Spring注解版)花履,根據(jù)不同的條件芽世,如果

滿足指定的條件,整個配置類里面的配置就會生效诡壁; 判斷當(dāng)前應(yīng)用是否是web應(yīng)用捂襟,如果是,當(dāng)前配置類生效

@ConditionalOnClass(CharacterEncodingFilter.class)

//判斷當(dāng)前項目有沒有這個類

CharacterEncodingFilter欢峰;SpringMVC中進(jìn)行亂碼解決的過濾器葬荷;

@ConditionalOnProperty(prefix= "spring.http.encoding", value = "enabled", matchIfMissing=

true) //判斷配置文件中是否存在某個配置spring.http.encoding.enabled;如果不存在纽帖,判斷也是成立的

//即使我們配置文件中不配置pring.http.encoding.enabled=true宠漩,也是默認(rèn)生效的;

public class HttpEncodingAutoConfiguration{

//他已經(jīng)和SpringBoot的配置文件映射了

private final HttpEncodingPropertiesproperties;

//只有一個有參構(gòu)造器的情況下懊直,參數(shù)的值就會從容器中拿

publicHttpEncodingAutoConfiguration(HttpEncodingProperties properties) {

this.properties =properties;

}

@Bean //給容器中添加一個組件扒吁,這個組件的某些值需要從properties中獲取

@ConditionalOnMissingBean(CharacterEncodingFilter.class)

//判斷容器沒有這個組件?

publicCharacterEncodingFilter characterEncodingFilter() {

CharacterEncodingFilter filter = newOrderedCharacterEncodingFilter();

filter.setEncoding(this.properties.getCharset().name());

filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));

filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));

return filter;

}

根據(jù)當(dāng)前不同的條件判斷室囊,決定這個配置類是否生效雕崩?

一但這個配置類生效魁索;這個配置類就會給容器中添加各種組件;這些組件的屬性是從對應(yīng)的properties類中獲取的盼铁,這些類里面的每一個屬性又是和配置文件綁定的

這里能看出配置文件能配置的屬性都是來源于HttpEncodingProperties類粗蔚。

精髓:

1:spring boot啟動會加載大量的自動配置類

2:我們看我們需要的功能有沒有springboot默寫好的自動配置類

3:我們看這個自動配置類中配置了哪些組件(我們要用的有就不用再配置了)

4:給容器中自動配置類添加組件時,會從properties類中獲取某些屬性饶火,我們可以在配置文件中指定這些屬性的值

xxxAutoConfigurartion自動配置類鹏控,給容器中添加組件,xxxAutoConfigurartion下的xxxxProperties:封裝配置文件中相關(guān)屬性肤寝;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末当辐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鲤看,更是在濱河造成了極大的恐慌缘揪,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件义桂,死亡現(xiàn)場離奇詭異找筝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)澡刹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門呻征,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罢浇,你說我怎么就攤上這事陆赋。” “怎么了嚷闭?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵攒岛,是天一觀的道長。 經(jīng)常有香客問我胞锰,道長灾锯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任嗅榕,我火速辦了婚禮顺饮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凌那。我一直安慰自己兼雄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布帽蝶。 她就那樣靜靜地躺著赦肋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上佃乘,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天囱井,我揣著相機(jī)與錄音,去河邊找鬼趣避。 笑死庞呕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鹅巍。 我是一名探鬼主播千扶,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼料祠,長吁一口氣:“原來是場噩夢啊……” “哼骆捧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起髓绽,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤敛苇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后顺呕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫攀,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年株茶,在試婚紗的時候發(fā)現(xiàn)自己被綠了来涨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡启盛,死狀恐怖蹦掐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情僵闯,我是刑警寧澤卧抗,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站鳖粟,受9級特大地震影響社裆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜向图,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一泳秀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榄攀,春花似錦嗜傅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春币他,著一層夾襖步出監(jiān)牢的瞬間坞靶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工蝴悉, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留彰阴,地道東北人。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓拍冠,卻偏偏與公主長得像尿这,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子庆杜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理射众,服務(wù)發(fā)現(xiàn),斷路器晃财,智...
    卡卡羅2017閱讀 134,696評論 18 139
  • SpringMVC原理分析 Spring Boot學(xué)習(xí) 5叨橱、Hello World探究 1、POM文件 1断盛、父項目...
    jack_jerry閱讀 1,309評論 0 1
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架罗洗,建立于...
    Hsinwong閱讀 22,434評論 1 92
  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的!钢猛! 因為Scala是基于Java虛擬機(jī)伙菜,也就是...
    燈火gg閱讀 3,452評論 1 24
  • 第一章 劫機(jī) 美國洛杉磯唐人街的一家餐廳中一名穿著白色大褂的帶著淺紅色墨鏡的男子一個人吃著炒面。整個餐廳除了餐廳的...
    作者酒肉和尚閱讀 354評論 0 0