springboot項目的配置文件信息一般放在application.yml(也有命名application.properties)文件中,當項目啓動的時候,我們可以只修改配置文件中的配置,而不修改代碼。如果不在配置文件中配置信息,雖然也可以實現功能,但是容易出現問題。
例如:跨系統交互時,另外一個系統(系統A)的域名或者端口發生變化,我們需要在自己的項目中對其地址信息進行修改。如果不在配置文件中進行配置,我們需要在代碼中修改所有與A系統交互時的訪問地址信息修改,如果存在多處與系統A交互,需要修改多處地方。修改相對較大,而且修改完之後,還需要重新發版。萬一在修改時,不小心碰到了其他代碼,修改了其他代碼邏輯,這上線發版後出問題就麻煩了,就等着背一個線上case事故吧。
如果我們配置在配置中配置改變量,所有用到該變量的地方,我們從配置文件中進行讀取。即使系統A的域名發生變化,我們可以只修改配置文件中改變量的值,不會影響到其他代碼。當然,這時也有人問,你最終還是修改了東西,難免不會粗心大意碰到其他代碼,這不是照樣存在風險嗎?
對於這個問題,可能是問問題的人還沒進入公司工作,也可能是我瞭解的太low了。爲什麼這麼說呢,因爲這些配置文件中的值,是不由程序員進行維護的,一般這些配置文件在公司都是有專門的運維進行維護的,在上線的時候,你提供配置文件的線上配置,運維會對其進行配置或者對你配置的進行覆蓋,因此,由運維進行操作,運維只會修改配置文件中的值,不會修改代碼。(當然這是我所在公司的風格,其他公司我不瞭解)
OK,廢話講這麼多了,開始正題。
1、基本配置變量讀取
首先我們先介紹一下最基本的配置,沒有數組list對象,沒有map對象。
注意:每個鍵也就是(冒號左面的值),鍵之後必須要有一個空格,在idea下,鍵會變成黃色(也就是冒號後面要有一個空格)
配置文件中的配置:
info:
name: mwl
love: lwm
type: alone
對於這種只包含變量的我們一般採取兩種方式取值,推薦第二種方式。
第一種方法,(變量值少時推薦使用種方法,不然需要定義多個變量進行接收):
@Value("${info.name}")
private String NAME;
@Test
public void TestValue(){
System.out.println(NAME);
}
第二種方法,採用**@ConfigurationProperties註解,其中prefix對應配置文件前綴,@Component註解用於添加到容器中,@Data**註解屬於插件lombok中的註解,用於減少get、set以及toString等方法的代碼量。
package com.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: MWL
* @date: 2020/3/6 9:59 上午
**/
@Component
@Data
@ConfigurationProperties(prefix = "info")
public class InfoConfig {
private String name;
private String love;
private String type;
}
單元自測類方法測試:
@Value("${info.name}")
private String NAME;
@Resource
private InfoConfig infoConfig;
@Test
public void TestConfigValue(){
System.out.println("infoConfig.toString():"+infoConfig.toString());
System.out.println("infoConfig.getName():"+infoConfig.getName());
System.out.println("NAME:"+NAME);
}
//程序運行結果如下:
infoConfig.toString():InfoConfig(name=mwl, love=lwm, type=alone)
infoConfig.getName():mwl
NAME:mwl
2、配置變量中嵌套對象
在原有的配置文件中添加(first和second)信息,如:
info:
name: mwl
love: lwm
type: alone
first:
hx: zui
face: yan
way: back
second:
wyy: nose
test: mouse
代碼如下:
package com.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: MWL
* @date: 2020/3/6 9:59 上午
**/
@Component
@Data
@ConfigurationProperties(prefix = "info")
public class InfoConfig {
private String name;
private String love;
private String type;
private First first;
private Second second;
@Data
static class First{
private String hx;
private String face;
private String way;
}
@Data
static class Second{
private String wyy;
private String test;
}
}
運行代碼:
@Value("${info.name}")
private String NAME;
@Value("${info.first.hx}")
private String HX;
@Resource
private InfoConfig infoConfig;
@Test
public void TestConfigValue(){
System.out.println("infoConfig.toString():"+infoConfig.toString());
System.out.println("infoConfig.getName():"+infoConfig.getName());
System.out.println("infoConfig.getFirst():"+infoConfig.getFirst());
System.out.println("HX:"+HX);
}
//程序運行結果:
infoConfig.toString():InfoConfig(name=mwl, love=lwm, type=alone, first=InfoConfig.First(hx=zui, face=yan, way=back), second=InfoConfig.Second(wyy=nose, test=mouse))
infoConfig.getName():mwl
infoConfig.getFirst():InfoConfig.First(hx=zui, face=yan, way=back)
HX:zui
在上述代碼中,存在兩個問題
- First和Second必須被static修飾,不然getFirst輸出爲null。
- 如果我們想要獲取First對象中的屬性,我們發現infoConfig.getFirst()中沒有其相關屬性的get方法
如果我們想要獲取First對象中的屬性我們可以將First和Second對象定義在一個新的類中。如下:
package com.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: MWL
* @date: 2020/3/6 9:59 上午
**/
@Component
@Data
@ConfigurationProperties(prefix = "info")
public class InfoConfig {
private String name;
private String love;
private String type;
private First first;
private Second second;
}
============================================
package com.config;
import lombok.Data;
/**
* @author: MWL
* @date: 2020/3/6 10:56 上午
**/
@Data
public class Second {
private String wyy;
private String test;
}
============================================
package com.config;
import lombok.Data;
/**
* @author: MWL
* @date: 2020/3/6 10:56 上午
**/
@Data
public class First {
private String hx;
private String face;
private String way;
}
//此時我們在運行上述測試類,發現可以獲取到First中的屬性
如果不使用對象嵌套對象的方法,可以在重新定義一套配置prefix = “info.first”,,如果將所有的代碼放在一個類裏,代碼需要稍作改動,如下所示。
代碼如下(爲了便於區分,新建一個類用於測試):
package com.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author: MWL
* @date: 2020/3/6 11:48 上午
**/
@Configuration
public class InfoConfigProperties {
@Data
@Configuration
@ConfigurationProperties(prefix = "info")
public static class InfoConfig{
private String name;
private String love;
private String type;
}
@Data
@Configuration
@ConfigurationProperties(prefix = "info.first")
public static class FirstPlay {
private String hx;
private String face;
private String way;
}
@Data
@Configuration
@ConfigurationProperties(prefix = "info.second")
public static class SecondPlay {
private String wyy;
private String test;
}
}
@Resource
private InfoConfigProperties.FirstPlay firCon;
@Test
public void TestinfoPro(){
System.out.println(firCon.getHx());
}
3、list、map對象讀取
配置文件如下(其中list、map的兩種寫法均可以讀取到對應值,看個人習慣):
person:
name: xiaoming
full-name: 小明
age: 23
boss: false
birth: 1995/10/04
#list: a,b,c,d
# list:
# - a
# - b
# - c
# - d
list: [a,b,c,100]
# map: {key1: value1,key2: value2}
map:
key1: 15
key2: 2
dog:
name: tom
age: 3
java代碼:
package com.config.entity;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @author: MWL
* @date: 2020/3/6 10:53 上午
**/
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private String fullName;
private Integer age;
private Boolean boss;
private Date birth;
private List<String> list;
private Map<String, String> map;
private Dog dog;
}
=====================================
//測試類代碼:
@Autowired
private Person person;
@Test
public void TestPerson(){
System.out.println(person.toString());
System.out.println(person.getDog().getAge());
System.out.println(person.getBoss());
System.out.println(person.getBirth());
System.out.println(person.getList().get(3));
System.out.println(person.getMap().get("key1"));
}
//運行結果:
Person(name=xiaoming, fullName=小明, age=23, boss=false, birth=Wed Oct 04 00:00:00 CST 1995, list=[a, b, c, d], map={key1=value1, key2=value2}, dog=Dog(name=tom, age=3))
3
false
Wed Oct 04 00:00:00 CST 1995
d
value1