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