SpringBoot简介
核心:约定大于配置
Spring是如何简化java开发的
为了降低java开发的复杂性,Spring采用了以下4种关键策略
- 基于pojo的轻量级和最小侵入性编程
- 通过IOC,依赖注入(DI)和面向接口实现松耦合
- 基于切面(AOP)和惯例进行声明式编程
- 通过切面和模板减少样式代码
SpringBootd的主要优点
- 为所有Spring开发者更快的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目
- 没有冗余代码生成和XML配置的要求
springboot原理(一丢丢)
自动配置
pom.xml
- spring-boot-denpendencies:核心依赖在父工程
- 我们在写入或者引入一些springboot依赖的时候,不需要指定版本,就是因为有版本仓库
启动器
1 | <dependency> |
启动器:就是springboot的启动场景
比如上面这个启动器,他就会帮我们自动导入web环境所有的依赖
springboot会将所有的功能场景都变成一个个的启动器
我们要使用什么功能,就只需要找到对应的启动器就可以了
starter
小结:springboot所有的配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器有了启动器,我们自动装配就会生效,然后就配置成功了。
- SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
- 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作
- 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;它会把所有需要导入的组件以类名的方式返回,这些组件就会被添加到容器
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件
- 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作
SpringApplication
这个类主要做了一下四个事情
- 推断这个应用是普通项目还是Web项目
- 查找并加载所有可用初始化器,设置带initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
run方法流程分析
SpringBoot中常用的注解
- @Controller: 控制器(注入服务)用于标注控制器
- @Service:用于标注服务层,主要来进行业务的逻辑处理
- @Repository实现dao访问用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件
- @Component:(把普通pojo实例化到spring容器中,相当于存在配置文件中)泛指各种组件,就是说我们的类不属于归类的时候(不属于@Controller、@Services等的时候),我们可以用@Component来标注这个类
- @Validated:开启数据校验,然后在属性上加@Email等注解(JSR303校验)
yaml语法
配置文件
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
- application.properties
- 语法结构:key=value
- application.yml
- 语法结构:key:空格 value
配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们配置好了。
yaml概述
YAML是 “YAML Ain’t a Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:”Yet Another Markup Language”(仍是一种标记语言)
这中语言以数据为中心,而不是以标记语言为重点!
以前的配置文件,大多数都是使用xml来配置,比如一个简单的端口配置,简单的对比一下xml和yaml;
传统的xml配置
1 | <server> |
yaml配置:
1 | server: |
yaml基础语法
说明:语法要求严格。
空格不能省略
以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。(类似于python)
属性和值的大小都是十分敏感的。
字面量: 普通的值[数字,布尔值,字符串]
字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;
1
key: value
注意:
- “” 双引号,不会转字符串里面的特殊字符,特殊字符会作为本身想表示的意思;比如 name: “bestrooki \n e” 输出 bestrooki 换行 e
- ‘’ 单引号,会转义特殊字符,特殊字符最终会变成和普通字符一样输出;比如 name: ‘bestrooki \n e’ 输出:bestrooki \n e
对象、map(键值对)
1 | #对象、Map格式 |
在下一行来写对象的属性和值的关系,注意缩进;
1 | student: |
行内写法
1 | student: {name: qinjiang,age: 3} |
数组(List、set)
用- 值表示数组中的一个元素,比如;
1 | pets: |
行内写法
1 | pets: [cat,dog,pig] |
修改SpringBoot的默认端口号
配置文件中添加,端口号的参数,就可以切换端口;
1 | server: |
yaml注入配置文件
在SpringBoot项目中的resource目录新建一个文件application.yml
编写一个实体类Dog;
1
2
3
4
5
6
7package com.bestrookie.springboot.pojo;
//注册bean到容器中
public class Dog {
private String name;
private Integer age;
//有参无参构造、get、set方法、toString()方法
}原来的方法是用过Value注解注入属性值
1
2
3
4
5
6
7//注册bean
public class Dog {
private String name;
private Integer age;
}在SpringBoot的测试类下测试
1
2
3
4
5
6
7
8
9
class DemoApplicationTests {
//将狗狗自动注入进来
Dog dog;
public void contextLoads() {
System.out.println(dog); //打印看下狗狗对象
}
}结果成功输出
我们再编写一个复杂一点的实体类:Person
1
2
3
4
5
6
7
8
9
10
11//注册bean到容器中
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//有参无参构造、get、set方法、toString()方法
}使用yaml的方式进行注入
1
2
3
4
5
6
7
8
9
10
11
12
13person:
name: bestrookie
age: 3
happy: false
birth: 2000/01/01
maps: {k1: v1,k2: v2}
lists:
- code
- girl
- music
dog:
name: 旺财
age: 1现在将person这个对象的值注入到这个类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
//注册bean
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}绑定完之后可能idea会提示爆红,可以点击查看文档找到一个依赖导入,但是如果不导入也没有问题不会影响程序的运行。
确认以上配置都完事之后,我们测试一下
1
2
3
4
5
6
7
8
9
class DemoApplicationTests {
Person person; //将person自动注入进来
public void contextLoads() {
System.out.println(person); //打印person信息
}
}
配置文件占位符
配置文件还可以编写占位符生成随机数
1 | person: |
对比小结
@Value这个使用起来并不友好,我们需要为每个属性单独注解赋值,比较下面功能对比图
@ConfigurationProperties | @value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定 | 支持 | 不支持 |
SpEl | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
- @ConfigurationProperties只需要写一次即可,@Value需要每个字段都添加
- 松散绑定:这个是什么意思呢?比如我的yaml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就松散绑定,
- JSR303数据校验:这个就是我们可以在字段中增加一层过滤器验证,可以保证数据的合法性
- 复杂类型封装,yaml中可以封装对象没使用value就不支持
结论:
配置yaml和配置properties都可以获取到值,强烈推荐yaml
如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用@value;
如果说,我们专门编写了一个javaBean来和配置文件一一映射,就直接使用@configurationProperties。
JSR303数据校验及多环境切换
如何使用
Springboot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。我们举例name只能支持Email格式。
1 | //注册bean |
运行结果:default message [不是一个合法的电子邮件地址];
使用数据校验,可以保证数据的正确性
常见参数
1 |
|
多环境切换
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境
例如:
application-test.properties 代表测试环境配置
application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件;
我们需要通过一个配置来选择需要激活的环境
1 | #比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试; |
yaml的多文档块
和properties配置文件中一样,但是使用yaml去实现不需要创建多个配置文件,更加方便了。
1 | server: |
注意:如果yaml和properties同时都配置了端口,并且没有激活其他的环境,默认properties文件的
配置文件加载位置
外部加载配置文件的方式十分多,我们选择最常用的即可,在开发的资源文件中进行配置
官方外部配置文件说明参考文档
springboot启动会扫描以下位置的application。properties或者application.yaml文件作为springboot的默认配置文件:
-
优先级1:项目路径下的config文件夹配置文件
- 优先级2:项目路径下配置文件
- 优先级3:资源路径下的config文件夹配置文件
- 优先级4:资源路径下配置文件
优先级由高到低,高优先级的配置会覆盖低优先级的配置
springboot会从这四个位置加载主配置文件。
自动配置原理
我们以8HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;
1 | //表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件; |
一句话总结:根据当前不同的条件判断,决定这个配置类是否生效
- 一旦这个配置类生效,这个配置类就会给容器添加各种组件
- 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的
- 所有在配置文件中能配置的属性都是在xxxproperties类中封装着
- 配置文件能配置什么就可以参照某个功能对应的这个属性类
1 | //从配置文件中获取指定的值和bean的属性进行绑定 |
总结
- Springboot启动会加载大量的自动配置类
- 我们看我们需要的功能在Springboot默认写好的自动配置类当中
- 我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件存在其中,我们就不需要再手动配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可
xxxxAutoConfigurartion:自动配置类给容器中添加组件
xxxxProperties:封装配置文件中相关属性