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)行編碼呢浑吟?
- 如果說笙纤,我們只是在某個(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;
}
}
- 但是组力,如果我們專門去寫一個(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)容生效惋戏。
- 添加新的服務(wù)類HelloService
package com.zhaoyi.hello1.service;
public class HelloService {
}
- 在類目錄下創(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è)試一下。
- 編寫測(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 例子
- 在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}
- 測(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
- 在application.properties中指定:
spring.profiles.active=dev
- 命令行方式激活猬错,此配置的優(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
即可逢唤。
- 虛擬機(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ù)整葡。