SpringBoot学习笔记-SpringBoot配置
SpringBoot学习笔记-SpringBoot配置
Table of Contents
1 Spring Boot配置
1.1 配置文件
- SpringBoot使用一个全局的配置文件
application.propertiesapplication.yml: YAML(YAML Ain't Markup Language), 以数据为中心, 比json, xml更适合做配置文件.
server: port: 8081
- 配置文件的作用: 修改SpringBoot自动配置的默认值.
1.2 YAML语法
- 使用缩进表示层级关系.
- 缩进时不允许使用Tab键,只允许使用空格.
- 缩进空格数目不重要,只要相同层级的元素左侧对齐即可
- 大小写敏感
1.3 YAML的数据结构
- 对象: 键值对的集合.
- 数组: 一组按次序排列的值.
- 字面量: 单个的,不可再分的值.
1.3.1 字面量
- 字面量的字符串默认不用加上单引号或者双引号.
""双引号, 不会转移字符串里面的特殊字符.- "zhangsan\nlisi" -> zhangsan换行lisi
''单引号, 会转义特殊字符, 特殊字符最终只是一个普通的字符串数据.- "zhangsan\nlisi" -> zhangsan\nlisi
K: V: 字面量
1.3.2 对象
- 对象的语法是对象加属性的kv形式.
friends: lastName: zhangsan age: 20
- 行内写法
friends: {lastName: zhangsan, age: 18}
1.3.3 数组(List,Set)
- 用
-值来表示数组的一个元素.
pets:
- cat
- dog
- pig
- 行内写法
pets: [cat,dog,pig]
1.4 获取yaml配置文件值注入
- yaml配置文件
person: lastName: zhangsan age: 18 boss: false birth: 2017/12/12 maps: {k1: v1, k2: 12} lists: - lisi - zhaoliu dog: name: 小狗 age: 2
- 组件bean
package com.devinkin.springboot.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; /** * 将配置文件中的每一个属性的值,映射到这个组件中 * @ConfigurationProperties 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定 * prefix="person", 配置文件中哪个下面的所有属性进行一一映射 * * @Component 只有这个组件是容器中的组件,才能使用容器提供@ConfigurationProperties的功能. */ @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; public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Boolean getBoss() { 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; } @Override public String toString() { return "Person{" + "lastName='" + lastName + '\'' + ", age=" + age + ", boss=" + boss + ", birth=" + birth + ", maps=" + maps + ", lists=" + lists + '}'; } }
- 导入配置文件处理器,以后编写配置就有提示了
<!-- 导入配置文件处理器, 配置文件进行绑定就会有提示 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
- 如果从properties配置文件中获取值注入,idea需要注意一下设置.
- 因为properties默认编码是ascii,而idea默认编码是utf-8
1.5 @Value获取值和@ConfigurationProperties获取值的比较
- 配置文件无论是yaml还是properties都能获取到值.
- 如果说我们只是在某个业务逻辑中需要获取一项配置文件的某项值,我们就使用
@Value - 如果我们专门编写了一个javaBean来和配置文件进行校验,我们就直接使用
@ConfigurationProperties
| @ConfigurationProperties | @Value | |
| 功能 | 批量注入配置文件的属性 | 一个个指定 |
| 松散绑定(松散语法) | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303数据校验 | 支持 | 不支持 |
| 复杂类型封装 | 支持 | 不支持 |
1.6 配置文件注入值数据校验
- 使用
@Validated注解.
@Component @ConfigurationProperties(prefix = "person") @Validated public class Person { /** * <bean class="Person"> * <property name="lastName" value="字面量"/${key}从环境变量,配置文件中获取值/#{SpEL}></property> * </bean> */ // @Value("${person.last-name}") // LastName必须是有效的格式 @Email private String lastName; }
1.7 @PropertySource和@ImportResource
@PropertySource加载指定的配置文件- 例:
@PropertySource(value = {"classpath:person.properties"}) @ImportResource导入Spring的配置文件, 让配置文件里面的内容生效.- SpringBoot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别.
- 想让Spring的配置文件加载进来, 把
@ImportResource标注在主配置类上.
@ImportResource(locations = {"classpath:beans.xml"}) @SpringBootApplication public class SpringBoot02ConfigApplication { public static void main(String[] args) { SpringApplication.run(SpringBoot02ConfigApplication.class, args); } }
- SpringBoot推荐给容器中添加组件的方式: 使用全注解的方式.
- 使用
@Bean给容器中添加组件
- 使用
package com.devinkin.springboot.config; import com.devinkin.springboot.service.HelloService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Configuration 它指明当前类是一个配置类,就是来替代之前的Spring配置文件 */ @Configuration public class MyAppConfig { /** * 将方法的返回值添加到容器中: 容器中这个组件默认的id就是方法名 * @return */ @Bean public HelloService helloService() { System.out.println("配置类@Bean给容器中添加组件了..."); return new HelloService(); } }
1.8 配置文件的占位符
- RandomValuePropertySource: 配置文件中可以使用随机数
${random.value}${random.int}${random.long}${random.int(10)}${random.int(1024,65536)}
- 属性配置占位符
- 可以在配置文件中引入前面配置过的属性(优先级前面配置过的这里都能用).
$app.name:默认值$来指定找不到属性时的默认值.
# idea使用的是utf-8 # 配置person的值 person.last-name=张三${random.uuid} person.age=${random.int} person.birth=2019/02/01 person.boss=false person.maps.k1=v1 person.maps.k2=v2 person.lists=a,b,c person.dog.name=${person.last-name}_habi person.dog.age=15
1.9 Profile
- Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活,指定参数等方式快速切换环境.
- 多profile文件形式
- 格式:
application-{profile}.properties/yaml
- 格式:
- yaml多profile文档模式,
profiles用于区分不同的文档.- 使用
---分割多文档块.
- 使用
server: port: 8081 spring: profiles: active: dev --- server: port: 8082 spring: profiles: prod --- server: port: 8083 spring: profiles: dev ---
- 激活profile的方式
- 命令行:
--spring.profiles.active=dev - 配置文件:
spring.profiles.active=dev - jvm参数:
-Dspring.profiles.active=dev
- 命令行:
1.10 配置文件的加载位置
- SpringBoot启动会扫描一下位置下的
application.properties或者application.yml文件作为SpringBoot的默认配置文件.- 优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容.
./config/./classpath:/config/classpath:/- SpringBoot会从这四个位置加载主配置文件: 互补配置.
- SpringBoot2.x弃用了
server.context-path, 改用server.servlet.context-path
- SpringBoot2.x弃用了
- 可以配置
spring.config.location来改变默认配置. 不过在项目调试的时候不会使用该配置.- 项目打包以后,我们可以使用命令行参数的形式,在项目启动的时候来指定配置文件的新位置.
- 指定的配置文件和默认加载的这些配置文件共同起作用, 互补配置.
1.11 外部配置加载顺序
- SpringBoot也可以从以下位置加载配置,优先级从高到低,高优先级的配置覆盖低优先级的配置,所有的配置会形成互补的配置.
- 命令行参数.
- 来自
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-{profile}.properties或application.yml(不带spring.profile) 配置文件 - jar包内部的
application-{profile}.properties或application.yml(不带spring.profile) 配置文件 @Configuration注解类上的@PropertySource- 通过
SpringApplication.setDefaultProperties指定的默认属性.
1.12 自动配置原理
- SpringBoot启动的时候加载主配置类,开启了自动配置功能
@EnableAutoConfiguration @EnableAutoConfiguration作用: 将类路径下的META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加到了容器中.- 利用
EnableAutoConfigurationImportSelector给容器导入一些组件. - 查看
EnableAutoConfigurationImportSelector其父类的selectImports方法. List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);获取候选的配置.SpringFactoriesLoader.loadFactoryNames()扫描所有jar包类路径下的META-INF/spring.factories- 把扫描到的这些文件的内容包装成
Properties对象 - 从
Properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把它们添加到容器中.
- 利用
- 每一个自动配置类进行自动配置功能.
- 以
HttpEncodingAutoConfiguration为例解释自动配置原理.- 根据当前不同的条件判断,决定这个配置类是否生效.
@Configuration // 启动指定类的ConfigurationProperties功能 // 将配置文件中对应的值和HttpEncodingProperties绑定起来.并把 HttpEncodingProperties 加入到IOC容器中. @EnableConfigurationProperties(HttpEncodingProperties.class) // Spring底层@Conditional注解,根据不同得到条件,如果满足指定的条件,整个配置类里面的配置就会生效. // 判断当前应用是否为Web应用 @ConditionalOnWebApplication // 判断当前项目有没有CharacterFilter类(SpringMVC进行乱码解决的过滤器) @ConditionalOnClass(CharacterEncodingFilter.class) // 判断配置文件中是否存在某个配置 spring.http.encoding.enabled, 如果不存在, 判断也是成立的. // 即使配置文件中不配置 spring.http.encoding.enabled, 也是默认生效的. @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration {}
- 所有在配置文件中配置的属性都是在
xxxProperties类中封装着, 配置文件能配置什么就可以参照某个功能对应的这个属性类.
// 从配置文件中获取指定的值和bean的属性进行绑定. @ConfigurationProperties(prefix = "spring.http.encoding") public class HttpEncodingProperties {}
- 给容器中添加一个组件, 这个组件的某些值需要从properties中获取.
@Bean @ConditionalOnMissingBean(CharacterEncodingFilter.class) public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; }
1.13 SpringBoot精髓
- SpringBoot启动会加载大量的自动配置类
- 看SpringBoot默认写好的自动配置类有没有我们需要的功能.
- 我们再来看自动配置类中到底配置了哪些组件.(只要我们使用的组件有,我们就不需要再来配置).
- 给容器中自动配置类添加组件的时候,会从
Properties类中获取某些属性, 我们就可以在配置文件中指定这些属性的值.
1.14 @Condition派生注解
@Condition作用: 指定的条件成立, 才给容器中添加组件, 配置类里面的所有内容才生效.- Condition注解的扩展
| @Condition扩展注解 | 作用(判断是否满足当前指定条件) |
| @ConditionOnJava | 系统的Java版本是否符合要求 |
| @ConditionOnBean | 容器中存在指定Bean |
| @ConditionOnMissingBean | 容器中不存在指定Bean |
| @ConditionOnExpression | 满足SpEL表达式指定 |
| @ConditionOnClass | 系统中有指定的类 |
| @ConditionOnMissingClass | 系统中没有指定的类 |
| @ConditionOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
| @ConditionOnProperty | 系统中指定的属性是否有指定的值 |
| @ConditionOnResource | 类路径下是否存在指定资源文件 |
| @ConditionOnWebApplication | 类路径下是否存在指定资源文件 |
- 在配置文件中添加如下配置
debug=true启用debug模式, 可以查看加载了哪些自动配置类.

浙公网安备 33010602011771号