SpringBoot之配置
回顾
配置文件
① 两种全局配置文件(文件名是固定的)
配置文件放在src/main/resources目录或者类路径/config下
application.properties(优先级高)
application.yml / application.yaml
配置文件的作用: 修改SpringBoot自动配置的默认值
② YAML
yml / yaml是YAML(YAML Ain't Markup Language)语言的文件, YAML以数据为中心, 比json/xml等更适合做配置文件.
实例:
YAML的基本语法
- 使用缩进表示层级关系
- 缩进时不允许使用tab键, 只允许使用空格
- 缩进的空格数目不受限制, 只要相同层级的元素在左侧对齐即可
- 大小写敏感
YAML支持的三种数据结构
- 对象 / Map(属性和值): 键值对的集合
普通写法:
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 20}
- 数组: 一组按次序排列的值
用- 值表示数组中的一个元素
普通写法:
pets:
- cat
- pig
- dog
行内写法:
pets: [cat,pig,dog]
- 字面量(普通的值, 如: 数字 字符串 布尔): 单个的 / 不可再分的值
直接写: 字符串默认不用加单引号或双引号
"": 双引号不会转义字符串里面的特殊字符, 特殊字符会作为其本身的意义输出
如: name: 'zhangsan \n lisi' ==> 代表为 zhangsan 换行 lisi
'': 单引号会转义字符串里面的特殊字符, 特殊字符不会作为其本身的意义输出(特殊字符最终只是一个普通的字符串)
如: name: 'zhangsan \n lisi' ==> 代表为 zhangsan \n lisi
③ 实例测试
实体类:
Person:
private String name;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
Dog:
private String name;
private Integer age;
配置文件(application.yml):
将配置文件中的每个值映射到属性中:
在Person类上加入以下两个注解:
@Component //将该组件初始化到容器中, 才能使用@ConfigurationProperties注解的功能
@ConfigurationProperties(prefix = "person") //该注解指定配置文件(全局配置文件application.yml / application.properties)中具体哪个变量下的值进行一一映射
注: 可以先导入配置文件处理器, 这样在编写配置文件时会有相应的提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
测试:
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
测试结果:
配置文件(application.properties):
测试结果:
另一种获取配置文件的值的方式(@Value("字面量 / ${key} / #{SpEL表达式}")):
测试结果:
@ConfigurationProperties和@Value的区别:
@ConfigurationProperties | @Value | |
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持(如: first-name和firstName相同) | 不支持(只支持first-name) |
SpEL表达式 | 不支持 | 支持(如: #{2.3*10}) |
JSR303数据校验(在类上使用@Validated注解) |
支持(如: 在某个字段上使用@Email注解, 则该字段必须为邮箱格式才正确, 否则报错) |
不支持 |
复杂类型封装 | 支持(如: 取Map或List或对象中的值) | 不支持 |
数据校验格式:
小结:
如果只是在某个业务逻辑中需要获取一下配置文件中的某项或某几项值, 则使用@Value注解; 如果专门编写了一个javaBean来和配置文件进行映射, 此时则需要@ConfigurationProperties注解.
从非全局配置文件中获取值进行映射的注解:
1) @ PropertySource(value={"配置文件的路径",...})
将之前的属性值都移到person.properties文件中, 测试能否将值注入Person类下的属性内.
2) @ImportResource: 导入Spring的配置的文件, 让配置文件的内容生效
beans.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.idea.springbott.service.HelloService"></bean>
</beans>
HelloService:
@Autowired
ApplicationContext ac;
@Test
public void testHelloService(){
boolean b = ac.containsBean("helloService");
System.out.println(b);
}
SpringBoot推荐给容器中添加组件的方式: 全注解方式
① 配置类<====>配置文件
② @Bean注解: 类同于配置文件中的<bean></bean>标签, 意为将方法的返回值添加到容器中
MyConfig配置类:
@Configuration
public class MyAppConfig {
@Bean
public HelloService helloService(){
System.out.println("配置类给容器添加组件了...");
return new HelloService();
}
}
配置文件占位符:
① 随机数
${random.value} / ${random.int} / ${random.long} / ${random.int(10)} / ${random.int[1024, 65536]}
② 占位符获取之前的属性值, 如果没有则可以指定默认值
属性配置:
person.name=王五${random.uuid}
person.age=${random.int}
person.boss=true
person.birth=2018/12/07
person.maps.k1=v1
person.maps.k2=15
person.lists=a,b,c
person.dog.name=${person.name:此处填写默认值}的dog
person.dog.age=18
profile标识: 动态切换, 以便适应不同的环境(开发环境 / 测试环境 / 生产环境等)
激活方式
1) spring.profiles.active=[具体的profile的名称]
2) 命令行: 打包成jar, 利用控制台方式启动(java -jar [部署包的名称] --spring.profiles.active=[profile的名称])
或者在idea中的Edit Configurations中进行设置也是属于命令行的一种方式
3) 虚拟机参数(VM options): -Dspring.profiles.active=[profile的名称]
① .properties文件的切换方式
在主配置文件编写的时候, 文件名可以是 application-[profile标识].properties/yml
如: application-dev.properties(表示开发环境) / application-prod.properties(表示生产环境)
默认情况下使用application.properties / application.yml主配置文件, 如果需要切换环境配置文件, 需要在主配置文件里面激活该需要切换的配置文件, 如: spring.profiles.active=[profile标识]
spring.profiles.active=dev
② .yml文件的切换方式(文档块)
内部配置文件的加载顺序:
4个存放位置: 按照优先级从高到低排列, 高优先级的配置覆盖低优先级的配置
① file: /config/ ==> 当前项目下的config文件夹下 优先级最高
② file: / ==> 当前项目下 优先级第二
③ classpath: /config/ ==> classpath下的config文件夹下 优先级第三
④ classpath: / ==> classpath下 优先级第四
SpringBoot会从这四个位置全部加载主配置文件从而互补配置
通过spring.config.location来改变默认的配置文件的位置
① 打包项目
② 使用命令行参数的形式, 在启动项目的时候指定配置文件的新位置, 指定的配置文件会和默认加载的配置文件共同起作用形成互补配置
外部配置文件的加载顺序:
SpringBoot也可以从以下位置加载配置文件, 优先级由高到低, 高优先级的配置会覆盖低优先级的配置, 所有的配置会形成互补配置.
① 命令行参数
java -jar [jar包名] --server.port=8089 / 其他命令也行(多个参数用空格隔开).
优先加载带spring.profiles.active, 并且由外部向内部加载(外部的优先级比内部的高)
② jar包外部的application-[profile的名称].properties / .yml(带spring.profiles.active)配置文件
③ jar包内部的application-[profile的名称].properties / .yml(带spring.profiles.active)配置文件
再加载不带spring.profile, 并且由外部向内部加载(外部的优先级比内部的高)
④ jar包外部application-[profile的名称].properties / .yml(不带spring.profiles.active)配置文件
⑤ jar包内部application-[profile的名称].properties / .yml(不带spring.profiles.active)配置文件
⑥ @Configuration注解类上的@PropertySource指定配置文件
自动配置原理:
配置文件能配置的属性
1) SpringBoot启动的时候加载主配置类, 开启了自动配置功能(注解: @EnableAutoConfiguration)
2) @EnableAutoConfiguration的作用:
利用@Import({EnableAutoConfigurationImportSelector.class})给容器中导入一些组件
selectImports(AnnotationMetadata annotationMetadata) ==> List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); //获取候选项的配置
① SpringFactoriesLoader.loadFactoryNames()
② classLoader.getResources("META-INF/spring.factories") //扫描所有jar包类路径下的META-INF/spring.factories
把扫描到的内容封装成properties对象, 并从中取出EnableAutoConfiguration.class类对应的值, 最后把它们添加进容器中.
每一个xxxAutoConfiguration都是容器中的一个组件, 都加入到容器中, 用他们来做自动配置.
3) 每一个自动配置类进行自动配置功能
4) 举例: HttpEncodingAutoConfiguration(http编码的自动配置)
@Configuration //这是一个配置类
@EnableConfigurationProperties({HttpEncodingProperties.class}) //启动指定类的ConfigurationProperties的功能; 将配置文件中对应的值和HttpEncodingProperties绑定起来;
@ConditionalOnWebApplication //Spring底层有@Conditional注解, 根据不同的条件, 如果满足指定的条件, 整个配置类才会生效.(判断当前应用是否是web应用, 如果是: 当前配置类生效)
@ConditionalOnClass({CharacterEncodingFilter.class}) //判断当前项目是否有CharacterEncodingFilter类
CharacterEncodingFilter: 是SpringMVC中进行乱码解决的过滤器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true) //判断配置文件中是否存
在某个配置, 即: spring.http.encoding.enabled; matchIfMissing = true: 如果文件不存在, 判断也是成立的(也就是说, 即使不配
置spring.http.encoding.enabled=true, 也是默认生效的)
HttpEncodingAutoConfiguration类下:
所有在配置文件中能配置的属性都是在xxxProperties类中封装着
HttpEncodingProperties: 该类上标注了@ConfigurationProperties(prefix = "spring.http.encoding")注解
该注解从配置文件中获取指定的值和bean的属性进行绑定
所以, HttpEncodingAutoConfiguration这个类的意义就是根据当前不同的条件进行判断, 决定这个配置类是否生效.
一旦这个配置类生效, 这个配置类就会给容器中添加各种组件, 这些组件的属性是从对应的properties类中获取的, 而这些类里面每一个属性又是和配置文件绑定的.
总结:
① SpringBoot启动会加载大量的自动配置类
② 查看需要的功能有没有SpringBoot默认写好的自动配置类
③ 如果有, 这个配置类配置了哪些组件(需要则注入即可, 无需再配置), 如果没有, 则需要自己写配置类
④ 给容器中的自动配置类添加组件的时候, 会从properties类中获取某些属性, 就可以在配置文件中指定这些属性的值(跟配置文件绑定了)
附:
由于自动配置类必须在一定条件下才能生效, 所以可以通过在配置文件中启用debug=true属性, 让控制台打印自动配置报告, 即能很方便知道具体哪些配置类生效哪些配置类不生效.
SpringBoot之配置的更多相关文章
- SpringBoot常用配置简介
SpringBoot常用配置简介 1. SpringBoot中几个常用的配置的简单介绍 一个简单的Spring.factories # Bootstrap components org.springf ...
- 在SpringBoot中配置aop
前言 aop作为spring的一个强大的功能经常被使用,aop的应用场景有很多,但是实际的应用还是需要根据实际的业务来进行实现.这里就以打印日志作为例子,在SpringBoot中配置aop 已经加入我 ...
- SpringBoot cache-control 配置静态资源缓存 (以及其中的思考经历)
昨天在部署项目时遇到一个问题,因为服务要部署到外网使用,中间经过了较多的网络传输限制,而且要加载arcgis等较大的文件,所以在部署后,发现页面loading需要很长时间,而且刷新也要重新从服务器下载 ...
- 补习系列(10)-springboot 之配置读取
目录 简介 一.配置样例 二.如何注入配置 1. 缺省配置文件 2. 使用注解 3. 启动参数 还有.. 三.如何读取配置 @Value 注解 Environment 接口 @Configuratio ...
- springboot +redis配置
springboot +redis配置 pom依赖 <dependency> <groupId>org.springframework.boot</groupId> ...
- SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页
SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页 **SpringBoot+Mybatis使用Pagehelper分页插件自动分页,非常好用,不用在自己去计算和组装了. ...
- SpringBoot自动配置源码调试
之前对SpringBoot的自动配置原理进行了较为详细的介绍(https://www.cnblogs.com/stm32stm32/p/10560933.html),接下来就对自动配置进行源码调试,探 ...
- SpringBoot实战之SpringBoot自动配置原理
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...
- SpringBoot 国际化配置,SpringBoot Locale 国际化
SpringBoot 国际化配置,SpringBoot Locale 国际化 ================================ ©Copyright 蕃薯耀 2018年3月27日 ht ...
随机推荐
- js获取时间戳的三种方法
1.Date.Now() 2.new Date().getTime() 3.Date.parse(new Date()) 其中1和2是相同含义 chrome控制台键入:Date.now() ===ne ...
- install rust
Step 1. Trial 1 Download rustup-init.exe exec rustup-init.exe SW hangs 2. Trial 2 install rust-1.33. ...
- [IDEA]IDEA设置注释模板
IDEA的注释模板有类注释模板和方法注释模板两种,下面分别介绍: 一.类注释模板 菜单路径:File->Settings->Editor->File and Code Templat ...
- LOJ 2548 「JSOI2018」绝地反击 ——二分图匹配+网络流手动退流
题目:https://loj.ac/problem/2548 如果知道正多边形的顶点,就是二分答案.二分图匹配.于是写了个暴力枚举多边形顶点的,还很愚蠢地把第一个顶点枚举到 2*pi ,其实只要 \( ...
- PCI9054 总结(讲解非常清楚)
转载自:http://blog.csdn.net/lg2lh/article/details/8042008 PCI的基本协议这里就不介绍了,因为一般的芯片协议都是集成好的,我只需要大体了解就行,不需 ...
- 高度自适应的div
需求:有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度 1.用flex 来实现 思路:flex 垂直布局(column),第一个元素固定高度,第二个元素flex ...
- JS语法基础
js声明 <!--在head标签中使用script标签进行js代码域声明--> <script type="text/javascript" language=& ...
- Mysql-12条优化技巧
应用程序慢如牛,原因多多,可能是网络的原因.可能是系统架构的原因,还有可能是数据库的原因. 那么如何提高数据库SQL语句执行速度呢?有人会说性能调优是数据库管理员(DBA)的事,然而性能调优跟程序员们 ...
- LeetCode【101. 对称二叉树】
对称二叉树,就是左节点的左节点等于右节点的右节点,左节点的右节点等于右节点的左节点. 很自然就想到迭代与递归,可以创建一个新的函数,就是另一个函数不断的判断,返回在主函数. class Solutio ...
- Oracle问题处理
一,如果在Oracle中执行for update操作时,出现一致卡顿现象,此时可能是有其它的进程阻塞了. 处理的方法就是查找出阻塞的进程,然后强制杀死 先查询出阻塞进程: select object_ ...