application.properties/yml文件就是用来修改默认配置信息的配置文件。application.properties / application.yml就是同一个配置文件,后缀名的不同,表示这个文件中内容的书写风格不同。
优先级:properties优先级高于yml,优先读取properties使用
优先读取系统的application.properties/yml
查找需要修改的默认配置信息的键名称:
修改默认配置信息的配置文件spring-boot-autoconfigure:2.6.4.jar-->META-INF-->spring.factories--># Auto Configure-->找到自己需要的自动配置类-->@EnableConfigurationProperties({DataSourceProperties.class})-->DataSourceProperties.class
-->@ConfigurationProperties(prefix = "spring.datasource")
配置依赖包【有提示功能】
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
1.application.yml
1.1基本语法
- key:value key冒号后面要有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- #表示注释
- 单引号和双引号表示的字符串内容会被转义/不转义
1.2 数据类型使用演示
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class PersonBean {
private Integer age;
private Boolean boss;
private String username;
private Date birth;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String,Object> score;
private Set<Double> salarys;
private Map<String,List<Pet>> allPets;
}
@Data
public class Pet {
private String name;
private Double weight;
}
application.yml
#int类型
#boolean类型
person:
age: 23
boss: false
#String类型
# username: 张三
# username: "zhangsan \n lisi" 如果不想被转义,就要双引号,会换行
# username: 'zhangsan \n lisi' 如果想被转义,就要单引号,不会换行
username: 'zhangsan \n lisi'
#Date类型
birth: 2022/03/25
#数组类型写法1
# interests: [篮球,足球,羽毛球]
#数组类型写法2
interests:
- 篮球
- 足球
- 羽毛球
# 集合类型写法1
# animal:
# - 喵喵
# - 汪汪
# - 兔兔
# 集合类型写法2
animal: [喵喵,汪汪,兔兔]
# 对象类型写法1
# pet:
# name: 喵喵
# weight: 30.6
# 对象类型写法2
pet: {name: 喵喵,weight: 30.6}
# pet: {"name": "喵喵","weight": 30.6} 写不写双引号都行
# set集合类型写法1
# salarys: [2.2,1.5,2.0]
# set集合类型写法2
salarys:
- 2.2
- 1.5
- 2.0
# Map<String, Object>类型写法1
# score:
# english: 99.9
# math: 125
# Map<String, Object>类型写法2
score: {english: 88.5,math: 120}
#Map<String, List<Pet>>类型
allPets:
sick:
- {name: 喵喵,weight: 22}
- name: 汪汪
weight: 33
height:
- { name: 兔兔,weight: 55 }
- name: 牛牛
weight: 44
总结一下:集合类要么[ ],要么-分级;对象类要么{ },要么直接分级;map同对象
测试类:
package com.weiwei.springdemo2;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;
@SpringBootTest
class Springdemo2ApplicationTests {
@Autowired
private PersonBean personBean;
@Test
void test1() {
System.out.println("age===="+personBean.getAge());
System.out.println("boss===="+personBean.getBoss());
System.out.println("username===="+personBean.getUsername());
System.out.println("date===="+personBean.getBirth());
System.out.println("===========================================");
for (String interest:personBean.getInterests()) {
System.out.println("interest===="+interest);
}
System.out.println("===========================================");
for (String animal:personBean.getAnimal()) {
System.out.println("animal===="+animal);
}
System.out.println("===========================================");
System.out.println("pet.name====="+personBean.getPet().getName());
System.out.println("pet.weight====="+personBean.getPet().getWeight());
System.out.println("===========================================");
for (Double salary:personBean.getSalarys()){
System.out.println("salary===="+salary);
}
System.out.println("===========================================");
for (Map.Entry<String,Object> entry:personBean.getScore().entrySet()) {
System.out.println(entry.getKey()+"====="+entry.getValue());
}
System.out.println("===========================================");
for (Map.Entry<String, List<Pet>> entry : userBean.getAllPets().entrySet()) {
System.out.println(entry.getKey() + "=====" + entry.getValue());
}
}
输出:
age====23
boss====false
username====zhangsan \n lisi
date====Fri Mar 25 00:00:00 CST 2022
===========================================
interest====篮球
interest====足球
interest====羽毛球
===========================================
animal====喵喵
animal====汪汪
animal====兔兔
===========================================
pet.name=====喵喵
pet.weight=====30.6
===========================================
salary====2.2
salary====1.5
salary====2.0
===========================================
english=====88.5
math=====120
===========================================
sick=====[Pet(name=喵喵, weight=12.23), Pet(name=汪汪, weight=22.0)]
health=====[Pet(name=兔兔, weight=33.0), Pet(name=牛牛, weight=44.0)]
2.application.properties
2.1 使用注意事项
- 使用键值对方式,k=v
- properties文件中的中文输出可能会乱码------解决方案:
修改编码,然后properties文件重新创建才会生效。
- 字符串中有转义字符需要转义的话,加\,如\\n
2.2 数据类型使用演示
application.properties
#int boolean String Date
user.age=23
user.boss=true
user.birth=2022/03/25
user.username=张三
#数组型
user.interests=喵喵,汪汪,兔兔
#list集合型写法1
#user.animal=喵喵,汪汪,兔兔
user.animal[0]=喵喵
user.animal[1]=汪汪
user.animal[2]=兔兔
#d对象型
user.pet.name=喵喵
user.pet.weight=111
#set集合类型
user.salarys=20,30,22
#Map<String, Object>类型
user.score.english=120
user.score.math=130
#Map<String, List<Pet>>类型
user.all-pets.sick[0].name=喵喵
user.all-pets.sick[0].weight=12.23
user.all-pets.sick[1].name=汪汪
user.all-pets.sick[1].weight=22
user.all-pets.health[0].name=兔兔
user.all-pets.health[0].weight=33
user.all-pets.health[1].name=牛牛
user.all-pets.health[1].weight=44
输出:
age====23
boss====true
username====张三
date====Fri Mar 25 00:00:00 CST 2022
===========================================
interest====喵喵
interest====汪汪
interest====兔兔
===========================================
animal====喵喵
animal====汪汪
animal====兔兔
===========================================
pet.name=====喵喵
pet.weight=====111.0
===========================================
salary====20.0
salary====30.0
salary====22.0
===========================================
english=====120
math=====130
===========================================
sick=====[Pet(name=喵喵, weight=12.23), Pet(name=汪汪, weight=22.0)]
health=====[Pet(name=兔兔, weight=33.0), Pet(name=牛牛, weight=44.0)]
3.自定义配置类xxx.properties注值
sss.properties同application.properties
#int boolean String Date
user.age=27
user.boss=true
user.birth=2022/03/25
user.username=张三
#数组型
user.interests=喵喵,汪汪,兔兔
#list集合型写法1
#user.animal=喵喵,汪汪,兔兔
user.animal[0]=喵喵
user.animal[1]=汪汪
user.animal[2]=兔兔
#d对象型
user.pet.name=喵喵
user.pet.weight=111
#set集合类型
user.salarys=20,30,22
#Map<String, Object>类型
user.score.english=120
user.score.math=130
#Map<String, List<Pet>>类型
user.all-pets.sick[0].name=喵喵
user.all-pets.sick[0].weight=12.23
user.all-pets.sick[1].name=汪汪
user.all-pets.sick[1].weight=22
user.all-pets.health[0].name=兔兔
user.all-pets.health[0].weight=33
user.all-pets.health[1].name=牛牛
user.all-pets.health[1].weight=44
UserBean
@Data
@Component
@ConfigurationProperties(prefix = "user")
@PropertySource(value = "classpath:sss.properties")
这两个不能少,少了不行
public class UserBean {
private Integer age;
private Boolean boss;
private String username;
private Date birth;
private Pet pet;
private String[] interests;
private List<String> animal;
private Set<Double> salarys;
private Map<String, Object> score;
private Map<String, List<Pet>> allPets;
}
测试都可以拿到值
测试自定义yml不行
4.@Value数据值与bean类中的成员变量绑定
(1)绑定int、boolean、date、String、List、Set类型时直接@Value(“值”)
UserBean
@Data
@Component
public class UserBean {
@Value("100")
private Integer age;
@Value("true")
private Boolean boss;
@Value("张三")
private String username;
@Value("2022/03/25")
private Date birth;
@Value("足球,篮球,羽毛球")
private String[] interests;
@Value("喵喵,牛牛,猪猪")
private List<String> animal;
@Value("11,22,33")
private Set<Double> salarys;
}
测试:
@Autowired
private UserBean userBean;
@Test
void test1() {
System.out.println("age====" + userBean.getAge());
System.out.println("boss====" + userBean.getBoss());
System.out.println("username====" + userBean.getUsername());
System.out.println("date====" + userBean.getBirth());
System.out.println("===========================================");
for (String interest : userBean.getInterests()) {
System.out.println("interest====" + interest);
}
System.out.println("===========================================");
for (String animal : userBean.getAnimal()) {
System.out.println("animal====" + animal);
}
System.out.println("===========================================");
for (Double salary : userBean.getSalarys()) {
System.out.println("salary====" + salary);
}
输出:
age====100
boss====true
username====张三
date====Fri Mar 25 00:00:00 CST 2022
===========================================
interest====足球
interest====篮球
interest====羽毛球
===========================================
animal====喵喵
animal====牛牛
animal====猪猪
===========================================
salary====11.0
salary====22.0
salary====33.0
(2)对象类型--@Value不支持复杂类型,不能直接注入对象类型的数据
对象无法直接用@Value()注入,可以直接在这个类里面给这个类的成员变量注入就好
(3)Map集合类型
UserBean类
@Data
@Component
public class UserBean {
@Value("#{{english:120,math:140}}")
private Map<String, Object> score;
}
测试:
for (Map.Entry<String, Object> entry : userBean.getScore().entrySet()) {
System.out.println(entry.getKey() + "=====" + entry.getValue());
}
输出:
english=====120
math=====140
5. @PropertySource+@Value
通过@PropertySource({"classpath:xxxx.properties","classpath:xxx.properties"})注解和@Value注解将.properties资源文件中的数据绑定到javabean类中的成员变量。
测试Map类型
TestBean类
@Data
@Component
@PropertySource("classpath:test.properties")
public class TestBean {
@Value("#{${stumap}}")
//${stumap}从文件中引值{myname: 'testmap',myage: '23'}
private Map<String, String> stumap;
}
测试:
@Test
void test2() {
for (Map.Entry<String, String> entry : testBean.getStumap().entrySet()) {
System.out.println(entry.getKey() + "=====" + entry.getValue());
}
}
输出:
myname=====testmap
myage=====23
6. @Value中#{表达式}与 ${表达式}区别
@Value("#{}") Spring 表达式语言(简称SpEL) 可以进行数据运算 / 类型转换
@Value("${xxxxx}") 单一的从配置文件中引用数据值,读取数据值 ,不会进行数据运算 / 类型转换
7.@value和@configurationproperties注解的区别
8.Profiles文件
Profifile文件就是用来配置在不同环境下的配置数据。因为在不同的环境下配置文件中配置的运行环境的数据是不同的,所以我们就需要灵活的在不同的运行环境下切换成对应的运行环境的数据,此时我们将不同的运行环境数据,配置到不同的配置文件中,通过在主配置文件application.properties中的spring.profiles.active属性完成切换。
application-dev.properties【开发环境配置】
server.port=8080
application-prod.properties【生产环境配置】
server.port=9090
application.properties
spring.profiles.active=指定dev还是prod【指定使用生产环境配置】
比如spring.profiles.active=dev
则测试:http://localhost:8080/......
第一种激活profile的方式,即在application.properties中指定属性spring.profiles.active的值。但是这种方式在实际项目中的使用并不合适,因为你每次提交代码还要手动修改spring.profiles.active的值。
第二种可以使用命令行的方式,Spring Boot的程序一般是打成jar包,在使用java -jar 执行jar包的时候,可以再后面加上:
--spring.profiles.active=dev;
例:
java -jar target/spring-boot-helloworld-0.0.1.jar --spring.profiles.active=prod
测试.yml配置同理
application-devyml.yml【开发环境配置】
server:
port: 8080
application-prodyml.yml【生产环境配置】
server:
port: 9090
application.yml 【主配置】
spring:
profiles:
active: prodyml 【指定使用生产环境配置】
http://localhost:9090/testInfo
spring:
profiles:
active: devyml 【指定使用开发环境配置】
9.主配置文件加载位置
spring boot 启动会扫描以下位置的application.properties或者 application.yml文件作为Spring boot的默认配置文件
– 项目根目录/config/
– 项目根目录/
– resource/config/
– resource:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。
SpringBoot会从这四个位置全部加载主配置文件;互补配置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar testspringboot02-0.0.1-SNAPSHOT.jar --spring.confifig.location=F:/application.properties
10.外部配置加载顺序
Spring Boot 支持多种外部配置方式
1. 命令行参数
2. 来自java:comp/env的JNDI属性
3. Java系统属性(System.getProperties())
4. 操作系统环境变量
5. RandomValuePropertySource配置的random.*属性值
6. jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
8. jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9. jar包内部的application.properties或application.yml(不带spring.profile)配置文件
优先加载带profifile,再来加载不带profifile,由jar包外向jar包内进行寻找
10. @Configuration注解类上的@PropertySource
11. 通过SpringApplication.setDefaultProperties指定的默认属性