SpringBoot
1、Springboot的特点
1.1 依赖管理
<!-- 在pom中引入依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<!--跟进去-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
<!--跟到最底层发现基本上能用到的版本号Springboot都给添加好了-->
1.2自动版本仲裁机制
<!-- 去maven中找到对应的版本依赖
<properties>中添加版本,可以替换掉默认版本 -->
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
1.3场景启动器
<!--1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
1.4自动配置
<!-- 自动配置了tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- 自动配置好springmvc -->
<!-- 主程序同级目录下的包中的组件都会被Springboot默认扫描到 ,想要改变扫描路径,@ComponentScan("包路径")-->
1.5Springboot注解
@SpringbootApplication 由
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("") 这三个注解组成的
//对于@EnableAutoConfiguration来说,SpringFactoriesLoader的用途稍微不同一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration场景中,它更多提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfig.EnableAutoConfiguration作为查找的Key,获得对应的一组@Configuration类。
2、容器功能
2.1 @Configuration和@Bean() 组件添加
<!-- 以前用spring的xml配置方式实现组件添加 -->
<beans ...>
<bean id="user01" class="com.yhcen.User">
<property name="name" value="zs"></property>
<property name="age" value="13"></property>
</bean>
<bean id="cat" class="com.yhcen.Pet">
<property name="name" value="mimi"></property>
<property name="age" value="1"></property>
</bean>
</beans>
/***
现在Springboot方式添加组件,创建类,在类上添加@Configuration注解
当@Configuration(proxyBeanMethods=true) 代理对象调用方法,外部无论调用多少次,都是之前在容器中注册的单实例对象
当@Configuration(proxyBeanMethods=false) 不是由代理对象调用的,每一次调用都会产生新的对象
*
*/
@Configuration //告诉springboot这是个配置类
public class MyBean{
@Bean //给容器中添加组件,以方法名作为组件的id,返回类型就是组件类型。
public User user01(){
return new User("zs",12);
}
@Bean("tomcat01") //如果自己定义了,组件名就不是方法名而是括号中的名称
public Pet tomcat(){
return new Pet("tomcat",12);
}
}
@SpringBootApplication
public class MainApplication{
public static void run(String[] args){
//如何获取组件
ConfigurableApplicationContext run =SpringBootApplication.run(MainApplication.class,args);
String[] name = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
//从容器中获取组件
//组件类 组件 = run.getBean("组件名","组件类.class");
Pet p1 = run.getBean("tomcat1",Pet.class);
}
}
2.2 @Import() 组件导入
/***
@Import() : 给容器中导入组件,跟进去发现是一个数组,默认组件的名字就是全类名
*/
@Import({User.class,DBHelper.class})
2.3@Conditional 指定条件注入
ConfigurableApplicationContext run =SpringBootApplication.run(MainApplication.class,args);
//判断容器中是否有此组件
boolean tom = run.containsBean("tom");
@Configuration //告诉springboot这是个配置类
public class MyBean{
@Bean
@ConditionalOnBean(name="tomcat01") //当容器中有tomcat01组件的时候下面的组件才会注入
public User user01(){
return new User("zs",12);
}
//@Bean("tomcat01") 当tomcat01这个组件被注掉的时候,在容器中获取tomcat01是获取不到的
public Pet tomcat(){
return new Pet("tomcat",12);
}
}
//当我们@Conditional这个注解放在方法上代表此方法成立的情况下才会成立,如果此注解放在类上,类上的条件成立,类里的方法才会成立
2.4@ImportResource组件导入
//在类上添加注解,以xml引入的方式导入组件
@ImportResource("classpath:bean.xml")
2.5@ConfigurationProperties(prefix="") 和@EnableConfigurationProperties(Car.class) 配置绑定
Car.java
@Component //把组件放到 容器中,添加@Component
@ConfigurationProperties(prefix="myCar") //属性绑定,找到配置文件中前缀为myCar的
public class Car{
private String name;
private double price;
get...
set...
}
application.properties
myCar.name=BYD
myCar.price=100000
还有一种方式在配置文件类中添加@EnableConfigurationProperties注解(建议使用此方法)
@Configuration
@EnableConfigurationProperties(Car.class)
public class MyConfig{
}
@ConfigurationProperties(prefix="myCar") //属性绑定,找到配置文件中前缀为myCar的
public class Car{
private String name;
private double price;
get...
set...
}
3、Springboot自动装配原理
@SpringbootApplication
由
@SpringbootConfiguration //其实就是@Configuration 代表当前是个配置类
@EnableAutoConfiguration
@ComponentScan //指定扫描哪些包
@EnableAutoConfiguration
由
@AutoConfigurationPackage //自动配置包
//批量注册,用registry给容器中导入一系列组件,将一个包下的所有组件导入进来
@Import(AutoConfigurationImportSelector.class)
3.1开启自动配置项
//虽然我们127个场景所有的自动配置启动的时候全部加载,按条件专配原则最终会按需配置
//按照条件装配规则(@Conditional),最终会按需配置
3.2修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
//给容器中加入了文件上传解析器;
总结:
-
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
-
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
-
生效的配置类就会给容器中装配很多组件
-
只要容器中有这些组件,相当于这些功能就有了
-
定制化配置
-
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
4、最佳实践
-
引入场景依赖
-
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
-
查看自动配置了哪些(选做)
-
自己分析,引入场景对应的自动配置一般都生效了
-
配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
-
是否需要修改
-
参照文档修改配置项
-
-https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
- 自己分析。xxxxProperties绑定了配置文件的哪些。
-
自定义加入或者替换组件
-
@Bean、@Component。。。
-
自定义器 XXXXXCustomizer;
- …
4.1Lombok
简化JavaBean开发
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
idea中搜索lombok
@Data //get/set方法
@AllArgsConstructor //有参构造方法
@NoArgsConstructor //无参构造方法
@ToString //toString
public class Pet{
private String name;
private String age;
}
4.2日志Logger
@slf4j
@RestController
public class UserController{
@RequestMapping(value="hello",method = RequestMethod.GET)
public String hello(){
log.info("日志打印"); //slf默认的属性可以打印日志
return "good";
}
}
4.3dev-tools 自动重启
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
需改完后按Ctrl+f9 ,自动部署
5、配置文件
两种配置文件.properties 和.yaml
5.1基本语法
-
key: value;kv之间有空格
-
大小写敏感
-
使用缩进表示层级关系
-
缩进不允许使用tab,只允许空格
-
缩进的空格数不重要,只要相同层级的元素左对齐即可
-
'#'表示注释
-
字符串无需加引号,如果要加,’'与""表示字符串内容 会被 转义/不转义
5.2数据类型
●字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
●对象:键值对的集合。map、hash、set、object
行内写法: k: {k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k2: v2
k3: v3
●数组:一组按次序排列的值。array、list、queue
行内写法: k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3
5.3示例
@Data
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
@Data
public class Pet {
private String name;
private Double weight;
}
# yaml表示以上对象 ,特殊字符 用双引号不会转义(特殊字符不会转义,直接表达特殊字符),单引号会转义(特殊字符作为字符串)
person:
userName: zhangsan
boss: false
birth: 2019/12/12 20:12:33
age: 18
pet:
name: tomcat
weight: 23.4
interests: [篮球,游泳]
animal:
- jerry
- mario
score:
english:
first: 30
second: 40
third: 50
math: [131,140,148]
chinese: {first: 128,second: 136}
salarys: [3999,4999.98,5999.99]
allPets:
sick:
- {name: tom}
- {name: jerry,weight: 47}
health: [{name: mario,weight: 47}]
5.4配置提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>