一、配置文件:文件名是固定的
--SpringBoot使用一个全局的配置文件
application.properties
application.yml
配置文件的作用:修改SpringBoot自动配置的默认值
SpringBoot在底层都给我们自动配置好
配置文件放在src/main/resources目录或者类路径/config下
yml是YAML(YAML Ain't Markup Language)语言的文件,以数据为中心,比json、xml等更适合做配置文件
YAML A Markup Language;是一个标记语言
YAML isn't Markup Language:不是一个标记语言
标记语言:
以前的配置文件,大多都使用的是xxx.xml文件
YAML:以数据为中心,比json、xml等更适合做配置文件
YAML:配置例子
server:
port:8081
YAML语法:
1.基本语法
k: (空格)v :(空格)表示一对键值对,空格必须有
以空格的缩进来控制层级关系;只要是左对其的一列数据,都是同一层级的;
属性和值大小写敏感
2.值的写法:
字面量:普通的值(数字,字符串,布尔)
k: v: 字面量直接来写
字符串默认不用加单引号和双引号
对象(属性和值)(键值对);
friends:
lastname: zhangsan
age: 20
行内写法:
friends: { lastname: zhangsan,age: 18}
数组(集合)
用-值表示数组中的一个元素
pets:
- cat
- dog
行内写法:
pets: [cat,dog]
获取配置文件值
例子:
新建application.yml
格式如下图:
person:
lastName: zhangsan
age: 18
boss: false
date: 2017/12/01
maps: {k1: v1,k2: v2}
lists:
-lisi
-zhaoliu
-wangwu
dog:
name:小狗
age:2
新建Person.java和Dog.java
Person.java
packagecom.example.demo.bean;
importorg.springframework.boot.context.properties.ConfigurationProperties;
importorg.springframework.stereotype.Component;
importjava.util.Date;
importjava.util.List;
importjava.util.Map;
/**
*将配置文件中配置的每一个属性的值,映射到这个组件中
*@ConfigurationProperties:
*告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
*prefix="person":配置文件中哪个下面的属性进行一一映射
*只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能
*/
@Component
@ConfigurationProperties(prefix="person")
publicclassPerson{
privateStringlastName;
privateIntegerage;
privateBooleanboss;
privateDatedate;
privateMap
privateListlists;
privateDogdog;
@Override
publicStringtoString(){
return"Person{"+
"lastName='"+lastName+'\''+
",age="+age+
",boss="+boss+
",date="+date+
",maps="+maps+
",lists="+lists+
",dog="+dog+
'}';
}
publicStringgetLastName(){
returnlastName;
}
publicvoidsetLastName(StringlastName){
this.lastName=lastName;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
publicBooleangetBoss(){
returnboss;
}
publicvoidsetBoss(Booleanboss){
this.boss=boss;
}
publicDategetDate(){
returndate;
}
publicvoidsetDate(Datedate){
this.date=date;
}
publicMap
returnmaps;
}
publicvoidsetMaps(Map
this.maps=maps;
}
publicList
returnlists;
}
publicvoidsetLists(List
this.lists=lists;
}
publicDoggetDog(){
returndog;
}
publicvoidsetDog(Dogdog){
this.dog=dog;
}
}
Dog.java
packagecom.example.demo.bean;
publicclassDog{
privateStringname;
privateIntegerage;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
@Override
publicStringtoString(){
return"Dog{"+
"name='"+name+'\''+
",age="+age+
'}';
}
}
在Person.java里会有如图提示:
导入下面的maven依赖
在测试类中编写如下代码:
packagecom.example.demo;
importcom.example.demo.bean.Person;
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.test.context.junit4.SpringRunner;
importjavax.annotation.security.RunAs;
/**
*SpringBoot的单元测试
*可以在测试期间很方便的类似编码一样进行自动注入等
*/
@SpringBootTest
classDemoApplicationTests{
@Autowired
Personperson;
@Test
voidcontextLoads(){
System.out.println(person);
}
}
运行结果:
Person{lastName='zhangsan', age=18, boss=false, date=Fri Dec 01 00:00:00 GMT+08:00 2017, maps={k1=v1, k2=v2}, lists=[lisi, zhaoliu, wangwu], dog=null}
2020-02-12 20:50:56.194 INFO 9088 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
在application.properties文件里设置值
从结果中可以看到中文出现了乱码
从IDEA的settings里如图设置:
再次运行,结果如图:
可以看到乱码已解决。
@ConfigurationProperties与@Value区别
@Value("${person.lastName}")
@ConfigurationPropertie @Value
功能 批量注入配置文件中的属性 一个个的
松散绑定 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持
配置文件yml还是properties他们都能获取值
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,就使用@Value
@PropertySources和@ImportResource
@PropertySources:加载指定的配置文件
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件也不能识别;
想让Spring的配置文件生效,加载进来,@ImportResource标注在配置类上。
@ImportResource(value={"classpath:beans.xml"})
导入spring的配置文件:
不来编写Spring的配置文件:
SpringBoot推荐给容器中添加组件的方式,推荐使用全注解的方式
1.配置类====Spring配置文件
2.使用@Bean给容器添加组件
新建配置类:ConfigApp.java
packagecom.example2.demo.config;
importcom.example2.demo.service.HelloService;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
/**
*@Configuration;指明当前类是一个配置类,就是来替代之前的spring配置文件
*在配置文件中使用<bean>标签添加组件
*/
@Configuration
publicclassConfigApp{
//将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
@Bean
publicHelloServicehelloService(){
System.out.println("ConfigApp.helloService:"+"配置类@Bean给容器中添加组件了。。。");
returnnewHelloService();
}
}
测试运行结果:
配置文件占位符
RandomValuePropertySource:配置文件中可以使用随机数
${random.value},${random.int},${random.long},${random.int(10)},${random.int[1024,65536]}
属性配置占位符:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
占位符获取之前配置的值,如果没有,可以用:指定默认值:
Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境。
1.多profile文件形式:
--格式:application-{profile}.properties:
application-dev.properties、application-prod.properties
我们在主配置文件编写的时候,文件名可以是:
application-{profile}.properties/yml
默认使用application.properties的配置
2.多profile文档快模式:
server:
port:8081
spring:
profiles:
active:prod
---
server:
port:8082
spring:
profiles:dev
---
server:
port:8083
spring:
profiles:prod
3.激活方式:
--命令行--spring.profile.active=dev
配置文件 spring.profiles.active=dev
jvm参数-Dspring.profile.active=dev
在配置文件中指定spring.profiles.active=dev
配置文件加载位置:
Spring Boot启动会自动扫描以下位置的application.properties/yml文件作为springboot的默认配置文件
-file:./config
-file:/
-classpath:/config/
-classpath:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。
在application.properties配置项目的访问路径:
server.context-path=/boot02
而在SpringBoot2.0.2中其配置方式变成了
server.servlet.context-path=/demo
我们也可以通过配置spring.config.location来改变默认配置
外部配置加载顺序
Spring Boot也可以从以下位置加载配置,优先级从高到低
1.命令行参数:
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找:
优先加载带profile
6.jar包外部的application-{profile}.properties或application.yml(带profile配置文件)
7..jar包内部的application-{profile}.properties或application.yml(带profile配置文件)
再来加载不带profile
8.jar包外部的application-{profile}.properties或application.yml(不带profile配置文件)
9.jar包内部的application-{profile}.properties或application.yml(不带profile配置文件)
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性
自动配置原理
1.SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration作用:
利用AutoConfigurationImportSelector给容器导入了一些组件
publicString[]selectImports(AnnotationMetadataannotationMetadata)
List
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下META-INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加到容器中。
将类路径下 META-INF/spring.factories 里面的配置的所有EnableAutoConfiguration的值加入到了容器中;
每一个这样的类都是容器中的一个组件,都加入到容器中;用他们来做自动配置
3.每一个自动配置类进行自动配置
4以HttpEncodingAutoConfiguration为例:
@Configuration( //表示这是一个配置类,以前编写的配置一样,也可以给容器添加组件
proxyBeanMethods=false
)
@EnableConfigurationProperties({HttpProperties.class})//启动指定类的ConfigurationProperties功能
ConfigurationProperties功能:将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到IOC容器中;
@ConditionalOnWebApplication(//Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;判断当前应用是否是web应用,如果是,当前配置类生效;
type=Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})//判断当前项目有没有这个类CharacterEncodingFilter(springMVC中进行乱码解决的过滤器)
@ConditionalOnProperty(//判断配置文件中是否存在某个配置
prefix="spring.http.encoding",
value={"enabled"},
matchIfMissing=true
)
public class HttpEncodingAutoConfiguration{
privatefinalEncodingproperties; //他已经和SpringBoot的配置文件映射了
//只有一个有参构造器的情况下,参数的值就会从容器中获取
publicHttpEncodingAutoConfiguration(HttpPropertiesproperties){
this.properties=properties.getEncoding();
}
@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取。
@ConditionalOnMissingBean //判断容器中没有这个组件
publicCharacterEncodingFiltercharacterEncodingFilter(){
CharacterEncodingFilterfilter=newOrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
returnfilter;
}
根据当前不同的条件判断,决定这个配置类是否生效;
一旦这个配置类生效,这个配置类就会给容器中添加各种组件,这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
5.所有在配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能对应的这个属性类
@ConfigurationProperties(//从配置文件中获取指定的值和bean的属性进行绑定
prefix="spring.http"
)
publicclassHttpProperties{
@Conditional派生注解
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置类里面的所有内容才生效
自动配置类必须在一定的条件下才能生效;
我们怎么知道哪些自动配置类生效?
我们可以通过在配置文件里配置 debug=true属性,来让控制台自动打印配置报告,这样我们就可以很方便的知道哪些自动配置类生效。
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches: 自动配置类启动的
-----------------
AopAutoConfiguration matched:
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
。。。
Negative matches: 没启动的
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)