(SpringBoot學(xué)習(xí)筆記3)Spring Boot的配置

1 yaml簡介

1.1 基本語法

k:(空格)v: 表示一對(duì)鍵值對(duì)(空格必須有)
以空格的縮進(jìn)來控制層級(jí)關(guān)系夜只;只要是做肚臍的一列數(shù)據(jù)蛉迹,都是同一個(gè)層級(jí)的稠诲。

server:
  port: 8081
  path: /hello

屬性和值都是大小寫敏感的舵匾。

1.2 值的寫法

1.2.1 字面量

1.2.1.1 普通的值(數(shù)字诬乞、字符串册赛、布爾)

k:v;字面量直接來寫震嫉,字符串不需要加上丹壹號(hào)或者雙引號(hào)森瘪;
雙引號(hào):不會(huì)轉(zhuǎn)移字符串李的特殊字符,特殊字符會(huì)作為本身想表示的意思票堵。

name:"zhangsan\nlisi"

其輸出就是有換行扼睬。
單引號(hào):會(huì)轉(zhuǎn)義特殊字符,特殊字符最終只是一個(gè)普通的字符串?dāng)?shù)據(jù)悴势。

name:"zhangsan\nlisi"

輸出為原樣窗宇。

1.2.1.2 對(duì)象、Map(屬性和值特纤、鍵值對(duì))

對(duì)象還是k:v的方式军俊,在下一行直接寫對(duì)象的屬性和值的關(guān)系,不過要注意縮進(jìn)(兩個(gè)空格)捧存。

friends:
  lastName: zhangsan
  age: 20

行內(nèi)寫法:

friends: {lastName: zhangsan,age: 18}

1.2.1.3 數(shù)組(List粪躬、Set)

短橫線(空格)值 表示數(shù)組中的一個(gè)元素。

pets:
  - cat
  - dog
  - pig

行內(nèi)寫法:

pets: [cat,dog,pig]

1.3 進(jìn)階語法

1.3.1 復(fù)合結(jié)構(gòu)

person:
  lastName: zhangsan
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: 12}
  lists:
    - lisi
    - zhangsan
  dog:
    name: xiaogou
    age: 2

2 配置文件

SB使用一個(gè)全局配置文件矗蕊,配置文件名是固定的:

  • application.properties
  • application.yml

配置文件的作用:修改SB自動(dòng)配置的默認(rèn)值短蜕。SB在底層都給我們自動(dòng)配置好了;

配置文件位于src/resources下面傻咖。

2.1 YAML

yaml a markup language 是一個(gè)標(biāo)記語言,以數(shù)據(jù)為中心岖研,比其他類型的標(biāo)記語言更適合作為配置文件卿操。
標(biāo)記語言:以前的配置文件大多都使用XXX.xml文件,

2.2 不同文件配置方式

YAML:

server:
  port: 8081

XML:

<server>
  <port>8081</port>
</server>

properties:

server.port = 8081

3 例子:配置文件實(shí)現(xiàn)值的注入

3.1 編寫配置文件

person:
  lastName: zhaoyi
  list:
    - list1
    - list2
  maps:
    k1: v1
    k2: v2
  age: 25
  boss: false
  dog:
    name: xiaohuang
    age: 30 

配置組件

// person類
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastName;
    private List<Object> list;
    private Map<String, Object> maps;
    private Integer age;
    private Boolean boss;
    private Dog dog;

    @Override
    public String toString() {
        return "Person{" +
                "lastName='" + lastName + '\'' +
                ", list=" + list +
                ", maps=" + maps +
                ", age=" + age +
                ", boss=" + boss +
                ", dog=" + dog +
                '}';
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getBoss() {
        return boss;
    }

    public void setBoss(Boolean boss) {
        this.boss = boss;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
}

// dog類
package com.zhaoyi.hello1.com.zhaoyi.hello1.bean;

public class Dog {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

3.2 使配置擁有提示

導(dǎo)入配置文件處理器孙援,這樣就會(huì)有提示編寫資源的信息害淤;

  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
  </dependency>

只有組件是容器中的組件,才能使用ConfigurationProperties提供的功能;

3.3 編寫測(cè)試類

SB單元測(cè)試:可以在測(cè)試期間很方便的類似編碼一樣進(jìn)行自動(dòng)注入等容器功能拓售;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Hello1ApplicationTests {

    @Autowired
    Person person;

    @Test
    public void contextLoads() {
        System.out.println(person);
    }
}

4 properties配置文件的編碼問題

4.1 使用properties配置文件

注釋掉application.yml的配置文件信息窥摄,新建一個(gè)application.properties文件,寫入和applicatio.yml相同功能的配置

person.age=14
person.last-name=張三
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.list=a,b,c
person.dog.name=小狗
person.dog.age=5

運(yùn)行測(cè)試后發(fā)現(xiàn)有關(guān)中文部分的輸出是亂碼础淤。

4.2 解決方法

idea使用的是utf-8編碼崭放,在setting處查詢file encoding哨苛,設(shè)置為utf-8,并選擇在運(yùn)行時(shí)轉(zhuǎn)化為ascll(勾選)

5 @configurationProperties和@Value

Spring中配置一個(gè)Bean:

<bean class="person">
  <property name="lastName" value="zhangsan"></property>
</bean>

其中币砂,value可以:

  • 字面量
  • ${key} 從環(huán)境變量或者配置文件中提取變量值
  • #{SPEL}

而@Value其實(shí)效果和其一樣建峭,比如,在類屬性上寫

@Value("person.lastName")
private String lastName
@Value("#{11*2}")
private Integer age

5.1 區(qū)別

@ConfigurationProperties @Value
功能 批量注入配置文件中的屬性 一個(gè)個(gè)指定
支持松散綁定 不支持松散綁定
SpEL 不支持 支持
JSR303數(shù)據(jù)校驗(yàn) 支持 不支持
復(fù)雜類型封裝 支持 不支持

注:

  • 松散綁定例如:
    配置文件填寫的是last-name决摧,而@Value必須寫一模一樣的亿蒸,否則會(huì)報(bào)錯(cuò)。而使用@ConfigurationProperties則可以使用駝峰式(其實(shí)就是類的屬性名)
  • @Validation 在類上加入此配置之后掌桩,開啟jsr303校驗(yàn)边锁,例如在某字段上加上@Email,則配置文件對(duì)應(yīng)字段必須符合郵箱格式波岛。相反茅坛,如果此處我們使用@Value注入值,可以看到盆色,可以正常的注入灰蛙,即便提供的不符合郵箱格式,也不會(huì)報(bào)錯(cuò)隔躲。

5.2 選擇

從上面的說明我們可以知道摩梧,兩者在配置上基本可以相互替換,彼此功能也大體一致宣旱,那么仅父,我們?cè)跇I(yè)務(wù)場景中,該選用哪一種進(jìn)行編碼呢浑吟?

  1. 如果說笙纤,我們只是在某個(gè)業(yè)務(wù)邏輯中需要獲取一下配置文件的某項(xiàng)值,考慮使用@Value.
@RestController
public class HelloController {
    @Value("${person.last-name}")
    private String name;

    @RequestMapping("/")
    public String hello(){
        return "hello world, " + name;
    }
}
  1. 但是组力,如果我們專門去寫一個(gè)java bean來和配置文件進(jìn)行映射省容,那么毫無疑問,我們應(yīng)該使用@ConfigurationProperties燎字;

6 @PopertySource注解

@PropertySource 加載指定的配置文件腥椒。

我們知道,@ConfigurationProperties默認(rèn)從全局配置文件(application.properties)中獲取值候衍,但通常我們會(huì)將相關(guān)的配置文件放到某個(gè)配置文件中笼蛛,例如,我們將有關(guān)person的配置信息放到person.properties中去蛉鹿。為了使組件類Person能夠找到配置文件的配置信息滨砍,需要使用增加新的注解@PropertySource指定從哪里加載配置等相關(guān)信息。

@PropertySource("classpath:person.properties")
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
}

7 @ImportResource注解

@ImportResource 導(dǎo)入Spring的配置文件,讓配置文件里面的內(nèi)容生效惋戏。

  1. 添加新的服務(wù)類HelloService
package com.zhaoyi.hello1.service;
public class HelloService {
}
  1. 在類目錄下創(chuàng)建一個(gè)bean.xml领追,即spring的配置文件,其中配置了一個(gè)service的bean.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.zhaoyi.hello1.service.HelloService"></bean>
</beans>

那么問題來了日川,在spring-boot中顯然是不會(huì)加載此bean的蔓腐,我們測(cè)試一下。

  1. 編寫測(cè)試類
@RunWith(SpringRunner.class)
@SpringBootTest
public class Hello1ApplicationTests {
    @Autowired
    ApplicationContext ioc;

    @Test
    public void testBean(){
        System.out.println("Is have helloService bean? " + ioc.containsBean("helloService"));
    }
}

測(cè)試結(jié)果:

Is have helloService bean? false

Spring boot里面是沒有Spring的配置文件龄句,我們自己編寫的配置文件回论,也不能自動(dòng)識(shí)別,想讓Spring的配置文件生效分歇,則需要手動(dòng)指示將其加載進(jìn)行傀蓉,使用@ImportResource標(biāo)注在一個(gè)配置類(例如應(yīng)用程序啟動(dòng)類,他也是一個(gè)配置類)上:

@ImportResource(locations = {"classpath:bean.xml"})
@SpringBootApplication
public class Hello1Application {
    public static void main(String[] args) {
        SpringApplication.run(Hello1Application.class, args);
    }
}

這時(shí)候運(yùn)行測(cè)試用例就會(huì)發(fā)現(xiàn)职抡,bean已經(jīng)出現(xiàn)在容器中了葬燎。

7 @Bean注解

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

一般我們不會(huì)使用6中所提到的這種方式,因?yàn)閤ml配置方式實(shí)在是寫了太多的無用代碼缚甩,如果xml的標(biāo)簽聲明谱净,以及頭部的域名空間導(dǎo)致。因此擅威,SpringBoot推薦給容器中添加組件的方式:全注解方式壕探。也就是用配置類來充當(dāng)bean配置文件。如下郊丛,即為一個(gè)配置類:

/**
 * @Configuration 指明當(dāng)前類是一個(gè)配置類
 */
@Configuration
public class MyConfig {
    // 將方法的返回值添加到容器中:容器中這個(gè)組件的id就是方法名
    @Bean
    public HelloService helloService(){
        return new HelloService();
    }
}

通過該配置類李请,可以為容器中添加了一個(gè)名為helloService的bean。

8 配置文件占位符

無論是使用yaml還是properties都自持文件占位符配置方式

8.1 隨機(jī)數(shù)

${random.value}

${random.int}

${random.long}

${random.int(10)}

${random.int[1024,65536]}

8.2 屬性占位符

  • 可以在配置文件中引用前面配置過的屬性厉熟;
  • ${app.name:默認(rèn)值} 若找不到屬性時(shí)导盅,則取默認(rèn)值處填寫的值;

8.3 例子

  1. 在person.properties中寫入如下配置
person.age=14
person.last-name=張三${random.uuid}
person.boss=false
person.maps.k1={person.xxx:novalue}
person.maps.k2=v2
person.list=a,b,c
person.dog.name=${person.last-name}_小狗狗
person.dog.age=${random.int}
  1. 測(cè)試輸出
Person{lastName='張三1b9fbbb1-6c58-4a35-8165-ad23800d7456', list=[a, b, c], maps={k2=v2, k1=novalue}, age=14, boss=false, dog=Dog{name='張三b3a355d7-54ce-4afd-9ae6-d3be4aeb4165_小狗狗', age=-122850975}}

注意:留意默認(rèn)值那一項(xiàng)設(shè)置揍瑟,我們?nèi)缭傅某晒υO(shè)置了默認(rèn)值novalue白翻。在實(shí)際項(xiàng)目中,這種情況比較常用绢片,稍微留意一下嘁字。如果沒有默認(rèn)值,則會(huì)將${xxx}這一段作為值杉畜,這顯然是錯(cuò)誤的。

9 Profile

profile一般是spring用來做多環(huán)境支持的衷恭,可以通過激活指定參數(shù)等方式快速的切換當(dāng)前環(huán)境此叠。

9.1 多Profile文件

我們?cè)谥髋渲梦募帉懙臅r(shí)候,文件名可以是 application-{profile}.properties(yml)
例如:
application-dev.properties、application-prod.properties等灭袁。

9.2 激活指定profile

  1. 在application.properties中指定:
spring.profiles.active=dev
  1. 命令行方式激活猬错,此配置的優(yōu)先級(jí)高于配置文件處的配置。
--spring.profiles.active=dev
  • 方式一 點(diǎn)擊編譯環(huán)境右上角的下拉框茸歧,選擇第一項(xiàng)edit configuration倦炒,在environment配置節(jié)中的Program arguments寫入spring.profiles.active=dev即可。
  • 方式二 將當(dāng)前的項(xiàng)目打包生成jar包软瞎,然后執(zhí)行java -jar your-jar-name.jar --spring.profiles.active=dev即可逢唤。
  1. 虛擬機(jī)參數(shù)方式激活 在步驟2的老地方,Program arguments上一項(xiàng)即為虛擬機(jī)參數(shù)激活涤浇,不過填寫的內(nèi)容為-Dspring.profiles.active=dev鳖藕,即多了一個(gè)-D而已。

9.3 yml多文檔配置文件

若我們使用properties只锭,則需要編寫多個(gè)不同的配置文件著恩,但如果我們使用yml的話,則可以通過多文檔配置節(jié)實(shí)現(xiàn)單文件管理蜻展。注:有關(guān)yml相關(guān)的知識(shí)參考此文檔的前半部分喉誊。

可以看到,我們通過---三個(gè)橫線實(shí)現(xiàn)文檔分割纵顾,同時(shí)在每一個(gè)文檔塊處指定了各個(gè)profile的不同配置信息伍茄,即dev環(huán)境下啟動(dòng)服務(wù)使用8082端口,prod環(huán)境下使用8083端口片挂。而指定哪一個(gè)profile則是通過默認(rèn)的文檔塊(即第一塊)中的spring.profiles.active進(jìn)行配置幻林。完成如上配置之后我們啟動(dòng)服務(wù),顯然此時(shí)是以激活的prod環(huán)境所配置的端口8083運(yùn)行的音念,如下啟動(dòng)日志所示:

com.zhaoyi.hello1.Hello1Application      : The following profiles are active: prod
o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8083 (http)

也就說沪饺,當(dāng)我們選定一個(gè)profile后,對(duì)應(yīng)的文檔塊的配置就會(huì)全部生效闷愤。

未完待續(xù)整葡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市讥脐,隨后出現(xiàn)的幾起案子遭居,更是在濱河造成了極大的恐慌,老刑警劉巖旬渠,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱萍,死亡現(xiàn)場離奇詭異,居然都是意外死亡告丢,警方通過查閱死者的電腦和手機(jī)枪蘑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人岳颇,你說我怎么就攤上這事照捡。” “怎么了话侧?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵栗精,是天一觀的道長。 經(jīng)常有香客問我瞻鹏,道長悲立,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任乙漓,我火速辦了婚禮级历,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叭披。我一直安慰自己寥殖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布涩蜘。 她就那樣靜靜地躺著嚼贡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪同诫。 梳的紋絲不亂的頭發(fā)上粤策,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音误窖,去河邊找鬼叮盘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霹俺,可吹牛的內(nèi)容都是我干的柔吼。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼丙唧,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼愈魏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起想际,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤培漏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胡本,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牌柄,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年侧甫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了友鼻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傻昙。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彩扔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情僻爽,我是刑警寧澤虫碉,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站胸梆,受9級(jí)特大地震影響敦捧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碰镜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一兢卵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绪颖,春花似錦秽荤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牍氛,卻和暖如春晨继,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搬俊。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工紊扬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唉擂。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓餐屎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親楔敌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啤挎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361