SpringBoot配置文件
一、全局配置文件
全局配置文件能对一些默认配置值进行修改。SpringBoot使用application.properties或者application.yaml的文件作为全局配置文件,存放在src/main/resource目录或者类路径的/config。
1. application.properties配置文件
- 语法为k-v结构,
key=value
- 默认为String数据类型,不需要添加双引号
""
,否则会被解析为带双引号的字符串 - properties的默认编码格式为
ISO-8859-1
,因此添加中文时需要转义 - 通过@PropertySource(value=“classpath:xx.properties”, encoding=“UTF-8”)注解配置自定义文件,注意文件名不能是springboot默认的application.properties文件名称,否则获取中文会乱码
- 注释为
#
开头
示例:
#端口号
server.port=8080
2. application.yml配置文件
- 语法为k-v结构,
key: value
,注意冒号后必须要有一个空格但实质上还是key=value - key与key之间可以有父子关系,子前面要有缩进
- yml的默认编码格式为
UTF-8
,因此可以使用中文 - 注释为
#
开头
示例:
sever:
port: 8080
二、配置文件详解
1. 不同类型的配置方式
1.1 普通数据类型(数字,字符串,布尔等)
properties与yaml一样,value直接写即可,字符串类型也不需要加引号
1.2 数组或单列集合
properties写法为逗号分隔,如
demo.array=a,b,c #数组
demo.list=a,b,c #单列集合
yaml有两种书写方式,缩进式写法和行内式写法:
#缩进式写法
demo:
array: [a,b,c] #数组,中括号可省略
list: [a,b,c] #单列集合,中括号可省略
#行内式写法
demo:
array1:
- a
- b
- c
array2:
a,
b,
c
1.3 Map集合或对象
properties写法:
#Map .key=value
demo.map.key1=value1
demo.map.key2=value2
#对象 .属性名=值
demo.student.name=xiaocchen
demo.student.age=20
yaml有两种书写方式,缩进式写法和行内式写法:
#缩进式写法(需要大括号包含)
demo:
map: {key1:value1,key2:value2}
#行内式写法
demo:
map:
key1: value1
key2: value2
2. 配置文件属性值的注入方式
2.1 使用@Value注入属性
该注解是Spring框架提供的,用来读取配置文件中的属性并逐个注入Bean对象的对应属性中(只能是普通数据类型)。
@Componet
public class Student {
@Value("${student.id}")
private Integer id;
}
2.2 使用@ConfigurationProperties注入属性
该注解是SpringBoot框架提供的,可以快速、方便地将配置文件中属性批量注入到某个Bean对象的多个对应属性中(可以是各种类型)。
需要引入依赖,配置依赖后需重启启动项目或者build(Ctrl+F9),application的配置项就会识别自定义属性并有代码提示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
#application.properties
student.id=1
student.name=xiaochen
@Componet
@ConfigurationProperties(prefix = "student") //指定前缀名
public class Student {
private Integer id;
private String name;
//必须得有setter,此处省略
}
2.3 @Value与@ConfigurationProperties的对比
@Value | @ConfigurationProperties |
---|---|
Spring框架 | SpringBoot框架 |
可以直接为属性赋值,无需setter | 必须要有setter |
只能注入普通数据类型 | 可以注入复杂类型 |
不支持JSR303数据校验 | 支持JSR303数据校验 |
支持SpEL表达式 | 不支持SpEL表达式 |
不支持松散绑定 | 支持松散绑定 |
什么是松散绑定?
如有一个为属性为helloWorld,配置文件中可以是helloWorld、hello-world、hello_world、HELLO_WORLD
什么是JSR303数据校验?
主要作用是校验配置文件中注入对应Bean属性的值是否符合相关规定,不符合会报错,如
@Componet @ConfigurationProperties(prefix = "student") //指定前缀名 @Validated //引入Spring框架支持的数据校验规则 public class Student { private Integer id; @Email //邮件规则校验 private String email; //必须得有setter,此处省略 }
什么是SpEL表达式?
全拼为Spring Expression Language,可以进行一些简单的运算,自定义一些解析规则,如
@Componet public class Student { @Value("#{2*3}") private Integer id; @Value("#{'xiaochen'}") //获取字符串 private String name; @Value("#{person.sex}") //获取bean对象person的sex属性 private Integer age; }
3. 自定义配置
之前聊的都是直接从application,properties或application.yaml中获取属性。
3.1 使用@ImportResource加载XML配置文件
@ImportResource注解标注在一个配置类上,通常会放在应用启动类上,使用时需要指定XML配置文件的路径和名称。
示例:
启动类上加@ImportResource("classpath:config/beans.xml")
。
创建一个类MyConfig.java
package com.xc.config;
public class MyConfig {}
此时的MyConfig是不会被SpringBoot所扫描到的,接下来在resource的config目录下创建一个beans.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="myConfig" class="com.xc.config.MyConfig"/>
</beans>
通过以下测试,输出为true时说明已经成功注入
@Autowired
//import org.springframework.context.ApplicationContext;
private ApplicationContext applicationContext;
@Test
void contextLoads() {
System.out.println(applicationContext.containsBean("myConfig"));
}
3.2 使用@Configuration自定义配置类
更多的使用@Configuration配置类代替XML配置,它的作用和XML配置一样,可以通过@Bean注解将对象注入到Spring容器,默认方法名就是组件名。
示例:
依然对上面的MyConfig类实现注入
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
@Configuration //定义该类是一个配置类
public class MyConfiguration {
@Bean //将返回值对象作为组件添加到Spring容器中,该组件id默认为方法名
public MyConfig myConfig() {
return new MyConfig();
}
}
3.3 加载配置文件还用到的一些注解
-
@PropertySource
指定自定义配置文件的路径和名称如:
@PropertySource(value = "classpath:config/student.properties")
。@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(PropertySources.class) public @interface PropertySource { /** * 指明此属性源的名称。如果省略,将根据底层资源生成名称 */ String name() default ""; /** * 指定资源路径。 * 例如classpath:/xxx/xxx或file:/xxx/xxx/xx */ String[] value(); /** * 忽略未找到资源,默认否。spring4.0 */ boolean ignoreResourceNotFound() default false; /** * 指定资源文件的编码格式。spring4.3 */ String encoding() default ""; /** * 指定资源工厂,不指定时使用默认的资源工厂。 */ Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class; }
-
@EnableConfigurationProperties
该注解表示开启对应配置类的属性诸如功能,该注解配合@ConfigurationProperties一起使用,之前都是使用的@Component注解而非@Configuration注解,所以@EnableConfigurationProperties可以省略。如
@EnableConfigurationProperties(MyConfig.class)
来一波总结性的案例:
#resource/config/student.properties
student.id=1
student.name=xiaochen
@Configuration //自定义配置类
@PropertySource(value = "classpath:config/student.properties") //指定配置文件路径名称
@EnableConfigurationProperties(Student.class) //开启对应配置类的属性注入功能
@ConfigurationProperties(prefix="student") //指定配置文件注入属性前缀
public class Student {
private Integer id;
private String name;
//省略setter、getter、toString
}
4. 多环境配置
应用程序一般会部署到不同的环境中去,如开发环境(dev)、测试环境(test)、生产环境(prod)等。
激活配置环境的方法主要有两个(以开发环境为例):
- 控制台执行激活命令:
java -jar xxx.jar --spring.profiles.active=dev
- 全局配置文件中设置:
spring.profiles.active=dev
4.1 配置文件分割法
---
可以分割文件,只需要修改spring.profiles.active
的值为对应的环境配置的spring.profiles
的值即可切换不同环境。
spring:
profiles:
active: dev #指定环境
---
server:
port: 8081
spring:
profiles: dev #定义环境名称
---
server:
port: 8082
spring:
profiles: test
---
server:
port: 8083
spring:
profiles: prod
4.2 Profile文件多环境配置
文件名需满足:application-{profile}.properties
格式,{profile}对应环境标识
创建编写对应的配置文件:
application-dev.properties //开发环境文件
application-test.properties //测试环境文件
application-prod.properties //生产环境文件
4.3 @Profile注解进行多环境配置
该注解用于进行多环境配置,并通过属性标识配置环境,无论使用Profile文件还是@Profile注解类都可以进行多环境配置,而且相互之间不会干扰。
示例:
public interface MyConnector {
void configure();
}
@Configuration
@Profile("dev") //指定多环境配置类标识-dev
public class DevMyConnector implements MyConnector {
@Override
public void configure() {
System.out.println("配置--DEV");
}
}
@Configuration
@Profile("test") //指定多环境配置类标识-test
public class TestMyConnector implements MyConnector {
@Override
public void configure() {
System.out.println("配置--TEST");
}
}
配置文件中spring.profiles.active为dev,通过测试可以正常输出"配置–DEV"字样。
@RestController
public class MyController {
@Autowired
private MyConnector myConnector;
@GetMapping("/showProfile")
public void showProfile(){
myConnector.configure();
}
}
5. 配置参数的一些玩法
SpringBoot除了直接配置属性外,还可以使用随机值和参数之间引用对属性值进行设置。
5.1 随机值
随机值使用了内嵌的RandomValuePropertySource类,语法格式为${random.xxx}
,xxx表示生成随机数的类型和范围。
demo.string=${random.value} #配置随机字符串
demo.number=${random.int} #配置随机整数
demo.bigNumber=${random.long} #配置随机long类型数
demo.uuid=${random.uuid} #配置UUID
demo.scopeNumber=${random.int(10)} #配置小于10的随机整数
demo.intervalNum=${random.int[100,200]} #配置范围[100,200]之间随机整数
5.2 参数之间的引用
语法格式${xx}
,xx表示已经配置过的属性名,如:
demo.name=xiaochen
demo.desc=my name is ${demo.name}
6. Spring Boot中application配置文件读取顺序
如果不同目录下有多个配置文件,读取顺序如下:
- 项目根目录/config/application.properties
- 项目根目录/config/application.yml
- 项目根目录/application.properties
- 项目根目录/application.yml
- resources/config/application.properties
- resources/config/application.yml
- resources/application.properties
- resources/application.yml
7. 可能遇到的一些问题
7.1 为什么获取配置文件属性时中文乱码?
通过@PropertySource(value=“classpath:xx.properties”, encoding=“UTF-8”)注解配置自定义文件,注意文件名不能是springboot默认的application.properties文件名称。或者直接采用yaml的配置文件,默认编码格式为UTF-8
,因此可以使用中文。
7.2 为什么获取yml的配置属性是null?
解决方法一:
当指定的配置文件与默认配置文件在同一级的话,可以通过在默认配置文件中配置spring.profiles.include属性,此时你指定的配置文件名得是application-xxx.yml,然后application.yml中可如下配置解决null问题:
spring:
profiles:
include: xxx #可逗号配置多个
解决方法二:
当前springboot版本的@ConfigurationProperties默认配置properties配置文件,不支持yml文件,这是可以继承DefaultPropertySourceFactory重写它的createPropertySource方法:
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
return new YamlPropertySourceLoader().load(resource.getResource().getFilename(),resource.getResource()).get(0);
}
}
然后@PropertySource指定路径名称时再指定该工厂:
@PropertySource(value = "classpath:config/student.yml",factory = YamlPropertySourceFactory.class)