SpringBoot之配置文件
本文最后更新于:2021年3月13日 晚上
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}
7. 参考链接
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!