1 什么是配置文件
- 指
main-resources-Application.properties
或Application.yml
文件,这两个都是全局配置文件 - 若不存在则new file新建
- 用于修改自动配置的默认值
2 YAML语言
-
是一种用于配置文件的标记语言
-
以前的配置文件一般用xml,而YAML以数据为中心(没有那么多开闭标签)
-
语法
-
key:value表示一个键值对,冒号和value之间必须有空格
-
以空格控制缩进来控制层级关系(那么只要左对齐就是同级)
-
区分大小写
-
value的书写
-
普通变量:Key: value
- 双引号,不会转义特殊字符。\n表示回车
- 单引号,会转义,\n是普通字符串
-
对象:用缩进写属性
-
缩进写法
-
行内写法
-
-
数组:用-表示一个元素
-
缩进写法
-
行内写法
Pets: [cat,dog,pig]
-
-
-
PS:写的时候可以注意下面的提示
3 配置文件应用实例:设置端口值
-
new java class:
bean.Person
-
new Java class :
Dog
-
定义Person类和Dog类【
Alt+insert
键,可以一键导入get/set/toString方法】 -
在pom里面导入配置文件处理器的依赖项(不然会not found错误)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
-
写好person的配置文件application.yml
-
把配置文件的值绑定到java类中
-
person类前面加入:
@ConfiguationProperties(perfix="person")
——告诉springboot,本类所有的属性都是由配置文件确定
——perfix,确定将配置文件中哪个属性进行一一映射
-
在person类前面加上@Component
——因为还要是组件内的容器,才能使用容器提供的ConfiguationProperties
-
-
在测试单元里面,注入person,看测试容器收到的person是不是配置文件设置的
这里本来应该是
@Autowired
,但是出现错误。修改成@Autowired(required=false)
解决。
-
运行
contextLoads()
函数,控制台打印出person的信息如下:可见,与配置文件的设置相同。
附代码:
Person.java
package com.atguigu.springboot02config.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
@Override
public String toString() {
return "person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public boolean isBoss() {
return boss;
}
public void setBoss(boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
Dog.java
package com.atguigu.springboot02config.bean;
public class Dog {
private String Name;
private Integer age;
@Override
public String toString() {
return "Dog{" +
"Name='" + Name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
application.yml
person:
lastName: zhangsan
age: 90
boss: false
birth: 2020/10/1
maps: { k1: v1,k2: v2}
lists:
- lisi
- zhaoliu
dog:
name: wawa
age: 2
SpringBoot02ConfigApplicationTests.java
package com.atguigu.springboot02config;
import com.atguigu.springboot02config.bean.Person;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.awt.*;
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringBoot02ConfigApplicationTests<person> {
@Autowired(required = false)
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
4 properties配置文件的写法
- 普通语法:
在application.properties里写入:
person.last-name=xxx
person.age=18
person.birth=2017/10/10
person.boss=false
person.maps.k1=v1
person.k2=14
person.lists=a,b,c
person.dog.name=doggie
person.dog.age=1
设置好后,同样运行contextLoads()
函数,也可以得到正确的person
但是会有中文乱码问题,解决方法:
在idea-setting-搜索file encoding-下方选择UTF-8-勾选Transparent …选项
- 随机数的写法:
person.last-name=kris${ random.uuid}
person.age=${ random.int}
- 为变量设置默认值:
person.dog.name=${ person.hello:hello}_dog
${person.hello:hello}_dog
:如果没有设置过person.hello这个东西,就会原样打印:{person.hello}_dog
${person.hello:hello}_dog
:没有设置过person.hello这个东西,person.hello就会变成默认值hello,总体打印成hello_dog
5 @Value
之前的yml和properties都是用了@ConfiguationProperties
注解,而除此之外还可以使用@Value
注解
如:
@Component
public class Person{
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
}
得到age=22
二者区别如下:
@ConfiguationProperties | @Value | |
---|---|---|
注入 | 批量设置变量值 | 一个个指定 |
松散绑定 | √ | × |
spEL | ×(不可计算) | √ |
JSR303数据校验 | √ | × |
复杂类型(如map) | √ | √ |
- 松散绑定:就是支持下面几种写法意义一样
- spEL(就是能不能计算)
- JSR303数据校验:指可以加上一个@Validated表示要校验某个变量的格式,如@Email表示某个变量必须是邮箱格式,格式错误就会报错
6 加载指定的配置文件
刚刚都是加载全局配置文件application.properties
,现在想加载别的文件来当配置文件
方法1:
- 在resources文件夹-新建文件
person.properties
- 用
@PropertySource(value={classpath:person.properties})
:加载指定配置文件
更推荐的方法(全注解方法):
- 添加配置类:在com下,new java class-
config.MyAppConfig
@Configuration
表明当前类是配置类,相当于配置文件@Bean
将方法的返回值添加到容器中
这是使用配置类给容器添加组件(将方法的返回值添加到容器中),在容器中标识组件的默认id是方法的方法名(helloService)
测试容器中有没有“helloService”这个组件
7 profile 多配置文件
在生产、开发、测试不同环境下,可能需要不同的配置文件来实现不同的配置
而主程序默认使用的是application.properties的配置
实现方法1:
-
在resources文件夹新建
application-pro.properties
(pro环境模拟),application-dev.properties
(dev环境模拟),application-test.properties
(test环境模拟)(注意:格式得是
application-xxx.properties
或者application-xxx.yml
) -
在全局配置
application.properties
头上写spring.profiles.active=dev
,指定哪个环境被激活
实现方法2(文档块方式):
- 在
application.yml
,用---
表示分割,上面叫document1,下面是document2,同理分割多个 - 指定
spring.profiles.active=dev
,如以下代码,运行的就是dev环境的端口,否则默认8081
server:
port: 8081
spring:
profiles:
active: dev
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: pro
8 配置文件加载位置
8.1 内部配置文件
springboot会识别以下四个位置的配置文件,而且是按优先级高到低依次往下
- file指项目的根目录
- classpath指的是类路径,这里是main-resources
识别的时候会覆盖+互补配置
- 覆盖:高优先级和低优先级都有,只采用高优先级的(但是也会加载低的)
- 互补配置:指如果在高优先级没有配置的话会采用低优先级的配置
项目打包好以后启动时,可以使用命令行参数的形式来指定配置文件的新位置,这时候指定的配置文件和默认加载的配置文件共同起作用形成互补配置;
——用于运维,已经打包好了不需要重新打包
8.2 外部配置文件
配置还可以写在这17个位置,同理也有“优先级顺序+覆盖+互补”
其中较为重要的有:
-
命令行形式直接修改配置:
多个参数之间用空格隔开,如–server=… --path=…
-
来自java:comp/env的JNDI属性
-
Java系统属性(System.getProperties())
-
操作系统环境变量
-
RandomValuePropertySource配置的random.*属性值
【由jar包外向jar包内进行寻找; 优先加载带profile,再来加载不带profile】
-
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
-
通过SpringApplication.setDefaultProperties指定的默认属性
所有支持的配置加载来源;
9 @Conditional组件
有些组件需要设置成在特定条件下生效。
@Conditional
这个组件为配置的生效设置了条件,如下表:
那怎么更方便的知道哪些配置生效?
-
在
application.properties
写上debug=true
-
控制台打印信息中,Positive matches 表示生效的,Negetive matches表示没有生效的