今日内容
1.配置文件
2.加载顺序
3.配置原理
1.配置文件
1.配置文件
SpringBoot使用一个全局的配置文件:名字固定
* application.properties
* application.yml
配置文件放在:src/main/resources目录或者在:类路径/config
这两个文件SpringBoot都会把它当成全局配置文件。
2.配置文件的作用
由于SpringBoot在地层默认给我们配置好了,全局配置文件可以对一
些默认配置进行修改。
3. application.yml
1.yml是YAML(YAML Ain't Markup Language)语言的文件,以数据为
中心,比json,xml等更适合做配置文件
2.标记语言:Markup Language
以前的配置文件,大多使用的是xxx.XML文件
3.yml:配置端口 以数据为中心
server:
port: 8089
4.XML:配置端口
<server>
<port>8089</port>
</server>
2. YAML语法
1. YAML基本语法:怎么表示属性和值的关系
K: V表示一对键值对(空格必须有);
以空格的缩进来控制层级关系:只要是左对齐的一列数据都是同一层级的;
在yml文件中,不可以使用“tab”键来缩进!缩进要使用空格来缩进;
属性和值也是大小写敏感的。
server:
port: 8089
path: /hello
2. 值的写法
1.字面量:普通的值(数字,字符串,布尔)
K: v 字面量直接来写:
字符串默认不用加上单引号或者双引号。
"":双引号,不会转义字符串里面的特殊字符;特殊字符会
作为本身想表达的意思。
例如:特殊字符作为特殊字符想表达的意思
name: "zhangsan\n lisi"
输出:zhangsan (换行)
lisi
例如:会转义特殊字符,特殊字符最终只是一个普通的字符串数据。
name: 'zhangsan\n lisi'
输出: zhangsan\n lisi
2.对象,Map:属性和值(键值对)
K: V :对象还是K: V的方式
值是对象的时候,第一行对象,下一行对象的属性和值(注意缩进)。
friends:
lastName: zhangsan
age: 20
对象的行内写法:
friends: {lastName: zhangsan,age: 18}
3.数组(List,Set):用-值表示数组中的一个元素
pets:
- cat
- dag
- pig
数组的行内写法:
pets: [cat,dog,pig]
3.将application.yml中配置属性值注入到Bean中
3.1
1.application.yml配置文件:
person:
lastName: zhangsan
age: 18
boss: false
birth: 2019/12/12
maps: {k1: v1, k2: 12}
list:
- lisi
- zhaoliu
- zhangsan
dog:
name: 小狗
age: 2
2.实体类
@Component
@ConfigurationProperties(prefix = "person" )
public class Person {
private String name;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
public String getName () {
return name;
}
}
注意1:@ConfigurationProperties(prefix = "person")
要导入一个SpringBoot配置文件的处理器的依赖。
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true </optional>
</dependency>
注意2:@Component
要想该实体类能起作用,那么必须是Spring容器中的组件,只有
这个组件是容器中的组件,才能使用容器提供的功能。
3. 测试类:
引导器创建的SpringBoot项目会自动生层一个测试类
@SpringBootTest : 说明是一个SpringBoot的单元测试
@RunWith(SpringRunner.class) :
单元测试用SpringBoot的驱动器。此版本该注解可能集成在别处了。
可以在测试期间很方便的进行自动注入的功能
@SpringBootTest
class Day0625SpringBoot01ConfigApplicationTests {
@Autowired
Person person;
@Test
void contextLoads () {
System.out.println(person);
}
}
3.2 配置application.properties
person.name=张三
person.age=15
person.birth=2019/12/01
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.list=a,b,c
person.dog.name=dog
person.dog.age=15
测试时,张三会乱码
解决:
3.3 用@Value注解为单个属性注入
1. 我们以前在配置文件中向IOC容器注入时
<bean class="Person" >
<properties name="lastname" value="" />
</bean>
其中<bean/>是将实体类Person扫描进去
name="lastname"为Person对象中的lastname属性赋值
value="":赋具体的值
有三种写法:
1.valeu="字面量"
@Value("true")
private Boolean boss;
2.value="${key}": 从环境变量,配置文件中获取值
@Value("${person.lastname}")
private String lastname;
3.value="#{SpeL语言}"
@Value("#{11*2}")
private Integer age;
2. 实体类Person
@Component
//@ConfigurationProperties(prefix = "person" )
public class Person {
@Value("${person.lastname} " )
private String lastname;
@Value("#{11*2}" )
private Integer age;
@Value("true" )
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
}
其中@Component就类似<bean/>标签,向IOC注入Person对象
@Value:为单个属性注入
@Value("${person.lastname}")
private String lastname;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
3. 同@ConfigurationProperties的区别:
1.功能
@ConfigurationProperties只需要一个注解,可以为我们批量注入属性。
@Value:只能为单个属性注入。
2. 松散语法
@ConfigurationProperties支持松散于法绑定
Person:
private String lastName;
application.yml:
person:
last-name: 张三
松散绑定将last-name注入到lastName上。
3. 支持SPEL
@ConfigurationProperties不支持
@Value支持
4. JSR303数据校验:
@ConfigurationProperties支持
我们在为属性注入值时,能够校验一下。
如果不满足校验规则,会报错。
@Value不支持
即使在为属性注入时,加入验证也不会生效,所以不会报错。
注意:在使用JSR303数据校验时,要导入一个新的依赖
6.0.0.Alpha5 版本很大
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.0.Final</version>
</dependency>
5. 复杂类型属性注入时:
@ConfigurationProperties支持
@Value不支持
区别小结:
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的
某项值,可以用@Value
@RestController
public class HelloController {
@Value("${person.lastname} " )
private String name;
@RequestMapping("/sayHello" )
public String sayHello (){
return "hello" + name;
}
}
如果说,专门编写了一个javaBean来和配置文件进行映射,我们
就直接使用@ConfigurationProperties。
4.@Property和@ImportResource
4.1 @ConfigurationProperties结合@PropertySource读取指定配置文件
我们知道@ConfigurationProperties能将实体类和配置文件中的值进行绑定。
但是绑定的前提是要求你的属性都写在了application.properties/yml中。
即@ConfigurationProperties默认是从全局配置文件中获取值。
application.properties
application.yml
显然我们不可能将所有的配置都放到一个全局配置文件中,那么一些和SpringBoot
无关的配置,我们就希望放到别的配置文件中。
1.将原来在全局配置中的person.xxx放到person.properties中
将全局配置中的person.xxx注释
person.lastname=李四
person.age=15
person.birth=2019/12/01
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.list=a,b,c
person.dog.name=dog
person.dog.age=15
2. @ConfigurationProperties(prefix = "person")
那么该注解:从全局配置中去前缀是person的值,显然取不到了。
3. 结合@PropertySource:加载指定的配置文件
@PropertySource(value = {"classpath:person.properties"})
告诉SpringBoot来加载类路径下的person.properties的内容,并把它们绑定到
javaBean的属性中。
@Component
@PropertySource(value = {"classpath:person.properties" })
@ConfigurationProperties(prefix = "person" )
public class Person {
private String lastname;
private Integer age;
private Boolean boss;
private Date birth;
}
4.2 @ImportResource
我们自己编写的配置文件,SpringBoot不会自动解析。
@ImportResource导入Spring的配置文件,让配置文件里面的内容生效
1.写了个spring配置文件: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="helloService" class="com.atguigu.day0625_springboot.service.HelloService" ></bean>
</beans>
在里面写了一个<bean/>配置,此时bean.xml没有被解析,所以IOC容器中没有这个bean。
2.测试一下
@Autowired
ApplicationContext ioc;
@Test
public void testHelloService (){
boolean flag = ioc.containsBean("helloService" );
System.out.println(flag);
}
打印结果:false。
3. @ImportResource标注在一个配置类上
我们将其标注在主配置类上:
@ImportResource(locations = {"classpath:beans.xml" })
@SpringBootApplication
public class SpringBoot01ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot01ConfigApplication.class, args);
}
}
导入beans.xml配置文件让其生效。
4.3 SpringBoot推荐给容器中添加组件的方式:使用全注解的方式
一般不推荐使用@ImportResource注解给IOC容器添加组件。
1.写一个配置类
可以在主配置类中写,这里我们专门写一个配置类。
@Configuration
public class MyConfig {
//将方法的返回值添加到容器中:容器中这个组件默认的ID就是方法名
@Bean
public HelloService helloService (){
System.out.println("配置类给容器添加组件了" );
return new HelloService();
}
}
其中:
@Configuration:指明这是一个配置类
@Bean:将方法的返回值添加到容器中:容器中这个组件默认的ID就是方法名
2. 不用再加载指定的配置类了,我们测试一下
5 配置占位符
1. 配置文件中可以使用随机数
person.lastname=张三${random.uuid}
person.age=${random.int}
person.birth=2019/12/01
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.list=a,b,c
person.dog.name=${person.lastname} _dog
person.dog.age=15
2. 测试结果
3. 占位符获取之前配置的值
如果解析不出来时:当作字符串
配置文件中没有person.hello所以当成字符串解析。
4. 为person.hello在占位符中指定值
person.dog.name=${person.hello: 小猫}_dog
6 Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活指
定参数等方式快速切换环境。
6.1 多Profile文件来实现切换环境
1. 我们在主配置文件编写的时候,文件名可以是:application-{profile}.properties/yml
带上profile标识。
A:当前主配置文件:
application.propertise:
server.port=8089
B:比如:我可以再配置两个不同环境的配置文件。
1.application-dev.properties: 开发环境的配置文件
server.port=80
2.application-prod.properties: 生产环境的配置文件
server.port=8090
2 SpringBoot应用默认使用主配置文件中配置的端口号启动,如何切换到其
他环境,然后使用其他环境中配置的配置文件呢?
1.激活开发环境的配置:
在主配置文件中加入如下代码:
spring.profiles.active=dev
启动应用:切换到开发环境,加载开发环境配置。
6.2 yml支持多文档块的方式:实现切换环境
我们用yml文件做主配置文件:application.yml
yml中有一种语法:文档块
激活方式:
spring:
profiles:
active: dev
server:
port: 8089
spring:
profiles:
active: dev
6.3 命令行方式 切换环境
-spring.profiles.active=dev
1.在EidtConfiguration中配置命令行参数
Program arguments: -spring.profiles.active=dev参数
2.测试:
主配置文件中激活的是prod环境
EidtConfiguration中配置的是:dev环境
运行:切换到dev环境
3. 在命令行中 切换环境
将SpringBoot应用打包
到包所在的目录打开命令行
命令行中运行jar包:
java -jar day0625_spring-boot01-config-0.0.1-SNAPSHOT.jar
--spring.profiles.active=dev
发现也是成功的切换到dev环境中。
4. 虚拟机参数
VM options:-Dspring.profiles.active=dev
测试:启动SpringBoot应用
7 配置文件加载优先顺序
1.
SpringBoot启动会扫描一下位置的application.properties/yml文件作为
SpringBoot的默认配置文件
- file:./config
- file:./ 当前项目的根目录下
- classpath:/config
- classpath:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,而且高
优先级配置内容会覆盖低优先级配置内容。
注意:前提是这些配置文件都是主配置文件:application.properties/yml
2.
除了主配置文件覆盖的规则外,还有互补配置:
高优先级的主配置文件,可以覆盖部分内容。其他的配置还用低优先级的配置。
在低优先级的主配置文件中在配置一个项目访问路径:
server.port=8089
server.servlet.context-path=/boot02
结果会将低优先级配置文件中不同于高优先级的内容加载进来。
3.
可以通过配置spring.config.location来改变默认配置。
项目打包好后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件
的新位置。指定配置文件和默认加载的配置文件共同起作用。形成互补配置。
3.1
注意:项目打包时,项目根目录下的的文件不会打进去,打包时这些文件不会打进去。
所以在命令行中启动SpringBoot应用时,优先级最高的是classpath/config
目录下的主配置文件。
3.2
在项目外部新建一个主配置文件:application.properties
命令行启动项目,并加载外部的这个配置,会和默认加载的配置文件共同起作用。
java -jar day0625_springboot02_config-0.0.1-SNAPSHOT.jar --spring.config.location=E:\application.properties
4. 外部配置加载顺序
SpringBoot也可以从以下位置加载配置,优先级从高到低:
1.命令行参数
在命令行启动SpringBoot应用时,用命令行参数修改默认配置,
会和默认加载的配置文件共同起作用。
例如:为项目指定一个新的端口和项目路径
java -jar day0625_springboot02_config-0.0.1-SNAPSHOT.jar
--server.port=8087 --server.server.servlet.context-path=/boot02
多个配置用空格分开:-- 配置项=值
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找
先加载带profile
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
再加载不带profile的
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
加载时,jar包外部(同一级目录)的主配置文件不用参数就会自动加载。
加载顺序如上。
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性