目录
1、配置文件
- SpringBoot在底层都帮我们将Spring中需要的配置,自动配置好了,如果需要进行修改,我们可以通过配置文件进行。
- 配置文件一般有两种不同的格式,分别为application.properties和application.yml
- 在springboot 项目中一般默认的配置文件是application.properties,但是实际项目中我们一般会使用application.yml 文件
2、yml
2-1 yml简介
YAML 是专门用来写配置文件的语言,非常简洁和强大。以前的配置文件;大多都使用的是 xxxx.xml 文件,YAML以数据为中心,比json、xml等更适合做配置文件;
yml配置文件
server:
port: 8081
xml配置文件
<server>
<port>8081</port>
</server>
2-2 yml语法
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- #表示注释,从这个字符一直到行尾,都会被解析器忽略
- 可以使用 “-小写字母” 或 "_小写字母"来 代替 “大写字母”,如 userName 与 user-name ,user_name 含义是一样的
2-2-1 基本语法
Key:(空格)Value
name: zhangsan
以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的
server:
port: 8080
path: /hello
2-2-2 不同数据格式的表示方式
(1)普通数据值(数字,字符串,布尔)
直接就是Key: Value
dan: '第一行\n第二行'
shuang: "第一行\n第二行"
wu: 第一行\n第二行
分别对带单引号、双引号、不带引号的String类型值进行测试
@RestController
public class HelloController {
@Value("${dan}")
public String dan;
@Value("${shuang}")
public String shaung;
@Value("${wu}")
public String wu;
@RequestMapping("/hello")
public String test1(){
System.out.println("单引号:"+dan);
System.out.println("-----------------");
System.out.println("双引号:"+shaung);
System.out.println("-----------------");
System.out.println("无引号:"+wu);
System.out.println("-----------------");
return "hello Springboot:success";
}
}
控制台
单引号:第一行\n第二行
-----------------
双引号:第一行
第二行
-----------------
无引号:第一行\n第二行
-----------------
结论
- 字符串默认不用加上单双引号,效果等同于加上单引号
- 加上单引号 ’ ’ :不会对字符串内容进行转义,输出的还是你写的字符串
- 加上双引号 " " :会对字符串内容进行转义,输出转义后的效果
(2)对象、Map(属性:值、键:值)
对象的写法还是基本的K: V格式,在对象的一行开始写它的属性和值的关系,注意缩进还是用空格不能用Tab,如:
Man:
name: zhangsan
age: 18
long: 18
hight: 180
也可以写成一行:
Man: {name: zhangsan,age: 18,long: 18,hight: 180}
(3)数组、Set
用 - 值 (即:-空格 值)的形式来表示数组中的一个元素
pets:
- dog
- cat
- pig
也可以写成一行:
pets: [dog,cat,pig]
2-2-3 yml格式练习
要求:创建Person类和Dog类,完成通过yml配置文件对Person类的值注入
1、创建Person类和Dog类
@Data
public class Person {
private String name;
private int age;
private boolean gay;
private Map<String,Object> pets;
private List<Object> study;
private Date birth;
private Dog dog;
}
@Data
public class Dog {
private String name;
private int age;
}
2、在yml文件中配置person类
person:
name: 王五
age: 36
gay: true
pets:
No1: dog
No2: pig
No3: Dog
study: [语文,数学,音乐]
birth: 2020/5/20
dog:
name: 小黄
age: 3
3、将配置文件中配置的每一个属性的值,映射到这个组件中
- 通过@ConfigurationProperties注解,告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
- 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能,所以要通过@Component注解将该类加入到容器中
- 通过prefix = “person”:将配置文件中所有属性进行一一映射
对应的JavaBean组件
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
public String name;
public int age;
public boolean gay;
public Map<String,Object> pets;
public List<Object> study;
public Date birth;
public Dog dog;
}
测试文件
@SpringBootTest
class Springboot01HelloworldApplicationTests {
/*注入person值*/
@Autowired
public Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
控制台结果:
Person(name=王五, age=36, gay=true, pets={No1=dog, No2=pig, No3=Dog}, study=[语文, 数学, 音乐], birth=Wed May 20 00:00:00 CST 2020, dog=Dog(name=小黄, age=3))
Tips:此外,我们可以导入spring-boot-configuration-processor这个依赖,让我们在yml文件输入时获得提示
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
提示效果如下
Tips:下面是在properties文件中进行person类的配置
person.name=差评
person.age=88
person.birth=2020/01/01
person.gay=false
person.dog.name=wang
person.dog.age=4
person.pets.k1=dog
person.pets.k2=cat
person.study=语文,数学,化学
运行发现乱码,在File>Setting中勾选运行中转为ascii就可以了
3、两种获取配置文件信息的方式
3-1 @ConfigurationProperties注解
上面的例子已经说过,这边简单总结一下
-
写好配置文件后,在你要注入的类上,写上@ConfigurationProperties注解
-
因为@ConfigurationProperties注解是Spring的功能,所以需要@Component注解将类加入Spring容器中
-
通过@ConfigurationProperties(prefix = “person”)的prefix = "person"来标注你要注入的配置文件是哪个
-
你要调用该类的时候通过@Autowired这个注解注入。如下:
@SpringBootTest class Springboot01HelloworldApplicationTests { @Autowired public Person person; @Test void contextLoads() { System.out.println(person); } }
3-2 @Value注解
@Value方式注入值一般用于单个值的注入
在你要注入的属性上写@Value("${配置文件中的名字}")
如:
man: 雄霸
@SpringBootTest
class Springboot01HelloworldApplicationTests {
@Value("${man}")
public String man;
@Test
void contextLoads() {
System.out.println("男人是:"+man);
}
}
控制台结果:男人是:雄霸
3-3 两种注入方式对比
项目 | @ConfigurationProperties | @Value |
---|---|---|
功能 | 批量注入配置文件中的值 | 一个个指定注入 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEl | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
上表说明
-
无论是yml还是properties配置文件,二者都可以读取
-
所谓松散语法也就是属性命名规则(Relaxed binding)
- person.firstName:使用标准方式
- person.first-name:大写用-
- person.first_name:大写用_
- PERSON_FIRST_NAME: 系统属性推荐使用这种写法
- 支持松散语法就是以上的命名都可以相互混用,表达的意思都一样;不支持就是相互之间无法识别
-
SpEl表达式具体百度。在上表中的意思就是,@Value注解可以通过@Value(#{SpEL表达式})的方式对值进行注入
@Value("#{2*13}") public int age; 运行结果:age=26
-
JSR303数据校验。在你要校验的类上加@Validated注解,在你要校验的属性上加校验的注解,如@Email,表示校验该属性的值是否为邮箱。在用@ConfigurationProperties注解注入属性值时,如果不是邮箱就会进行校验,报以下错误
同样的情况下@Value注解则正常运行,不会进行校验 -
复杂类型封装主要是指,配置文件中的复杂数据,如Map、Set、数组等无法通过@Value直接进行注入,但可以通过特殊格式注入
-
【总结】
(1)如果只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value
(2)如果专门编写了一个javaBean来和配置文件进行映射 ,我们就直接使用@ConfigurationProperties
3-4 @Value注入复杂封装类型
注入Map
配置文件,以yml为例。配置文件的map外面需要扩上双引号,里面的值需要扩上单引号
maps: "{k1:'v1',k2:'v2',k3:'v3'}"
实体类,@Value("#{${map名字}}")
@Value("#{${maps}}")
public Map<String,String> maps;
注入数组
yml配置文件写成一行
list: 语文,数学,英语
实体类,@Value("#{’${list名字}’.split(’,’)}")
@Value("#{'${list}'.split(',')}")
public List list;
4、@PropertySource和@ImportResource
前面所说的application配置文件是全局的配置文件,而现在要讲的两个配置文件则有独立配置的作用
4-1 @PropertySource加载指定配置文件
首先,在resources文件夹下创建person.properties文件,将全局配置文件中的信息,转移到这个配置文件中
resources/person.properties文件
person.name=牛逼
person.age=666
person.birth=2020/01/01
person.gay=false
person.dog.name=wang
person.dog.age=4
person.pets.k1=dog
person.pets.k2=cat
person.study=语文,数学,地理,666
其次,在实体类上添加 @PropertySource注解
然后,按格式写上指定注入的配置文件路径
@PropertySource(value={“classpath:xxx.properties”})
@Data
@Component
@PropertySource(value={"classpath:person.properties"})
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private int age;
private boolean gay;
private Map<String,Object> pets;
private List<Object> study;
private Date birth;
private Dog dog;
}
4-2 @ImportResource
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上,如主配置类
resources下创建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.atguigu.springboot.service.HelloService"></bean>
</beans>
添加到主配置类上,将beans.xml注入到Spring容器中
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
4-3 SpringBoot推荐给容器中添加组件的方式
SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式
- 创建配置类,并添加@Configuration注解,使其成为Spring配置文件
- 使用@Bean注解的方法给容器中添加组件。方法名就是id,返回值就是要添加到容器中的东西
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
*
* 在配置文件中用<bean><bean/>标签添加组件
*
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
5、占位符
在properties和yml配置文件中都可以使用占位符
${random.value}:生成随机值
${random.int}:生成随机整数
${random.long}:生成随机long值
${random.int(10)}:生成随机[0,10)的整数
${random.int[1024,65536]}:生成[1024,65536)间的整数
${person.name}:可以获取前面使用过的配置值
${person.name1:hello}:可以获取前面使用过的配置值,如果值不存在,则默认使用冒号后的值
实例:配置文件
person:
name: 网六
age: ${random.int(15,30)}
gay: true
pets:
No1: ${person.hello:Hi}
No2: pig的ID:${random.value}
No3: Dog
study: [语文,数学,音乐]
birth: 2020/5/20
dog:
name: ${person.name}的Dog
age: ${random.int(-1,2)}
【Console】
Person(
name=网六,
age=24,
gay=true,
pets={No1=Hi,
No2=pig的ID:e7ba1755ecbcd205c8e13565a4f43c6b,
No3=Dog},
study=[语文, 数学, 音乐],
birth=Wed May 20 00:00:00 CST 2020,
dog=Dog(name=网六的Dog, age=0))
@Value配置
@Component //注册bean
public class Person {
/ /直接使用@value
@Value("${person. name}") / /从配置文件中取值
private String name;
@Value ("#{11*2}") //#{SPEL} Spring表达式
private Integer age;
@Value ("true") // 字面量
private Boolean happy;
}
6、Profile
Profile是Spring对不同环境提供不同配置支持的功能,可以通过激活、指定参数等方式进行配置切换。
三种开发过程中常用的环境
- 开发环境(dev):开发环境是程序猿们专门用于开发的服务器,配置可以比较随意,为了开发调试方便,一般打开全部错误报告。
- 测试环境(test):一般是克隆一份生产环境的配置,一个程序在测试环境工作不正常,那么肯定不能把它发布到生产机上。
- 生产环境(prod):是值正式提供对外服务的,一般会关掉错误报告,打开错误日志。
三个环境也可以说是系统开发的三个阶段:开发->测试->上线,其中生产环境也就是通常说的真实环境。
5-1 多种配置文件
properties和yml配置文件都可以通过以下方式切换配置
在编写application配置文件的时候,可以写成application-{profile}.properties文件。系统默认使用的是application.properties文件
如果我们想要使用别的配置文件,可以通过application.properties中激活配置文件进行选择
在application.properties文件中,添加:spring.profiles.active=xxx
spring.profiles.active=prod
选择使用application-prod.properties配置文件
5-2 多文档块方式
yml可以通过多文档块方式切换配置
在yml配置文件中,可以通过"- - -"三个短杠将配置文件分为不同的Document,不同的Document相当于是不同的配置文件,可以在不同的Document上标注profiles的名字用于区分。默认使用的是第一个Document的配置,可以通过以下代码进行切换
spring:
profiles:
active: dev
#Document1
#默认的配置文件
server:
port: 8081
spring:
profiles:
active: dev
---
#Document2
server:
port: 8082
spring:
profiles: dev
---
#Document3
server:
port: 8083
spring:
profiles: prod
5-3 命令行方式
打开SpringBoot配置文件
输入命令行:–spring.profiles.active=dev
5-4 cmd命令方式
将项目打包后,通过cmd窗口启动,启动时输入命令行java jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
5-4 通过虚拟机参数
在虚拟机输入参数:-Dspring.profiles.active=dev
7、SpringBoot配置文件加载
7-1 配置加载优先级
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
- –file:./config/
- –file:./
- –classpath:/config/
- –classpath:/
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
上述说明
-
–classpath:/ 优先级最低。指的是直接在resources文件夹下创建的application配置文件
-
–classpath:/config/ 优先级高于–classpath:/。指的是在resources文件夹下创建config文件夹,里面的application配置文件
-
–file:./ 优先级高于上述两项。指的是在根目录下创建的配置文件
-
–file:./config/ 最高优先级。指的是在根目录下创建config文件夹下的配置文件
配置加载规律
-
上述所有路径下的主配置文件都会被加载,对于配置文件中相同的内容,高优先级的配置文件会覆盖低优先级的配置文件
-
配置互补:各个配置文件中的内容相同的会覆盖不同的会互补
demo:在最低优先级配置文件中,配置:server: servlet: context-path: /spring
则会形成互补,直接用http://localhost:8084/hello无法访问,需要添加/spring才能访问http://localhost:8084/spring/hello
Tips:实际开发过程中,如果我们需要对配置的某些部分进行调整,则可以使用这种覆盖的方式,既不会影响原来的配置,又可以对配置进行修改
7-2 指定配置文件
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
7-3 外部配置文件加载优先级顺序
(1)命令行加载(最高优先级)
命令行执行jar包时,直接指定某些配置信息,如端口号:
java -jar springboot-01-helloworld-0.0.1-SNAPSHOT.jar --server.port=8088
需要修改多个配置文件,则用空格进行分隔,每个要修改的配置信息前加 - - 两个短杠
(2)来自java:comp/env的JNDI属性
(3)Java系统属性(System.getProperties())
(4)操作系统环境变量
(5)RandomValuePropertySource配置的random.*属性值
6-9的加载原则
由jar包外向jar包内进行寻找;
优先加载带profile
再来加载不带profile
(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)配置文件
(10)@Configuration注解类上的@PropertySource
(11)通过SpringApplication.setDefaultProperties指定的默认属性
所有支持的配置加载来源 参考官方文档
8、自动配置原理
博客
这就是自动装配的原理!
精髓:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3)、我们再来看这个自动配置类中到底配置了哪些组件; (只要我们要用的组件存在在其中,我们
就不需要再手动配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置
文件中指定这些属性的值即可;
xxxxAutoConfigurartion:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性;