【SpringBoot新手篇】SpringBoot配置文件详情
SpringBoot配置文件详情1. Spring Boot的默认配置1.1 配置文件1.2 YAML语法1.2.1 基本语法1.2.2 值的写法2. 配置文件值注入3. @Value获取值和@ConfigurationProperties获取值比较4. 配置文件注入值数据校验5. @PropertySource&@ImportResource&@Bean5.1 获取Spring容
【SpringBoot新手篇】SpringBoot配置文件详情
1. Spring Boot的默认配置
Spring Boot使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。所以,我们要想把Spring Boot玩的溜,就要懂得如何开启各个功能模块的默认配置,这就需要了解Spring Boot的配置文件application.properties。 Spring Boot默认配置文件为CLASSPATH(resources目录)下的application.properties(yml)。
Spring Boot使用了一个全局的配置文件application.properties,可以放在src/main/resources(yml)目录下或者类路径的/config下,总之打包后需要在CLASSPATH下。
Sping Boot的全局配置文件的作用是对一些默认配置的配置值进行修改。
注:如果你工程没有这个application.properties(yml),那就在src/main/java/resources目录下新建一个File,命名为application.properties(yml)。
1.1 配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
配置文件的作用 : 修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;
- YAML(YAML Ain’t Markup Language);
- YAML A Markup Language:是一个标记语言;
- YAML isn’t Markup Language:不是一个标记语言;
标记语言:
以前的配置文件; 大多都使用的是 xxxx.xml文件;YAML : 以数据为中心,比json、xml等更适合做配置文件;
YAML:配置例子
server:
port: 8081
相当于XML:
<server>
<port>8081</port>
</server>
1.2 YAML语法
1.2.1 基本语法
K:(空格)V:表示一对键值对(空格必须有);以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
server:
port: 8081
path: /hello
属性和值也是大小写敏感;
1.2.2 值的写法
- 字面量: 普通的值(数字,字符串,布尔)
K: V:字面直接来写;
字符串默认不用加上单引号或者双引号;
" ":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi":输出:zhangsan \n lisi
' ':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: 'zhangsan \n lisi';输出:zhangsan 换行 lisi
- 对象、Map(属性和值)(键值对)
- K: V:在下一行来写对象的属性和值的关系;注意缩进
对象还是K: V的方式
user:
id: 1
username: 张三
age: 21
行内写法:
user: {id: 1,username: 张三,age: 21}
- 数组(List、Set)
用-值表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
2. 配置文件值注入
application.properties(yml)提供自定义属性的支持,这样我们就可以把一些常量配置在这里:yml:语法中间有空格
name: "张三"
age: 21
然后直接在要使用的地方通过注解@Value(value=”${name}”),使用SPEL表达式取数据,值就可以绑定到你想要的属性上面
@RestController
public class HelloController {
@Value("${name}")
private String username;
@Value("${age}")
private Integer age;
@GetMapping("/")
public String hello(){
return username+"===="+age;
}
}
我们启动工程输入http://localhost:8080 就可以看到打印了”张三====21”。
有时候属性太多了,一个个绑定到属性字段上太累,官方提倡绑定一个对象的bean,这里我们建一个User.java类,顶部需要使用注解@ConfigurationProperties(prefix = "user")来指明使用哪个,注: 必须和属性名对应,否则为null
user:
id: 1
username: "张三"
age: 21
使用 @ConfigurationProperties 注解在idea会给我们提示,需要导入配置文件处理器。
![0]
在pom导入配置文件处理器,以后编写配置就有提示了:
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.1 Environment
使用 Environment 方式来获取配置属性值非常简单,只要注入Environment类调用其方法getProperty(属性key)即可
import org.springframework.core.env.Environment;
@Configuration
public class RedissonConfig {
@Autowired
private Environment env;
/**
* Redisson客户端注册
* 单机模式
*/
@Bean(destroyMethod = "shutdown")
public RedissonClient createRedissonClient() {
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://" + env.getProperty("spring.redis.host") + ":" + env.getProperty("spring.redis.port"));
singleServerConfig.setTimeout(Integer.valueOf(env.getProperty("redisson.timeout")));
return Redisson.create(config);
}
}
2.2 @Value 注解
@Value注解是Spring框架提供的用于注入配置属性值的注解,它可用于类的成员变量、方法参数和构造函数参数上,这个记住很重要!
在应用程序启动时,使用 @Value 注解的 Bean 会被实例化。所有使用了 @Value 注解的 Bean 会被加入到 PropertySourcesPlaceholderConfigurer 的后置处理器集合中。
当后置处理器开始执行时,它会读取 Bean 中所有 @Value 注解所标注的值,并通过反射将解析后的属性值赋值给标有 @Value 注解的成员变量、方法参数和构造函数参数。
需要注意,在使用 @Value 注解时需要确保注入的属性值已经加载到 Spring 容器中,否则会导致注入失败。
使用场景
1、用于注入基本类型和String类型的数据
2、它支持使用spring的EL表达式#{}
3、也可以通过${} 的方式获取配置文件中的数据。配置文件支持properties,xml和yml文件。前提必须导入配置文件,一般和@PropertySource结合使用
在实际开发中,像连接数据库的配置,发送邮件的配置等等,都可以使用配置文件配置起来。此时读取配置文件就可以借助spring的el表达式读取。
application.yml
person:
lastName: zysheep@126.com
url: /user/get,/user/save,/person/get,/person/save
Person实体类中必须要加上 @Component ,使这个类注入到 IOC 容器中,否则 @Value注解不生效
@Component //必须把类加到Spring容器中被管理
@Component //必须把类加到Spring容器中被管理
public class Person {
/**
* 1、用于注入基本类型和String类型的数据。
* 2、它支持使用spring的EL表达式`#{}`
* 3、也可以通过`${} `的方式获取配置文件中的数据。配置文件支持properties,xml和yml文件。前提必须导入配置文件,一般和`@PropertySource`结合使用
*/
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
// ${} 和 #{} 一起使用
@Value("#{'${person.url}'.split(',')}")
private List<String> url;
}
错误使用
1、缺失配置
如果在代码中引用变量,配置文件中未进行配值,就会出现类似下图所示的错误。

为了避免此类错误导致服务启动异常,我们可以在引用变量的同时给它赋一个默认值,以确保即使在未正确配值的情况下,程序依然能够正常运行。

2、静态变量(static)赋值
还有一种常见的使用误区,就是将 @Value 注解加到静态变量上,这样做是无法获取属性值的。静态变量是类的属性,并不属于对象的属性,而 Spring是基于对象的属性进行依赖注入的,类在应用启动时静态变量就被初始化,此时 Bean还未被实例化,因此不可能通过 @Value 注入属性值。
3、常量(final)赋值
@Value 注解加到final关键字上同样也无法获取属性值,因为 final 变量必须在构造方法中进行初始化,并且一旦被赋值便不能再次更改。而 @Value 注解是在 bean 实例化之后才进行属性注入的,因此无法在构造方法中初始化 final 变量。
4、非注册的类中使用
只有标注了@Component、@Service、@Controller、@Repository 或 @Configuration 等容器管理注解的类,由 Spring 管理的 bean 中使用 @Value注解才会生效。而对于普通的POJO类,则无法使用 @Value注解进行属性注入。
5、引用方式不对
如果我们想要获取 TestService 类中的某个变量的属性值,需要使用依赖注入的方式,而不能使用 new 的方式。通过依赖注入的方式创建 TestService 对象,Spring 会在创建对象时将对象所需的属性值注入到其中。
/**
* @value注解 引用方式不对
*/
@Test
public void var7_1Test() {
TestService testService = new TestService();
log.info("引用方式不对 注入: {}", testService.getVar7());
}
2.3 @ConfigurationProperties 注解
@ConfigurationProperties注解是 SpringBoot 提供的一种更加便捷来处理配置文件中的属性值的方式,可以通过自动绑定和类型转换等机制,将指定前缀的属性集合自动绑定到一个Bean对象上。
类上添加@Validated注解,实现JSR303校验
@ConfigurationProperties支持JSR303数据校验,@Value不支持JSR303数据校验。
如果一个类只配置了 @ConfigurationProperties 注解,而没有使用 @Component 注解将该类加入到 IOC 容器中,那么它就不能完成 application.yml配置文件和 Java Bean的数据绑定
application.yml
person:
lastName: zysheep@126.com
age: 18
boss: true
Person实体类中必须要加上 @Component ,使这个类注入到 IOC 容器中
@Data
@Component //必须把类加到Spring容器中被管理
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
//lastName必须是邮箱格式
@Email
private String lastName;
private Integer age;
private Boolean boss;
}
PersonController
@RestController
@RequiredArgsConstructor
public class PersonController {
final Person person;
@GetMapping("/getPerson")
public String testProperties() {
return person.toString();
}
}

注意: 属性不要以isXXX开头,因为实体映射生成的get/set方法会把is去掉,导致set注入的属性值为空
@EnableConfigurationProperties
@EnableConfigurationProperties注解的作用是:让使用了 @ConfigurationProperties 注解的类生效,并且将该类注入到 IOC 容器中,交由 IOC 容器进行管理
实体类有了@EnableConfigurationProperties 注解之后该实体类就不需要加上 @Component 注解了
@Data
// @Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
//lastName必须是邮箱格式
@Email
private String lastName;
private Integer age;
private Boolean boss;
}
PersonController有了@EnableConfigurationProperties 注解之后该实体类就不需要加上 @Component 注解了
@RestController
@RequiredArgsConstructor
@EnableConfigurationProperties(Person.class)
public class PersonController {
final Person person;
@GetMapping("/getPerson")
public String testProperties() {
return person.toString();
}
}
2.4 @PropertySources 注解
除了系统默认的 application.yml 或者 application.properties 文件外,我们还可能需要使用自定义的配置文件来实现更加灵活和个性化的配置。与默认的配置文件不同的是,自定义的配置文件无法被应用自动加载,需要我们手动指定加载。
@PropertySources 注解的实现原理相对简单,应用程序启动时扫描所有被该注解标注的类,获取到注解中指定自定义配置文件的路径,将指定路径下的配置文件内容加载到 Environment 中,这样可以通过 @Value 注解或 Environment.getProperty() 方法来获取其中定义的属性值了。
使用场景
# 我们连接数据库的信息如果直接写到JdbcConfig类中,当需要修改时,就面临修改源码
的问题,此时使用@PropertySource和SpringEL表达式,就可以把配置放到properties
文件中了。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_day01
jdbc.username=root
jdbc.password=root
@Configuration
@PropertySource(value = "classpath:jdbc.properties")
public class MySqlConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
}
但是当我试图加载.yaml文件时,启动项目居然报错了,经过一番摸索我发现,@PropertySources 注解只内置了PropertySourceFactory适配器。也就是说它只能加载.properties文件。

那如果我想要加载一个.yaml类型文件,则需要自行实现yaml的适配器 YamlPropertySourceFactory。
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(encodedResource.getResource());
Properties properties = factory.getObject();
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
}
}
而在加载配置时要显示的指定使用 YamlPropertySourceFactory适配器,这样就完成了@PropertySource注解加载 yaml 文件。
@Configuration
@PropertySource(value = "classpath:jdbc.yml", encoding = "utf-8", factory = YamlPropertySourceFactory.class)
public class MySqlConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
}
2.5 YamlPropertiesFactoryBean 加载 YAML 文件
我们可以使用 YamlPropertiesFactoryBean 类将 YAML 配置文件中的属性值注入到 Bean 中。
@Configuration
public class YamlConfig {
@Bean
public PropertySourcesPlaceholderConfigurer yamlConfigurer() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("zysheep.yml"));
configurer.setProperties(Objects.requireNonNull(yaml.getObject()));
return configurer;
}
}
可以通过 @Value 注解或 Environment.getProperty() 方法来获取其中定义的属性值。
@Value("${user.username:程序员小李}")
private String username;
@Value("${user.age}")
private Integer age;
@GetMapping("/readYmal2")
public R readYaml2() {
return R.success(String.format("username:[%s] == age: [%s]",username, age) );
}

3. @Value获取值和@ConfigurationProperties获取值比较
@Value是以前spring底层的,使用@Value需要一个一个参数指定,@ConfigurationProperties批量注入配置文件中的属性。更多比较如下:
| — | @ConfigurationProperties | @Value |
|---|---|---|
| 功能 | 批量注入配置文件中的属性 | 一个个指定 |
| 松散绑定(松散语法) | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303数据校验 | 支持 | 不支持 |
| 复杂类型封装 | 支持 | 不支持 |
总结: 配置文件yml还是properties他们都能获取到值;如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
4. 配置文件注入值数据校验
类上添加@Validated注解,实现JSR303校验
@ConfigurationProperties支持JSR303数据校验,@Value不支持JSR303数据校验。
@Component //必须把类加到Spring容器中被管理
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
/**
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
* <bean/>
*/
//lastName必须是邮箱格式
//@Email
//@Value("${person.last-name}")
private String lastName;
//@Value("#{11*2}")
private Integer age;
//@Value("true")
private Boolean boss;
}
5. @PropertySource&@ImportResource&@Bean
@PropertySource:加载指定的配置文件;
person.properties
person.last-name=hfbin
person.age=23
person.boss=true
Person.java
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
}
@ImportResource: 导入Spring的配置文件,让配置文件里面的内容生效;Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
@SpringBootApplication
@ImportResource(locations = "classpath:beans.xml")
public class Panyucable01Application {
public static void main(String[] args) {
SpringApplication.run(Panyucable01Application.class, args);
}
}
SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式
- 配置类 @Configuration ------>Spring配置文件
- 使用 @Bean 给容器中添加组件
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
*
* 在配置文件中用<bean><bean/>标签添加组件
*
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public Person person(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new Person();
}
}
5.1 获取Spring容器
SpringBoot平台下采用ApplicationContextAware的方式完成ApplicationContext实例的获取,并通过ApplicationContext实例完成对Spring管理的Bean实例手动获取。
@Component
public class BeanUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
private static final Logger logger = LoggerFactory.getLogger(BeanUtils.class);
/**
* Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContext方法
* @param applicationContext
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
if(BeanUtils.applicationContext == null) {
BeanUtils.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
6. 配置文件占位符
6.1 随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
6.2 占位符获取之前配置的值,如果没有可以是用:指定默认值
可以在配置文件中引用前面配置过的属性(优先级前面配置过的这里都能用)。
person.last-name=张三${random.uuid}
person.name=$person.last-name}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
# ${person.hello:默认值} 来指定找不到属性时的默认值
person.dog.age=15
7. Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、 指定参数等方式快速切换环境 。
7.1 多Profile文件
我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml
比如开发环境:application-dev.properties
生产环境 :application-prod.properties
默认使用application.properties的配置
7.2 yml支持多文档块方式
server:
port: 8081
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
7.3 激活指定profile
- 在配置文件
application.properties中指定spring.profiles.active=dev - 命令行: 可以直接在测试的时候,配置传入命令:
java -jar spring-boot-panyucable-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
- 虚拟机参数
-Dspring.profiles.active=dev
7.4 配置文件加载位置
项目内部配置文件
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
1、–file:./config/
2、–file:./
3、–classpath:/config/
4、–classpath:/
1、config/application.properties(项目根目录中config目录下)
2、config/application.yml
3、application.properties(项目根目录下)
4、application.yml
5、resources/config/application.properties(项目resources目录中config目录下)
6、resources/config/application.yml
7、resources/application.properties(项目的resources目录下)
8、resources/application.yml
- 优先级由高到底,高优先级的配置会覆盖低优先级的配置;
- SpringBoot会从这四个位置全部加载主配置文件;互补配置;
- 我们还可以通过spring.config.location来改变默认的配置文件位置,项目打包好以后,
我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
外部配置加载顺序
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
注意: 聚合工程下,在子项目中使用方式二加载application.yml配置文件不生效
SpringBoot项目在打包的时候,只会把 main 目录下的文件打包,而test、以及自己新建的config等目录是不会被打到jar包里的
SpringBoot也可以从以下外部位置加载配置:优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。
-
命令行参数
- 所有的配置都可以在命令行上进行指定;
- 多个配置用空格分开; –配置项=值
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
-
来自java:comp/env的JNDI属性
-
Java系统属性(System.getProperties())
-
操作系统环境变量
-
RandomValuePropertySource配置的random.*属性值
-
jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
-
jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
-
jar包外部的application.properties或application.yml(不带spring.profile)配置文件
-
jar包内部的application.properties或application.yml(不带spring.profile)配置文件
-
@Configuration注解类上的@PropertySource ,(yaml文件不支持@PropertySource )。例:
外部配置。外部配置使用file,类路径使用classpath@Configuration @PropertySource(value = {"file:/xxx/xxx/config/xxxConfig.properties"}, encoding = "utf-8")
更多推荐



所有评论(0)