08-SpringBoot(28)
1. 什么是SpringBoot
Spring Boot 是一个简化 Spring 应用程序开发的框架。它的主要目标是减少 Spring 应用程序的配置和开发复杂性,使得能够更快地构建、测试和部署 Spring 应用
- 它通过提供默认配置、自动化配置和嵌入式服务器等功能,简化了传统 Spring 应用的繁琐配置过程
- 将一些依赖关系、默认配置已经都梳理好了,直接一个引用就搞定了,这就是它的本质
2. 核心特性有哪些
- 自动配置。一些依赖、默认配置都预设了,极大减少了配置量
- 内嵌服务器。以前 web 开发需要下载 tomcat 或者 jetty,现在 springboot 内置了
- 丰富的 starter。一些特定功能需要依赖的库全部封装好,直接一个引用足以
- 还有一些监控、健康检查(Actuator)等
3. 如何创建一个SpringBoot
- 使用 Spring Initializr 网站生成项目:访问
start.spring.io
,选择项目依赖,生成并下载项目 - 使用 IDE 创建:在 IDE 中,选择创建新的 Spring Boot 项目,配置依赖项和项目信息
- (不常见)使用 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 {
}
@SpringBootConfiguration
- 是 @Configuration 注解的一个特殊形式,表明该类是一个 Spring 配置类,用于定义 Bean
@EnableAutoConfiguration
- 启用 Spring Boot 的自动配置机制。根据类路径中的依赖项、其他 Bean 以及各种属性配置,自动配置 Spring 应用上下文。这个注解极大地减少了需要手动配置的内容
@ComponentScan
- 启用组件扫描,让 Spring 自动发现并注册应用程序上下文中的组件(如
@Component
、@Service
、@Repository
、@Controller
等注解标记的类)。默认扫描@SpringBootApplication
所在类的包及其子包
- 启用组件扫描,让 Spring 自动发现并注册应用程序上下文中的组件(如
7. 支持哪些嵌入式服务器
Spring Boot 支持以下嵌入式服务器:
Tomcat
:默认 嵌入式服务器 。 广泛使用,稳定性高Jetty
: 轻量级,高度可定制。支持 WebSocketUndertow
: 非常轻量级,启动速度快,非阻塞式架构,支持 WebSocket
8. properties、application.yml区别
两者的区别就在于书写格式,对配置而言效果是一样的
application.properties
:使用键值对配置,格式简单application.yml
:使用 YAML 语法,拥有天然的树状结构,支持层次结构和更直观的配置
9. 定义、读取自定义配置
@Value
注解:
@Value("${my.custom.property}")
private String myProperty;
@ConfigurationProperties
注解:
@Component
@ConfigurationProperties(prefix = "my.custom")
public class MyCustomProperties {
private String property;
}
Environment
接口:
@Autowired
private Environment env;
public void someMethod() {
String value = env.getProperty("my.custom.property");
}
10. 配置优先级
Spring Boot 在启动时加载配置属性的顺序,可参考如下官方文档:
- 从上到下,优先级逐渐降低
- 在 SpringBoot 中,配置加载越靠前,优先级越低,因为同样的参数会被后面的文件覆盖,所以加载顺序越靠后,优先级越高
简单优先级:
- 命令行参数
- JAR包外面的
application-{profile}.properties
- JAR包内的
application-{profile}.properties
- JAR包外的
application.properties
- JAR包内的
application.properties
Bootstrap 和 properties 之间的优先级(与加载顺序相反):(properties
、yml
同时存在,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. 如何处理全局异常
捕获全局异常方式如下:
- 可以创建一个异常处理类,并使用
@ControllerAdvice
注解 - 在类中编写异常处理方法,并使用
@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
- 注意!8192 并不是 SpringBoot 默认同时可以处理的请求,因为 Tomcat 还有一个默认等待数,加上这个才是 SpringBoot 默认同时可以处理的请求数
- 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 处理跨域请求主要有以下几种方式:
- 最简单的注解方式,在控制器上使用
@CrossOrigin
注解。这种方式简单直接,适合对类进行跨域设置
- 对全局的请求跨域,可以通过实现 WebMvcConfigurer 接口并重写 addCorsMappings 方法,可以对整个应用程序进行统一的跨域配置
- 更加细分,添加一个
CorsFilter
来处理跨域请求
17. 怎么使用拦截器
在项目中,通常使用拦截器来进行权限校验、日志记录、处理异常等问题
- 实现 HandlerInterceptor 接口,并实现接口中的方法
- 通过实现 WebMvcConfigurer 的 addInterceptors 方法来添加自定义的拦截器
- 拦截器具体实现代码:
- 注册拦截器代码
18. 如何实现定时任务
- 通过使用 @Scheduled 注解的方式来实现(单机不太经常变动十分推荐)
- 分布式系统或想要时间可以灵活变化,选择一些定时任务框架 xxl-job、elastic-job、Quartz ...
@Scheduled 有几个属性需要注意:
fixedRate
:固定频率执行,单位毫秒fixedDelay
:完成上一次执行后,固定延迟执行,单位毫秒cron
:使用 Cron 表达式来定义执行计划
19. 实现国际化(i18n)
实现国际化(i18n)主要依赖于 Spring Framework 的 MessageSource
接口。简单步骤如下:
- 在
resources
中创建属性文件来存储各种语言的翻译。命名规则一般是messages_xx.properties
- Spring Boot 自动配置了
MessageSource
的 Bean,它会查找任何名称为messages
的属性文件。也可以自定义前缀
- 使用
LocaleResolver
:默认使用AcceptHeaderLocaleResolver
,根据 HTTP 头部的Accept-Language
来解析区域设置 - 在 Controller 或其他 Bean 中,可以使用
@Autowired
注入 MessageSource,然后调用getMessage()
来获取本地化的消息
20. Spring Actuator的优势
Spring Actuator 主要是来帮助监控、管理应用。通过 HTTP 端点或 JMX beans 来暴露应用的内部信息
- 实时监控:Actuator 提供了关于应用健康、指标、日志等的详细信息
- 应用管理:它允许你查看配置属性、环境变量、组件等,并支持动态调整日志级别
- 易于集成:可以很容易地与外部监控系统集成,eg:Prometheus
- 提高安全性:可以配置访问控制,以保护敏感端点不被外部访问
21. 自定义JSON序列、反序列化
通常涉及使用 Jackson
库,是 SpringBoot 默认的 JSON 处理库
- 创建继承自 JsonSerializer 或 JsonDeserializer 的类来实现自定义的序列化或反序列化逻辑
日期序列化代码:
日期反序列化代码:
- 使用
@JsonSerialize
和@JsonDeserialize
注解来应用这些自定义的序列化器和反序列化器- 可以直接应用于模型的字段或整个类
- 全局配置可以自定义配置 ObjectMapper
22. 2.x与1.x版本有哪些改进
Spring Boot 2.x 相比于 1.x 版本引入了许多重要的改进和新特性,主要包括以下几个方面:
- 从 Framework 4 升级到 Spring Framework 5
- Spring Boot 2.x 要求至少使用 Java8
- 2.x 版本强化了对响应式编程的支持,包括响应式数据库驱动的支持。eg:MongoDB Reactive, Redis Reactive 等
- Spring Boot 2.x 采用了 Spring Security 5,包含了更多现代化的安全特性。eg:更好的 OAuth2 支持和改进的 JSON Web Tokens (JWT) 集成
- 2.x 版本中,Actuator 端点的安全和可管理性得到加强, 一些端点不再展示详细信息
- 响应式编程支持。 引入了 Spring WebFlux 作为构建响应式 Web 应用的框架
23. @Conditional是什么
- 条件注解
@Conditional
是一种强大的机制, 可以应用于 bean 方法或配置类。这种机制一般用于创建基于不同环境的组件 - Condition 接口定义了一个方法 matches,该方法接受两个参数,通过这些参数,可以访问正在创建的 bean 的上下文以及注解的元数据
创建一个条件:
通过 @Conditional
将这个条件应用于配置类或 bean:
24. 如何发布事件
发布和处理事件是一种强大的方式来解耦应用组件。支持通过《事件发布-订阅模型》来进行应用内的通信
- 允许应用组件以松散耦合的方式交互,提高了代码的模块化和灵活性。可以轻松地添加或移除监听器,而不影响事件发布者的代码
- 定义一个事件类。继承
ApplicationEvent
- 设置监听器来进行事件监听。
@EventListener
标记监听特定事件的方法,通过 classes 属性来指定需要监听的事件
ApplicationEventPublisher
提供了发布事件的功能
25. 如何实现多数据源配置
- 首先要引入使用的数据源依赖
- 通过配置
application.yml
/application.properties
来配置数据源的地址、密码等信息
- 通过配置数据源 DataSource 进行 Bean 注入,指定每个数据源的配置信息
- 配置不同数据源的 SqlSessionFactory,后面即可根据不同包下面的 mapper来指定不同的数据源
- 只需要指定好 xml 文件的位置以及所在的包、DataSource 组件的名称即可
26. 如何实现异步处理
在全局启动上打上 @EnableAsync
,然后只需要在方法上 @Async
注解,这个方法就是异步的
27. 启动时执行特定代码方式
在 SpringBoot 启动时,往往需要启动一些特定代码,eg:记录日志、检查换件配置诸如此类的操作,可以通过以下几点方法来执行:
- 实现
CommandLineRunner
接口并覆盖其 run 方法,这是一个非常简单且常用的方法 - 实现
ApplicationRunner
它接收的是ApplicationArguments
,可以更方便地处理应用程序参数 - 使用
@PostConstruct
注解的方法会在依赖注入完成后立即调用 - 实现
ApplicationListener
接口,监听ApplicationReadyEvent
事件,确保所有 Spring 组件都已初始化完成后再执行代码 - 在 Spring Boot 应用的主类中,也可以直接编写启动时执行的代码
- 实现
SmartInitializingSingleton
接口, 所有单例 Bean 初始化完成后执行代码
28. 不推荐使用@Autowired
使用 @Autowired
会看见以下提示:
简单来说这个提示就是不建议直接通过字段依赖注入,推荐通过构造方法,那为什么要通过构造方法呢?
- 使用
@Autowired
IDEA 不会检查关系是否存在,而使用构造注入会检查依赖关系 - 构造函数注入的方法更能明确依赖关系,易于维护
@Autowired
如果注入不正确,编译过程不会报错,但是运行之后报NullPointerException
不利于及时发现