SpringBoot之配置文件
1. 什么是配置文件?
当我们构建完Spring Boot项目后,会在resources目录下给我们一个默认的全局配置文件 application.properties,这是一个空文件,因为Spring Boot在底层已经把配置都给我们自动配置好了,当在配置文件进行配置时,
会修改SpringBoot自动配置的默认值。
2. 配置文件有什么用?
- 修改SpringBoot自动配置的默认值,使我们程序的插件能正常运行(比如Mysql、mybatis配置)。
- 自定义配置属性,便于我们维护程序中的变量值。
3. 配置文件的种类
3.1 .yml(推荐使用)
- YAML:一种标记语言,以数据为中心,比JSON、XML更适合做配置文件,后缀名可以是
.yml
或.yaml
。 - 在SpringBoot中,使用最广泛的配置文件是它,yaml之所以流行,除了他配置语法精简之外,还因为yaml是一个跨编程语言的配置文件 。
- 基本语法
- k:(空格)v;其中k是键,v是值,注意冒号后面有个空格。
- 以空格的缩进为控制层级关系,
左对齐
的一列数据的层级关系是一样的。 - 属性和值都是大小写敏感的。
- .yml配置Tomcat启动端口号示例
server:
port: 8081
3.2 .properties
- 以key=value格式存储内容的文件。
server.port=8081
3.3 .xml
- 传统的Spring配置文件格式。
- 因为其配置繁琐、开发效率稍低、文件解析耗时等原因,.xml配置文件已经不推荐使用。
<?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="xmlTest" class="com.liang.stu.properties.core.XmlTest">
<property name="stringTest" value="abc"/>
<property name="listTest" value="a,b,c"/>
<property name="mapTest">
<map>
<entry key="a" value="1"/>
<entry key="b" value="2"/>
</map>
</property>
</bean>
</beans>
4. SpringBoot配置文件读取优先级
4.1 三种比较方式
- 文件名优先级
application > bootstrap
- 路径优先级
1. file:./config/ (项目根目录中config目录下)
2. file:./ (项目根目录下)
3. classpath:/config/ (项目resources目录中config目录下)
4. classpath:/ (项目的resources目录下)
如下图所示
- 类型优先级
.properties > .yml
4.2 小结
- 三种优先级比较时,只有前者相同,才需比较后面的
文件名优先级 > 路径优先级 > 类型优先级
- 经过测试发现:springboot项目默认并不能读取到bootstrap配置文件,必须加入spring-cloud-context的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
- 所以bootstrap是在cloud项目中才使用的配置文件
- bootstrap.yml 用来程序引导时执行,应用于更加早期配置信息读取. 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等.如果加载的application.yml的内容标签与bootstrap的标签一致,application会覆盖bootstrap, 而application.yml 里面的内容可以动态替换。 - 经过测试发现:配置文件放在项目根目录下时只有是自定义的属性配置才会生效,(比如非自定义的server.port=8081配置不会生效)。
看到这篇博客的人知其原因可留言告知,非常感谢。
5. SpringBoot获取配置文件属性的方法
- 假设有一个 application.yml 配置信息如下
com:
stringTest: abc
listTest: a,b,c
5.1 通过 @Value
注解将对应的属性注入到field上
- 必须将实体类交由SpringBoot自动装配到Spring容器中。使用时依赖注入
@Getter
@Component
public class ValueTest {
@Value("${com.stringTest}")
private String stringTest;
@Value("${com.listTest}")
private List<String> listTest;
}
- 编写测试类
@SpringBootTest
public class ValueTests {
@Resource
private ValueTest valueTest;
@Test
public void test() {
System.out.println(valueTest.getStringTest());
System.out.println(valueTest.getListTest());
}
}
- 运行结果
abc
[a, b, c]
5.2 通过 @ConfigurationProperties
将属性映射给类的属性
@ConfigurationProperties注解只会映射已经被SpringBoot读取的配置文件。
如果你的
.properties
配置还未被SpringBoot读取,可以使用@PropertySource指定。如果你的
application-*.yml
配置还未被SpringBoot读取,可以在application.yml里加入以下配置使SpringBoot读取。
spring:
profiles:
active: common,wx
- 创建PropertySourceTest实体类接收属性映射
@Configuration
@ConfigurationProperties(prefix = "com") //指定前缀
@PropertySource(value = "classpath:test.properties", encoding = "UTF-8") //额外指定需要读取的文件和读取格式
public class PropertySourceTest {
private static String stringTest;
public static String getStringTest() {
return stringTest;
}
public void setStringTest(String stringTest) {
PropertySourceTest.stringTest = stringTest;
}
}
- 编写测试类
@Test
public void test() {
System.out.println(PropertySourceTest.getStringTest());
}
- 运行结果
abc
- 使用
@ConfigurationProperties
方式可以进行配置文件与实体字段的自动映射,但需要字段必须提供set方法才可以。 - 使用
@Value
注解修饰的字段不需要提供set方法。
5.3 利用 Environment (org.springframework.core.env.Environment)
- 直接引入Environment即可
@SpringBootTest
public class EnvironmentTests {
@Resource
private Environment env;
@Test
public void test() {
System.out.println(env.getProperty("com.stringTest"));
System.out.println(env.getProperty("com.listTest"));
}
}
- 运行结果
abc
a,b,c
5.4 通过工具类
5.4.1 .yml 属性文件读取
- 利用
org.yaml.snakeyaml
包下的Yaml
读取配置文件从而获得对应的配置信息。 - 创建
YamlUtil
工具类。
@Slf4j
public class YamlUtil {
private static Map<String, Object> ymlMap = new HashMap<>();
public YamlUtil(String location) {
ymlMap = getYmlMap(location);
}
public static YamlUtil getInstance(String location) {
return new YamlUtil(location);
}
public static Map<String, Object> getYmlMap(String location) {
try {
Yaml yaml = new Yaml();
log.info("开始加载资源:{}", location);
InputStream in = YamlUtil.class.getClassLoader().getResourceAsStream(location);
return yaml.loadAs(in, HashMap.class);
} catch (Exception e) {
log.error("加载资源:{}失败,发生IOException异常,异常信息为:{}", location, e.getMessage(), e);
}
return null;
}
public String getString(String key) {
String separator = ".";
if (!key.contains(separator)) {
return ymlMap.get(key).toString();
}
String[] keys = key.split("\\.");
Map<String, Object> finalMap = new HashMap<>();
for (int i = 0; i < keys.length - 1; i++) {
if (i == 0) {
finalMap = (Map<String, Object>) ymlMap.get(keys[0]);
continue;
}
if (finalMap == null) {
return null;
}
finalMap = (Map<String, Object>) finalMap.get(keys[i]);
}
if (finalMap == null) {
return null;
}
return finalMap.get(keys[keys.length - 1]).toString();
}
}
- 编写测试类
@Test
public void test3() {
System.out.println(YamlUtil.getInstance("application.yml").getString("com.stringTest"));
}
- 运行结果
abc
5.4.2 .properties 属性文件读取
- 利用
org.springframework.core.io.support
包下的PropertiesLoaderUtils
读取配置文件从而获得对应的配置信息。 - 创建
PropertiesUtil
工具类。
@Slf4j
public class PropertiesUtil {
private final Properties properties;
public PropertiesUtil(String location) {
properties = getProperties(location);
}
public static PropertiesUtil getInstance(String location) {
return new PropertiesUtil(location);
}
public String getString(String key) {
return properties.getProperty(key);
}
public static Properties getProperties(String location) {
try {
log.info("加载资源文件:{}", location);
return PropertiesLoaderUtils.loadProperties(
new EncodedResource(
new ClassPathResource(location), "UTF-8"));
} catch (IOException e) {
log.error("加载资源:{}失败,发生IOException异常,异常信息为:{}", location, e.getMessage(), e);
}
return null;
}
}
- 编写测试类
@Test
public void test3() {
System.out.println(YamlUtil.getInstance("application.yml").getString("com.stringTest"));
}
- 运行结果
abc
6. .xml配置文件读取
.xml
配置文件常用结合<bean>
标签,将属性值赋给实体类使用。- 修改
application.yml
允许bean覆盖。
spring:
main:
allow-bean-definition-overriding: true #允许bean覆盖
- 创建 bean.xml。
<?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="xmlTest" class="com.liang.stu.properties.core.XmlTest">
<property name="stringTest" value="abc"/>
<property name="listTest" value="a,b,c"/>
<property name="mapTest">
<map>
<entry key="a" value="1"/>
<entry key="b" value="2">
</entry>
</map>
</property>
</bean>
</beans>
- 创建 XmlTest实体类
public class XmlTest {
private static String stringTest;
private static List<String> listTest;
private static Map<String, Object> mapTest;
public static String getStringTest() {
return stringTest;
}
public void setStringTest(String stringTest) {
XmlTest.stringTest = stringTest;
}
public static List<String> getListTest() {
return listTest;
}
public void setListTest(List<String> listTest) {
XmlTest.listTest = listTest;
}
public static Map<String, Object> getMapTest() {
return mapTest;
}
public void setMapTest(Map<String, Object> mapTest) {
XmlTest.mapTest = mapTest;
}
}
- 编写测试类
@SpringBootTest
public class XmlTests {
@Test
public void test() {
System.out.println(XmlTest.getStringTest());
System.out.println(XmlTest.getListTest());
System.out.println(XmlTest.getMapTest());
}
}
- 运行结果
abc
[a, b, c]
{a=1, b=2}