08-SpringBoot(28)

1. 什么是SpringBoot

Spring Boot 是一个简化 Spring 应用程序开发的框架。它的主要目标是减少 Spring 应用程序的配置和开发复杂性,使得能够更快地构建、测试和部署 Spring 应用

  • 它通过提供默认配置、自动化配置和嵌入式服务器等功能,简化了传统 Spring 应用的繁琐配置过程
  • 将一些依赖关系、默认配置已经都梳理好了,直接一个引用就搞定了,这就是它的本质

2. 核心特性有哪些

  1. 自动配置。一些依赖、默认配置都预设了,极大减少了配置量
  2. 内嵌服务器。以前 web 开发需要下载 tomcat 或者 jetty,现在 springboot 内置了
  3. 丰富的 starter。一些特定功能需要依赖的库全部封装好,直接一个引用足以
  4. 还有一些监控、健康检查(Actuator)等

3. 如何创建一个SpringBoot

  1. 使用 Spring Initializr 网站生成项目:访问 start.spring.io,选择项目依赖,生成并下载项目
  2. 使用 IDE 创建:在 IDE 中,选择创建新的 Spring Boot 项目,配置依赖项和项目信息
  3. (不常见)使用 Spring Boot CLI:安装 Spring Boot CLI 后,运行命令 spring init 创建项目

4. 什么是SpringInitializr

Spring Initializr 是一个在线服务网站,用于快速生成基于 Spring Boot 的项目模板

  • 用户可以通过 Spring Initializr 网站(start.spring.io
  • 选择项目的基本设置,包括项目依赖、构建工具、编程语言版本等,然后生成并下载一个预配置好的 Spring Boot 项目压缩包
  • 快速创建 SpringBoot 项目

5. Boot应用程序入口是什么

Spring Boot 应用程序的主要入口是一个包含 main() 的 Java 类,在类中标上 @SpringBootApplication ,通过调用 SpringApplication.run() 方法启动 Spring Boot 应用程序

6. @SpringBootApplication注解

@SpringBootApplication 其实是一个复合注解,包含了很多其他注解,简化标识 Spring Boot 应用程序的主类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

}
  1. @SpringBootConfiguration
    • 是 @Configuration 注解的一个特殊形式,表明该类是一个 Spring 配置类,用于定义 Bean
  2. @EnableAutoConfiguration
    • 启用 Spring Boot 的自动配置机制。根据类路径中的依赖项、其他 Bean 以及各种属性配置,自动配置 Spring 应用上下文。这个注解极大地减少了需要手动配置的内容
  3. @ComponentScan
    • 启用组件扫描,让 Spring 自动发现并注册应用程序上下文中的组件(如 @Component@Service@Repository@Controller 等注解标记的类)。默认扫描 @SpringBootApplication 所在类的包及其子包

7. 支持哪些嵌入式服务器

Spring Boot 支持以下嵌入式服务器:

  1. Tomcat:默认 嵌入式服务器 。 广泛使用,稳定性高
  2. Jetty: 轻量级,高度可定制。支持 WebSocket
  3. Undertow: 非常轻量级,启动速度快,非阻塞式架构,支持 WebSocket

8. properties、application.yml区别

两者的区别就在于书写格式,对配置而言效果是一样的

  • application.properties:使用键值对配置,格式简单
  • application.yml:使用 YAML 语法,拥有天然的树状结构,支持层次结构和更直观的配置

9. 定义、读取自定义配置

  1. @Value 注解:
@Value("${my.custom.property}")
private String myProperty;
  1. @ConfigurationProperties 注解:
@Component
@ConfigurationProperties(prefix = "my.custom")
public class MyCustomProperties {
    private String property;
}
  1. Environment 接口:
@Autowired
private Environment env;

public void someMethod() {
    String value = env.getProperty("my.custom.property");
}

10. 配置优先级

Spring Boot 在启动时加载配置属性的顺序,可参考如下官方文档:

Snipaste_2024-06-03_09-00-58.png
  • 从上到下,优先级逐渐降低
  • 在 SpringBoot 中,配置加载越靠前,优先级越低,因为同样的参数会被后面的文件覆盖,所以加载顺序越靠后,优先级越高

简单优先级:

  • 命令行参数
  • JAR包外面的 application-{profile}.properties
  • JAR包内的 application-{profile}.properties
  • JAR包外的 application.properties
  • JAR包内的 application.properties

Bootstrap 和 properties 之间的优先级(与加载顺序相反):(propertiesyml 同时存在,yml加载顺序靠后,优先级更高)

  • application.yml
  • application.properties
  • bootstrap.yml
  • bootstrap.properties

11. Boot的jar和普通jar区别

  • Spring Boot 打成的 JAR 包不仅包含了应用程序的源代码和依赖库,还包含了程序运行需要的配置、脚本和服务依赖(内嵌服务器,eg: Tomcat、Jetty、Undertow),可以直接部署运行
  • 普通的 JAR 包只有源代码和一些依赖,通常需要外部服务器或容器来运行

12. 是否可以使用 XML 配置

  • SpringBoot 也是基于 Spring,所以可以使用 XML 配置,但它更适合使用基于注解的配置和自动配置来简化开发流程
  • 如果要使用 xml 可以通过 @ImportResource 注解导入 XML 配置文件,让 Spring Boot 应用程序能够识别和使用这些 Bean

13. 如何处理全局异常

捕获全局异常方式如下:

  1. 可以创建一个异常处理类,并使用 @ControllerAdvice 注解
  2. 在类中编写异常处理方法,并使用 @ExceptionHandler 注解指定要处理的异常类型
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
    }

    @ExceptionHandler(MyCustomException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<String> handleCustomException(MyCustomException ex) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
    }
}
 








 





14. 同时可以处理多少请求

Spring Boot 能够处理的并发请求数量并不在于 SpringBoot,而实在于它所使用的容器

  • 默认的容器 Tomcat 为例,从引入的 spring-boot-autoconfigure 依赖可以看出,Tomcat 默认的最大连接数是 8192
微信图片_20240604090901.png
  • 注意!8192 并不是 SpringBoot 默认同时可以处理的请求,因为 Tomcat 还有一个默认等待数,加上这个才是 SpringBoot 默认同时可以处理的请求数
微信图片_20240604090911.png
  • SpringBoot 默认同时可以处理的请求数 = Tomcat默认的最大连接数 + Tomcat默认等待数 = 8192 + 100 = 8292

Tomcat 配置可以用过配置文件修改

server:
  tomcat:
    max-connections: 6000 # 最大连接数
    accept-count: 100     # 最大等待数

15. 理解Boot中的starter

"starter" 是一个用于简化 Maven 依赖管理的概念,它把所有依赖关系都打包在一起,可以帮助开发者快速集成和配置 Spring 项目中常用的库

16. 如何处理跨域请求(CORS)

Spring Boot 处理跨域请求主要有以下几种方式:

  1. 最简单的注解方式,在控制器上使用 @CrossOrigin 注解。这种方式简单直接,适合对类进行跨域设置
Snipaste_2024-06-04_13-55-34.png
  1. 对全局的请求跨域,可以通过实现 WebMvcConfigurer 接口并重写 addCorsMappings 方法,可以对整个应用程序进行统一的跨域配置
Snipaste_2024-06-04_13-56-03.png
  1. 更加细分,添加一个 CorsFilter 来处理跨域请求
Snipaste_2024-06-04_13-56-27.png

17. 怎么使用拦截器

在项目中,通常使用拦截器来进行权限校验、日志记录、处理异常等问题

  1. 实现 HandlerInterceptor 接口,并实现接口中的方法
  2. 通过实现 WebMvcConfigurer 的 addInterceptors 方法来添加自定义的拦截器

  1. 拦截器具体实现代码:
Snipaste_2024-06-04_14-10-31.png
  1. 注册拦截器代码
Snipaste_2024-06-04_14-10-40.png

18. 如何实现定时任务

  • 通过使用 @Scheduled 注解的方式来实现(单机不太经常变动十分推荐)
  • 分布式系统或想要时间可以灵活变化,选择一些定时任务框架 xxl-job、elastic-job、Quartz ...

@Scheduled 有几个属性需要注意:

  1. fixedRate:固定频率执行,单位毫秒
  2. fixedDelay:完成上一次执行后,固定延迟执行,单位毫秒
  3. cron:使用 Cron 表达式来定义执行计划

19. 实现国际化(i18n)

实现国际化(i18n)主要依赖于 Spring Framework 的 MessageSource 接口。简单步骤如下:

  1. resources 中创建属性文件来存储各种语言的翻译。命名规则一般是 messages_xx.properties
  2. Spring Boot 自动配置了 MessageSource 的 Bean,它会查找任何名称为 messages 的属性文件。也可以自定义前缀
Snipaste_2024-06-05_09-45-32.png
  1. 使用 LocaleResolver:默认使用 AcceptHeaderLocaleResolver,根据 HTTP 头部的 Accept-Language 来解析区域设置
  2. 在 Controller 或其他 Bean 中,可以使用 @Autowired 注入 MessageSource,然后调用 getMessage() 来获取本地化的消息
Snipaste_2024-06-05_09-49-23.png

20. Spring Actuator的优势

Spring Actuator 主要是来帮助监控、管理应用。通过 HTTP 端点或 JMX beans 来暴露应用的内部信息

  1. 实时监控:Actuator 提供了关于应用健康、指标、日志等的详细信息
  2. 应用管理:它允许你查看配置属性、环境变量、组件等,并支持动态调整日志级别
  3. 易于集成:可以很容易地与外部监控系统集成,eg:Prometheus
  4. 提高安全性:可以配置访问控制,以保护敏感端点不被外部访问

21. 自定义JSON序列、反序列化

通常涉及使用 Jackson 库,是 SpringBoot 默认的 JSON 处理库

  1. 创建继承自 JsonSerializer 或 JsonDeserializer 的类来实现自定义的序列化或反序列化逻辑

日期序列化代码:

Snipaste_2024-06-05_10-10-35.png

日期反序列化代码:

Snipaste_2024-06-05_10-10-19.png
  1. 使用 @JsonSerialize@JsonDeserialize 注解来应用这些自定义的序列化器和反序列化器
    • 可以直接应用于模型的字段或整个类
Snipaste_2024-06-05_10-11-05.png
  1. 全局配置可以自定义配置 ObjectMapper
Snipaste_2024-06-05_10-11-44.png

22. 2.x与1.x版本有哪些改进

Spring Boot 2.x 相比于 1.x 版本引入了许多重要的改进和新特性,主要包括以下几个方面:

  1. 从 Framework 4 升级到 Spring Framework 5
  2. Spring Boot 2.x 要求至少使用 Java8
  3. 2.x 版本强化了对响应式编程的支持,包括响应式数据库驱动的支持。eg:MongoDB Reactive, Redis Reactive 等
  4. Spring Boot 2.x 采用了 Spring Security 5,包含了更多现代化的安全特性。eg:更好的 OAuth2 支持和改进的 JSON Web Tokens (JWT) 集成
  5. 2.x 版本中,Actuator 端点的安全和可管理性得到加强, 一些端点不再展示详细信息
  6. 响应式编程支持。 引入了 Spring WebFlux 作为构建响应式 Web 应用的框架

23. @Conditional是什么

  • 条件注解 @Conditional 是一种强大的机制, 可以应用于 bean 方法或配置类。这种机制一般用于创建基于不同环境的组件
  • Condition 接口定义了一个方法 matches,该方法接受两个参数,通过这些参数,可以访问正在创建的 bean 的上下文以及注解的元数据

创建一个条件:

Snipaste_2024-06-06_10-01-21.png

通过 @Conditional 将这个条件应用于配置类或 bean:

Snipaste_2024-06-06_10-02-44.png

24. 如何发布事件

发布和处理事件是一种强大的方式来解耦应用组件。支持通过《事件发布-订阅模型》来进行应用内的通信

  • 允许应用组件以松散耦合的方式交互,提高了代码的模块化和灵活性。可以轻松地添加或移除监听器,而不影响事件发布者的代码
  1. 定义一个事件类。继承 ApplicationEvent
wecom-temp-7936-5141797be1dc58167b8d4360ad742e9c.webp
  1. 设置监听器来进行事件监听。@EventListener 标记监听特定事件的方法,通过 classes 属性来指定需要监听的事件
img_1.png
  1. ApplicationEventPublisher 提供了发布事件的功能
img_2.png

25. 如何实现多数据源配置

  1. 首先要引入使用的数据源依赖
  2. 通过配置 application.yml / application.properties 来配置数据源的地址、密码等信息
img1.png
  1. 通过配置数据源 DataSource 进行 Bean 注入,指定每个数据源的配置信息
img11.png
  1. 配置不同数据源的 SqlSessionFactory,后面即可根据不同包下面的 mapper来指定不同的数据源
    • 只需要指定好 xml 文件的位置以及所在的包、DataSource 组件的名称即可
img22.png

26. 如何实现异步处理

在全局启动上打上 @EnableAsync ,然后只需要在方法上 @Async 注解,这个方法就是异步的

27. 启动时执行特定代码方式

在 SpringBoot 启动时,往往需要启动一些特定代码,eg:记录日志、检查换件配置诸如此类的操作,可以通过以下几点方法来执行:

  1. 实现 CommandLineRunner 接口并覆盖其 run 方法,这是一个非常简单且常用的方法
  2. 实现 ApplicationRunner 它接收的是 ApplicationArguments,可以更方便地处理应用程序参数
  3. 使用 @PostConstruct 注解的方法会在依赖注入完成后立即调用
  4. 实现 ApplicationListener 接口,监听 ApplicationReadyEvent 事件,确保所有 Spring 组件都已初始化完成后再执行代码
  5. 在 Spring Boot 应用的主类中,也可以直接编写启动时执行的代码
  6. 实现 SmartInitializingSingleton 接口, 所有单例 Bean 初始化完成后执行代码

28. 不推荐使用@Autowired

使用 @Autowired 会看见以下提示:

Snipaste_2024-06-11_09-17-36.png

简单来说这个提示就是不建议直接通过字段依赖注入,推荐通过构造方法,那为什么要通过构造方法呢?

  1. 使用 @Autowired IDEA 不会检查关系是否存在,而使用构造注入会检查依赖关系
  2. 构造函数注入的方法更能明确依赖关系,易于维护
  3. @Autowired 如果注入不正确,编译过程不会报错,但是运行之后报 NullPointerException 不利于及时发现