源码地址
# 一、Spring与SpringBoot
Springboot+Spring Framework+Spring Data+Spring Cloud+Spring Security…
覆盖了:
Spring5重大升级:
适配器设计模式:A接口有(1,2,3,4,5方法),B适配器实现A。C类继承B(重写1,2,3方法),D类继承B重写(4,5方法)
基于Java8的一些新特性,如:提供了接口默认实现。Spring5重新设计源码架构。
特点:能快速创建出生产级别的Spring应用,整合Spring其他框架
创建独立Spring应用
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
Provide opinionated ‘starter’ dependencies to simplify your build configuration
Automatically configure Spring and 3rd party libraries whenever possible
提供生产级别的监控、健康检查及外部化配置
无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
分布式的困难:
分布式的解决:
即原生应用如何上云。 Cloud Native
上云的困难:
上云的解决:
Spring Boot官网
查看版本新特性
官方文档架构
新添内容:
<mirrors>
<mirror>
<id>nexus-aliyunid>
<mirrorOf>centralmirrorOf>
<name>Nexus aliyunname>
<url>http://maven.aliyun.com/nexus/content/groups/publicurl>
mirror>
mirrors>
<profiles>
<profile>
<id>jdk-1.8id>
<activation>
<activeByDefault>trueactiveByDefault>
<jdk>1.8jdk>
activation>
<properties>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<maven.compiler.compilerVersion>1.8maven.compiler.compilerVersion>
properties>
profile>
profiles>
需求:浏览发送/hello请求,响应 “Hello,Spring Boot 2”
1.创建maven工程
2.引入依赖
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.4.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
3.创建主程序
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
4.编写业务
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello, Spring Boot 2!";
}
}
5.运行&测试
MainApplication
类http://localhost:8080/hello
,将会输出Hello, Spring Boot 2!
设置配置:
maven工程的resource文件夹中创建application.properties文件。
# 设置端口号
server.port=8888
更多配置信息
6.打包部署
在pom.xml添加:
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
打包好的jar包被生成在helloworld工程项目的target文件夹内。
用cmd运行java -jar boot-01-helloworld-1.0-SNAPSHOT.jar
,既可以运行helloworld工程项目。
将jar包直接在目标服务器执行即可。
a> 父项目做依赖管理,后续引入依赖时不需要加版本号
依赖管理:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.4.RELEASEversion>
parent>
源码中父项目如下:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.3.4.RELEASEversion>
parent>
它几乎声明了所有开发中常用的依赖的默认版本号,自动版本仲裁机制
b> 开发导入 spring-boot-starter-场景启动器
spring-boot-starter-web
所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<version>2.3.4.RELEASEversion>
<scope>compilescope>
dependency>
c> 导入依赖时无需关注版本号,自动版本仲裁
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
d> 可以修改默认版本号
<properties>
<mysql.version>8.0.26mysql.version>
properties>
组件在容器中有,就会生效:
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<version>2.3.4.RELEASEversion>
<scope>compilescope>
dependency>
自动配好SpringMVC(由spring-boot-starter-web引入)
自动配好Web常见功能,如:字符编码问题
默认的包结构
@SpringBootApplication
==等同于==
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.zju.boot")
MultipartProperties
这个类会在容器中创建对象组件的循环依赖特性,必须是单实例
配置类本身也是组件
配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
Full模式(proxyBeanMethods = true):保证每个@Bean方法被调用多少次返回的组件都是单实例的
Lite模式(proxyBeanMethods = false):每个@Bean方法被调用多少次返回的组件都是新创建的
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
//Tomcat中组件为
它们是Spring的基本标签,在Spring Boot中并未改变它们原来的功能
@Bean:表示方法返回对象,然后对象交给IOC管理
@Component:普通的注解
@Controller:web层
@Service:业务逻辑层以及Service层
@Repository:dao层即持久层
@ComponentScan:扫描包
@Import({User.class, DBHelper.class,…})自动从类中的无参构造函数创建一个实例注册到IOC容器中
【注意】IOC容器中默认组件的名字id就是全类名,如 User 类就是:com.zju.boot.bean.User
@Import({User.class, DBHelper.class})
public class MyConfig {
}
条件装配:满足Conditional指定的条件,则进行组件注入
用@ConditionalOnMissingBean举例说明:
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = "tom")//没有tom名字的Bean时,MyConfig类的Bean才能生效。
public class MyConfig {
@Bean
public User user01(){
User zhangsan = new User("zhangsan", 18);
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom22")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
boolean tom = run.containsBean("tom");
System.out.println("容器中Tom组件:"+tom);//false
boolean user01 = run.containsBean("user01");
System.out.println("容器中user01组件:"+user01);//true
boolean tom22 = run.containsBean("tom22");
System.out.println("容器中tom22组件:"+tom22);//true
}
@ImportResource导入Spring配置文件
使用场景:比如,公司使用bean.xml文件生成配置bean,然而你为了省事,想继续复用bean.xml,@ImportResource粉墨登场。
beans.xml:
<beans ...">
<bean id="haha" class="com.lun.boot.bean.User">
<property name="name" value="zhangsan">property>
<property name="age" value="18">property>
bean>
<bean id="hehe" class="com.lun.boot.bean.Pet">
<property name="name" value="tomcat">property>
bean>
beans>
使用方法:将注解加到配置类中
@ImportResource("classpath:beans.xml")
public class MyConfig {
...
}
spring.banner.image.location=classpath:banner.jpg
classpath:只会到你的class路径中查找文件
读取properties文件中的内容,并且把它封装到JavaBean中,以供随时使用
方法一:
在实体类中配置@ConfigurationProperties
配置文件application.properties中
mycar.brand=BYD
mycar.price=100000
//只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
...
}
@RestController
public class HelloController {
@Autowired
Car car;//根据类型属性注入
@RequestMapping("/car")
public Car car(){
return car;
}
}
方法二:
应用场景,引用第三方包中类没有配置@Component注解
开启Car属性配置绑定功能
把这个Car这个组件自动注册到容器中
@EnableConfigurationProperties(Car.class)
public class MyConfig {
...
}
@ConfigurationProperties(prefix = "mycar")
public class Car {
...
}
Spring Boot应用启动类:
@SpringBootApplication
=@SpringBootConfiguration
+@EnableAutoConfiguration
+@ComponentScan
@Configuration
代表当前是一个配置类。
指定要扫描哪些包
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
自动配置包?指定了默认的包规则,即mainApplication所在包路径
@Import(AutoConfigurationPackages.Registrar.class)//给容器中导入一个组件
public @interface AutoConfigurationPackage {
...
}
getAutoConfigurationEntry(annotationMetadata);
给容器中批量导入一些组件List configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类Map> loadSpringFactories(@Nullable ClassLoader classLoader);
得到所有的组件META-INF/spring.factories
位置来加载一个文件。
META-INF/spring.factories
位置的文件spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
# 文件里面写死了spring-boot一启动就要给容器中加载的所有配置类127个
# spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
...
虽然我们127个场景的所有自动配置类启动的时候默认全部加载,
但是xxxxAutoConfiguration
按照条件装配规则(@Conditional
),最终会按需配置
如
AopAutoConfiguration
类:
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = "auto",
havingValue = "true",
matchIfMissing = true
)
public class AopAutoConfiguration {
public AopAutoConfiguration() {
}
...
}
以autoconfigure—web—servlet—DispatcherServletAutoConfiguration—multipartResolver为例
//文件上传解析器自动配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。此时容器中有MultipartResolver但命名不规范。
//SpringMVC中命名为multipartResolver。防止有些用户配置的文件上传解析器命名不符合规范。
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;//给容器中加入了文件上传解析器;
}
以ChracterEncoding为例
xxxAutoConfiguration加载自动配置类 —> 装配组件 —> xxxProperties里面拿值属性值 ----> application.properties自定义属性值
因此,修改配置文件即为修改整合场景的配置,配置文档或者查看底层源码
Lombok用标签方式代替构造器、getter/setter、toString()等鸡肋代码。
安装Lombok插件
spring boot已经管理Lombok,引入依赖:
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
@NoArgsConstructor
//@AllArgsConstructor
@Data
@ToString
@EqualsAndHashCode
public class User {
private String name;
private Integer age;
private Pet pet;
public User(String name,Integer age){
this.name = name;
this.age = age;
}
}
@Slf4j
@RestController
public class HelloController {
@RequestMapping("/Hello/{username}")
public String HelloMapping(@PathVariable("username") String username){
log.info("请求进来了");
return "Hello, wz "+username;
}
}
实现热部署,自动重启
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
dependencies>
在IDEA中,项目或者页面修改以后:Build project(Ctrl+F9)。
Spring Initailizr是创建Spring Boot工程向导,搭建好基础架构
在IDEA中,菜单栏New -> Project -> Spring Initailizr
application.properties中写配置文件
一种标记语言,非常适合用来做以数据为中心的配置文件,替代xml
k: v
#行内写法:类似于json
k: {k1: v1,k2: v2,k3: v3}
#或
k:
k1: v1
k2: v2
k3: v3
#行内写法:类似于json
k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3
@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;
}
person:
username: fkd
boss: true
birth: 2022/4/21 21:55:00
age: 23
pet: {name: wz,weight: 23}
interests: [篮球,足球]
animal: [猫,够,兔子]
score: {math: 80, English: 90}
salaries: [32000,43000,31000]
allPets: {sick: [{name: wz,weight: 20},{name: fkd,weight: 22}],healthy:[{name: sk,weight: 30}]}
自定义的类和配置文件绑定一般没有提示。若要提示,添加如下依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>