SpringBoot
什么是SpringBoot?
Spring Boot基于Spring,是一个非常好的微服务开发框架,你可以使用它快速的搭建起一个系统,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。spring大家都知道,boot是启动的意思。所以,spring boot其实就是一个启动spring项目的一个工具而已。
在任何的spring项目中,你都会找到Java配置或一大堆的XML配置文件,很多配置都是复杂并且模板化,降低了开发效率还提高了我们开发的成本。而在springboot中这些都自动为我们做好了,让开发人员更加专注于业务需求的开发。
优点:
- 使编码变得简单:spring boot采用java config的方式,对spring进行配置,并且提供了大量的注解,极大地提高了工作效率。
- 使配置变得简单:所有spring boot的项目都只有一个配置文件:application.properties/application.yml。用了spring boot,再也不用担心配置出错找不到问题所在了。
- 使部署变得简单:spring boot内置了三种servlet容器:tomcat,jetty,undertow。所以,你只需要一个java的运行环境就可以跑spring boot的项目了(spring boot项目的入口是一个main方法,运行该方法即可。 )
- 使监控变得简单:spring boot提供了actuator包,可以使用它来对你的应用进行监控。
- 使测试变的简单:内置了JUnit、Spring Boot Test等多种测试框架,方便测试;
什么是 Spring Boot Starters?
Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,而不需要到处找示例代码和依赖包。starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦。不同的starter是为了解决不同的依赖,starter其实就是帮助用户简化了配置的操作(如你想使用Spring JPA访问数据库,只要加入springboot-starter-data-jpa启动器依赖就能使用了。)
Spring Boot ⽀持哪些内嵌 Servlet 容器?
spring boot内置了三种servlet容器:tomcat,jetty,undertow。
为何在 Spring Boot 应⽤程序中使⽤ Jetty ⽽不是 Tomcat?
Tomcat和Jetty都是一种Servlet引擎,他们都支持标准的servlet规范和JavaEE的规范。
Jetty的架构比Tomcat的更为简单
- Jetty的架构是基于Handler来实现的,主要的扩展功能都可以用Handler来实现,扩展简单。
- Tomcat的架构是基于容器设计的,进行扩展是需要了解Tomcat的整体设计结构,不易扩展。
Jetty的性能比Tomcat性能高
Jetty可以同时处理大量连接而且可以长时间保持连接,适合于web聊天应用等等。
Jetty的架构简单,因此作为服务器,Jetty可以按需加载组件,减少不需要的组件,减少了服务器内存开销,从而提高服务器性能。
Jetty默认采用NIO(非阻塞IO)结束在处理I/O请求上更占优势,在处理静态资源时,性能较高。
Tomcat适合处理少数非常繁忙的链接,也就是说链接生命周期短的话,Tomcat的总体性能更高。 另外,Tomcat默认采用BIO(阻塞IO)处理I/O请求,在处理静态资源时,性能较差。
Servlet的规范支持较好
- Jetty的应用更加快速,修改简单,对新的Servlet规范的支持较好。 GAE(谷歌应用引擎已经全面切换为Jetty)
- Tomcat目前应用比较广泛,对JavaEE和Servlet的支持更加全面,很多特性会直接集成进来。(中小企业还再在用)
介绍⼀下@SpringBootApplication 注解
@SpringBootApplication放置在Springboot启动类上,表明该类是开启Springboot容器的入口,它是一个复合注解。里面包含了包扫描,自动注入,配置注入的功能,下面就给大家介绍@SpringBootApplication包含的三个注解及其含义
第一个:@SpringBootConfiguration
@SpringBootConfiguration这个注解的作用就是声明当前类是SpringBoot应用的配置类,项目中只能有一个。所以一般我们无需自己添加。
第二个:@EnableAutoConfiguration(开启自动装配)
开启自动配置,告诉SpringBoot基于所添加的依赖,去“猜测”你想要如何配置Spring。我们使用SpringBoot构建一个项目,只需要引入所需框架的依赖,配置就可以交给SpringBoot处理了。
第三个:@ComponentScan(包扫描)
配置组件扫描的指令,通过basePackageClasses或者basePackages属性来指定要扫描的包。扫描所标注的类所在包下的所有需要注入的组件,将其注入
Spring Boot 的⾃动配置是如何实现的?
Spring Boot 自动配置,顾名思义,是希望能够自动配置,将我们从配置的苦海中解脱出来。那么既然要自动配置,它需要解三个问题:
- 满足什么样的条件?通过条件注解,表示当前配置类需要在当前项目有指定类的条件下,才能生效。
- 创建哪些Bean?通过@Configuration 注解声明这是一个配置类,可以解决“创建哪些 Bean”的问题。
- 创建Bean 的属性?通过配置属性,在 Spring Boot 定义了
@ConfigurationProperties
注解,用于声明配置属性类(让配置属性类生效),将指定前缀的配置项批量注入到该类中。
Spirng Boot 常⽤的两种配置⽂件
常见的配置文件格式:xml,Properties,json,yaml
在Spring Boot中,配置文件有两种不同的格式,一个是properties,另一个是yaml。(配置文件的作用:修改SpringBoot自动配置的默认值;)
- properties文件比较常见,相对于properties而言,yaml更加简洁明了,而且使用的场景也更多,很多的开源项目都是使用yaml进行配置,虽然yml看上去简洁不少,但yml阅读不直观,复制黏贴麻烦。properties书写简单方便,一行一个配置,而yml树状需要找到对应属性节点,需要对齐,父节点对错了可能排查问题需要很久,虽然IDE有自动对齐功能,但是在生产环境用vim命令编辑的情况下,properties肯定比yml来得方便。
- yaml中的数据是有序的,properties中的数据是无序的。在一些需要路径匹配的的配置中,顺序就显得尤为重要,此时我们一般采用yaml。
properties:配置文件的默认位置,及执行优先级顺序
首先,当我们创建一个Spring Boot工程时,默认resources目录下就有一个appliction.properties文件,可以在appliction.properties文件中进行项目配置
但是这个文件并非唯一的文件,在Spring Boot中,一共有4个地方可以存放application.properties文件。
1.当前项目根目录下的config目录下
2.当前项目的根目录下
3.resources目录下的config目录下
4.resources目录下其优先级由高到底,高优先级的配置会覆盖低优先级的配置
指定加载文件类型
可以在不同类型的配置文件中配置 测试,线上 ,以及 开发的配置文件 ,不需要在同一个配置文件中频繁更改。
application-dev.properties 开发配置文件
application-online.properties 线上配置文件
application-test.properties 测试配置文件
Spring Boot 常⽤的读取配置⽂件的⽅法有哪些?
有2种常用的方法:
- 使用@Value注解:在属性名上添加该注解,读取properties配置文件时,默认读取的是application.properties。
- 使用@ConfigurationProperties注解标注在类或者方法上:在实际项目中,当项目需要注入的变量值很多时,上述所述的两种方法工作量会变得比较大,这时候我们通常使用基于类型安全的配置方式,将properties属性和一个Bean关联在一起,即使用注解@ConfigurationProperties读取配置文件数据。
- @ConfigurationProperties通常用于将配置全量注入某个类中;
- @Value通常用于注入某一些特定配置值中;
Spring Boot 加载配置⽂件的优先级了解么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haE6i392-1632496383303)(C:\Users\LENOVO-LX\AppData\Roaming\Typora\typora-user-images\image-20210906114000171.png)]
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在—互补配置。(优先级指的是,配置文件都会加载,相同属性根据优先级高低进行合并。)
如果Spring Boot的配置文件同时存在application.properties
和application.yaml
,优先级的顺序为 properties>yaml
常⽤的 Bean 映射⼯具有哪些?
Java开发项目中,我们经常需要将对象转换成其他形式的对象,因此我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型。
进行这种转换除了手动编写大量的get/set
代码,还可以使用一些方便的类库:
-
apache的
BeanUtils
-
spring的
BeanUtils
apache的
BeanUtils
和spring的BeanUtils
中拷贝方法的原理都是先用jdk中java.beans.Introspector
类的getBeanInfo()
方法获取对象的属性信息及属性get/set方法,接着使用反射进行赋值。 -
cglib的
BeanCopier
。cglib的
BeanCopier
采用了不同的方法:它不是利用反射对属性进行赋值,而是直接使用ASM的MethodVisitor
直接编写各属性的get/set
方法生成class文件,然后进行执行。由于是直接生成字节码执行,所以BeanCopier
的性能较采用反射的BeanUtils
有较大提高
Spring Boot 如何监控系统实际运⾏状况?
Spring Boot 如何做请求参数校验?
通常我们编写一个接口,参数校验这一步是必不可少的,如果传递的参数不符合规范,那么不应该进入到业务方法应该将不合法信息提示给前端。对于参数校验传统的做法是,每个接口在接收到参数后再手动判断是否合法,这样一来每个接口都要手动编写验证规则,很明显这部分工作可以独立出来做统一验证。
为解决上述问题,springboot本身提供了一个验证框架。
- 添加相应依赖,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
-
定义参数接受类并添加验证规则
@Data @ToString public class User { @NotEmpty(message = "姓名不能为空") private String username; @Min(value = 1 , message = "年龄不能小于1岁") @Max(value = 100 , message = "年龄不能大于100岁") private Integer age; @Email @NotEmpty(message = "邮箱不能为空") private String email;
-
参数校验(使用controller层校验直接加入以下注解)
在controller层的参数校验可以分为两种场景:
- 单个参数校验
- 实体类参数校验
单个参数校验:
@RestController
@Validated
public class PingController {
@GetMapping("/getUser")
public String getUserStr(@NotNull(message = "name 不能为空") String name,
@Max(value = 99, message = "不能大于99岁") Integer age) {
return "name: " + name + " ,age:" + age;
}
}
注意:这里一定要在方法所在的controller类上加入@Validated
注解,不然没有任何效果
实体类参数校验:
当处理post请求或者请求参数较多的时候我们一般会选择使用一个bean来接收参数,然后在每个需要校验的属性上使用参数校验注解:
@Data
public class UserInfo {
@NotNull(message = "username cannot be null")
private String name;
@NotNull(message = "sex cannot be null")
private String sex;
@Max(value = 99L)
private Integer age;
}
然后在controller方法中用@RequestBody
表示这个参数接收的类
如何使⽤ Spring Boot 实现全局异常处理?
SpringBoot的项目已经对有一定的异常处理了,但是对于我们开发者而言可能就不太合适了,因此我们需要对这些异常进行统一的捕获并处理。SpringBoot中有一个ControllerAdvice
的注解,使用该注解表示开启了全局异常的捕获,我们只需再自定义一个方法使用ExceptionHandler
注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(value =Exception.class)
public String exceptionHandler(Exception e){
System.out.println("未知异常!原因是:"+e);
return e.getMessage();
}
}
Spring Boot 中如何实现定时任务 ?
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具备这两个 Spring 中的定时任务实现策略,当然也支持 Quartz,本文我们就来看下 Spring Boot 中两种定时任务的实现方式。
使用 @Scheduled:直接创建一个 Spring Boot 项目,并且添加 web 依赖 spring-boot-starter-web
,项目创建成功后,到启动类添加 @EnableScheduling
注解,开启定时任务:
@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduledApplication.class, args);
}
}
一般在项目中,除非定时任务涉及到的业务实在是太简单,使用 @Scheduled 注解来解决定时任务,否则大部分情况可能都是使用 Quartz 来做定时任务。在 Spring Boot 中使用 Quartz ,只需要在创建项目时,添加 Quartz 依赖即可:
项目创建完成后,也需要添加开启定时任务的注解:
@SpringBootApplication
@EnableScheduling
public class QuartzApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzApplication.class, args);
}