SpringBoot
Spring boot
问题
- 简单介绍一下 Spring?有啥缺点?
- 为什么要有 SpringBoot?
- 说出使用 Spring Boot 的主要优点
- 什么是 Spring Boot Starters?
- Spring Boot 支持哪些内嵌 Servlet 容器?
- 如何在 Spring Boot 应用程序中使用 Jetty 而不是 Tomcat?
- 介绍一下@SpringBootApplication 注解
- Spring Boot 的自动配置是如何实现的?
- 开发 RESTful Web 服务常用的注解有哪些?
- Spirng Boot 常用的两种配置文件
- 什么是 YAML?YAML 配置的优势在哪?
- Spring Boot 常用的读取配置文件的方法有哪些?
- Spring Boot 加载配置文件的优先级了解么?
- 常用的 Bean 映射工具有哪些?
- Spring Boot 如何监控系统实际运行状况?
- 1Spring Boot 如何做请求参数校验?
- 如何使用 Spring Boot 实现全局异常处理?
- Spring Boot 中如何实现定时任务 ?
介绍
Spring Boot简化Spring开发(减少配置文件,开箱即用)
优点
- 容易上手
- 开箱即用
- 提供了一系列大型项目通用的非业务性功能
- 配置简单
什么是Spring Boot starters
Spring Boot starters是一系列依赖关系的集合 在没有Spring Boot starters之前,我们开发REST服务或者Web应用程序,我们需要食用Tomcat或Jackson这样的库,依赖需要一个个手动添加,有了Spring Boot starters只需要添加这个一个依赖就可以,这个依赖中包含了我们开发REST服务所有的依赖。
如何在 Spring Boot 应用程序中使用 Jetty 而不是 Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加Jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
介绍一下@SpringBootApplication注解
@SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合
- @EnableAutoConfiguration:启用SprintBoot的自动配置机制
- @ComponentScan:扫描@Component(@Service,@Controller)注解的bean,注解默认会扫描该类所在的包下所有的类
- @ Configuration:允许在上下文中注册额外的bean或导入其他配置类
Spring Boot的自动配置如何实现
这个是因为@SpringBootApplication的原因,由于@SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合
1. ```@EnableAutoConfiguration```注解通过Spring提供的@Import注解导入```@ AutoConfigurationImportSelector ```,这个类中的getCandidateConfigurations方法会将所有自动配置类的信息以List形式返回。这些配置会被Spring容器作bean来管理。
2. ```@Conditional``` 注解。@ConditionalOnClass(指定的类必须存在于类路径下)制定了容器必须还有其实现类。
<figure
>
<picture>
<!-- Auto scaling with imagemagick -->
<!--
See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
-->
<source
class="responsive-img-srcset"
srcset="/assets/img/2021/09/image-2fdea424401047dc83a0da78eebfe41a-480.webp 480w,/assets/img/2021/09/image-2fdea424401047dc83a0da78eebfe41a-800.webp 800w,/assets/img/2021/09/image-2fdea424401047dc83a0da78eebfe41a-1400.webp 1400w,"
sizes="95vw"
type="image/webp"
>
<img
src="/assets/img/2021/09/image-2fdea424401047dc83a0da78eebfe41a.png"
class="img-fluid rounded z-depth-1"
width="70%"
height="auto"
data-zoomable
loading="eager"
onerror="this.onerror=null; $('.responsive-img-srcset').remove();"
>
</picture>
</figure>
### 结论
- SpringBoot 所有的自动配置都是在启动的时候扫描并加载的
- 自动配置真正实现
- 从classpath中搜寻所有的META-INF/spring.factories配置文件
- 并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类
- 然后将这些都汇总成为一个实例并加载到IOC容器中
- 不过有部分配置类不会一开始就自动加载,只有满足 @ConditionalOnXXX(xxxx) 中的条件才会生效 —— 导入对应的 start 启动器
## RESTful Web服务常用注解
### Spring Bean相关
- @Autowired:自动导入对象到类中,被注入进的类同样被Spring容器管理;
- @RestController : @RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器 bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。
- @Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
- @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
- @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
- @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。
### 常见HTTP请求类型
- @GetMapping : GET 请求、
- @PostMapping : POST 请求。
- @PutMapping : PUT 请求。
- @DeleteMapping : DELETE 请求。
### 前后端传值
- @RequestParam以及@Pathvairable :@PathVariable用于获取路径参数,@RequestParam用于获取查询参数。
- @RequestBody :用于读取 Request 请求(可能是 POST,PUT,DELETE,GET 请求)的 body 部分并且 Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用HttpMessageConverter或者自定义的HttpMessageConverter将请求的 body 中的 json 字符串转换为 java 对象。
## Spring的常用配置文件
application.properties或者 application.yml
## 读取配置文件
1. 通过@Value读取简单的配置文件信息(不推荐)
```java
@Value("${wuhan2020}")
String wuhan2020;
- 通过
@ConfigurationProperties
读取并与 bean 绑定LibraryProperties类上加了 @Component 注解,我们可以像使用普通 bean 一样将其注入到类中使用。
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "library")
@Setter
@Getter
@ToString
class LibraryProperties {
private String location;
private List<Book> books;
@Setter
@Getter
@ToString
static class Book {
String name;
String description;
}
}
使用
package cn.javaguide.readconfigproperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author shuang.kou
*/
@SpringBootApplication
public class ReadConfigPropertiesApplication implements InitializingBean {
private final LibraryProperties library;
public ReadConfigPropertiesApplication(LibraryProperties library) {
this.library = library;
}
public static void main(String[] args) {
SpringApplication.run(ReadConfigPropertiesApplication.class, args);
}
@Override
public void afterPropertiesSet() {
System.out.println(library.getLocation());//
System.out.println(library.getBooks()); //
}
}
- 通过@ConfigurationProperties读取并校验
ProfileProperties 类没有加 @Component 注解。我们在我们要使用ProfileProperties 的地方使用@EnableConfigurationProperties注册我们的配置 bean:
@PropertySource读取指定的 properties 文件
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:website.properties")
@Getter
@Setter
class WebSite {
@Value("${url}")
private String url;
}
使用
@Autowired
private WebSite webSite;
System.out.println(webSite.getUrl());//https://javaguide.cn/
Spring Boot加载配置文件的优先级
Spring Boot 如何监控系统实际运行状况
使用 Spring Boot Actuator 来对 Spring Boot 项目进行简单的监控。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Spring Boot请求参数校验
校验注解
JSR提供的注解校验
- @Null 被注释的元素必须为 null
- @NotNull 被注释的元素必须不为 null
- @AssertTrue 被注释的元素必须为 true
- @AssertFalse 被注释的元素必须为 false
- @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
- @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
- @Past 被注释的元素必须是一个过去的日期
- @Future 被注释的元素必须是一个将来的日期
- @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的注解校验
- @NotBlank(message =) 验证字符串非 null,且长度必须大于 0
- @Email 被注释的元素必须是电子邮箱地址
- @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
- @NotEmpty 被注释的字符串的必须非空
- @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
使用示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
@NotNull(message = "classId 不能为空")
private String classId;
@Size(max = 33)
@NotNull(message = "name 不能为空")
private String name;
@Pattern(regexp = "((^Man$|^Woman$|^UGM$))", message = "sex 值不在可选范围")
@NotNull(message = "sex 不能为空")
private String sex;
@Email(message = "email 格式不正确")
@NotNull(message = "email 不能为空")
private String email;
}
验证请求体(RequestBody)
我们在需要验证的参数上加上了@Valid 注解,如果验证失败,它将抛出MethodArgumentNotValidException。默认情况下,Spring 会将此异常转换为 HTTP Status 400(错误请求)。
@RestController
@RequestMapping("/api")
public class PersonController {
@PostMapping("/person")
public ResponseEntity<Person> getPerson(@RequestBody @Valid Person person) {
return ResponseEntity.ok().body(person);
}
}
验证请求参数(Path Variavles 和 Request Parameters)
一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数
@RestController
@RequestMapping("/api")
@Validated
public class PersonController {
@GetMapping("/person/{id}")
public ResponseEntity<Integer> getPersonByID(@Valid @PathVariable("id") @Max(value = 5,message = "超过 id 的范围了") Integer id) {
return ResponseEntity.ok().body(id);
}
@PutMapping("/person")
public ResponseEntity<String> getPersonByName(@Valid @RequestParam("name") @Size(max = 6,message = "超过 name 的范围了") String name) {
return ResponseEntity.ok().body(name);
}
}
Spring Boot实现全局异常处理?
使用@ControllerAdvice
和 @ExceptionHandler
处理全局异常。
Spring Boot实现定时任务
使用@Scheduled
注解就能很方便地创建一个定时任务。
@Component
public class ScheduledTasks {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
/**
* fixedRate:固定速率执行。每5秒执行一次。
*/
@Scheduled(fixedRate = 5000)
public void reportCurrentTimeWithFixedRate() {
log.info("Current Thread : {}", Thread.currentThread().getName());
log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date()));
}
}
单纯依靠 @Scheduled 注解 还不行,我们还需要在 SpringBoot 中我们只需要在启动类上加上@EnableScheduling 注解,这样才可以启动定时任务。@EnableScheduling 注解的作用是发现注解 @Scheduled 的任务并在后台执行该任务。
Enjoy Reading This Article?
Here are some more articles you might like to read next: