SpringBoot

#back-end/springBoot

Introducing Spring Boot

Spring Boot 可帮助创建可以运行的独立的、生产级的、基于 Spring 的应用程序,大多数 Spring Boot 应用程序只需要很少的 Spring 配置。

System Requirements

  • Spring Boot 3.1.3 需要 Java 17,并且兼容 Java 20(包括 Java 20)

  • Spring Framework 6.0.11 或更高版本

Setting up with Maven

配置pom文件

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

Controller层

HelloController 类上的第一个注释是 @RestController 。这称为构造型注释。它为阅读代码的人提供提示,并为 Spring 提供该类扮演特定角色的提示。

在本例中,我们的类是一个 Web @Controller ,因此 Spring 在处理传入的 Web 请求时会考虑它。

//@RestController 注释告诉 Spring 将结果字符串直接渲染回调用者。
@RestController
public class HelloController {

@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}

Main

第二个类级注释是 @SpringBootApplication 。此注释称为元注释,它结合了 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan

@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}

Condition Annotations

  • @ConditionalOnClass:如果类路径中存在这个类,则触发指定行为

  • @ConditionalOnMissingClass:如果类路径中不存在这个类,则触发指定行为

  • @ConditionalOnBean:如果容器中存在这个Bean(组件),则触发指定行为

  • @ConditionalOnMissingBean:如果容器中不存在这个Bean(组件),则触发指定行为

Class Conditions

@ConditionalOnClass@ConditionalOnMissingClass 注释允许根据特定类的存在或不存在来包含 @Configuration 类。由于注释元数据是使用 ASM 解析的,因此可以使用 value 属性来引用真实的类,即使该类实际上可能不会出现在正在运行的应用程序类路径中。如果希望使用 String 值指定类名,也可以使用 name 属性。

此机制不适用于 @Bean 方法,其中返回类型通常是条件的目标:在方法上的条件应用之前,JVM 将加载类和可能处理的方法引用,其中如果 class 不存在将会失败。

为了处理这种情况,可以使用单独的 @Configuration 类来隔离该情况,如以下示例所示:

@AutoConfiguration
// Some conditions ...
public class MyAutoConfiguration {

// Auto-configured beans ...

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService.class)
public static class SomeServiceConfiguration {

@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}

}

}

Bean Conditions

@ConditionalOnBean@ConditionalOnMissingBean 注释允许根据特定 bean 的存在或不存在来包含 bean。您可以使用 value 属性按类型指定 Bean,或使用 name 属性按名称指定 Bean。 search 属性允许您限制搜索 bean 时应考虑的 ApplicationContext 层次结构。

当放置在 @Bean 方法上时,目标类型默认为该方法的返回类型,如下例所示:

@AutoConfiguration
public class MyAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}

在前面的示例中,如果 ApplicationContext 中尚未包含 SomeService 类型的 bean,则将创建 someService bean。

Property Conditions

@ConditionalOnProperty 注释允许基于 Spring 环境属性包含配置。使用 prefixname 属性指定应检查的属性。默认情况下,匹配任何存在且不等于 false 的属性。您还可以使用 havingValuematchIfMissing 属性创建更高级的检查。

@ConfigurationProperties: 声明组件的属性和配置文件哪些前缀开始项进行绑定

@EnableConfigurationProperties:快速注册注解:

  • 场景:SpringBoot默认只扫描自己主程序所在的包。如果导入第三方包,即使组件上标注了 @Component@ConfigurationProperties 注解,也没用。因为组件都扫描不进来,此时使用这个注解就可以快速进行属性绑定并把组件注册进容器

将容器中任意组件(Bean)的属性值配置文件的配置项的值进行绑定

  • 给容器中注册组件(@Component、@Bean)
  • 使用@ConfigurationProperties 声明组件和配置文件的哪些配置项进行绑定

Auto Configuration

实现自动配置的类用 @AutoConfiguration 注释。此注释本身使用 @Configuration 进行元注释,使自动配置成为标准 @Configuration 类。附加 @Conditional 注释用于限制何时应用自动配置。通常,自动配置类使用 @ConditionalOnClass 和 @ConditionalOnMissingBean 注释。这确保仅当找到相关类并且您尚未声明自己的 @Configuration 时才应用自动配置。

auto configuration

@SpringBootApplication由三个注解组成

  • @SpringBootConfiguration : 标记该类可以用来作为 Spring Boot 启动类的配置类,内部是 @Configuration 注解
  • @EnableAutoConfiguration : 设置自动配置,会自动加载某些特定的配置类并进行初始化处理
  • @ComponentScan : 主要为配置组件扫描加载@Configuration类的包路径,默认为当前目录下的所有包

@EnableAutoConfiguration
开启自动配置的核心, 加载META-INF/spring.factories文件的信息, 筛选出以EnableAutoConfiguration为key的数据, 加载到IOC容器中, 实现自动配置功能

  • @Import(AutoConfigurationImportSelector.class)提供功能:批量给容器中导入组件
  • SpringBoot启动会默认加载 142个配置类
  • 这142个配置类来自于spring-boot-autoconfigureMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件指定的
  • 项目启动的时候利用 @Import 批量导入组件机制把 autoconfigure 包下的 xxxxAutoConfiguration类导入进来(自动配置类)
  • 每一个自动配置类,都有条件注解@ConditionalOnxxx,只有条件成立,才能生效

xxxxAutoConfiguration

  • 给容器中使用@Bean 放一堆组件
  • 每个自动配置类都可能有这个注解@EnableConfigurationProperties(ServerProperties.class), 用来把配置文件中配的指定前缀的属性值封装到 xxxProperties属性类
  • 以Tomcat为例:把服务器的所有配置都是以server开头的。配置都封装到了属性类中。
  • 只需要改配置文件的值,核心组件的底层参数都能修改

Logging

Spring Boot 使用 Commons Logging 进行所有内部日志记录,但使底层日志实现保持开放状态。为 Java Util Logging、Log4j2 和 Logback 提供了默认配置。在每种情况下,记录器都预先配置为使用控制台输出,还可以使用可选的文件输出。

默认情况下,如果您使用 Starters,则使用 Logback 进行日志记录。还包括适当的 Logback 路由,以确保使用 Java Util Logging、Commons Logging、Log4J 或 SLF4J 的依赖库都能正常工作。

一般来说,您不需要更改日志依赖项,Spring Boot 默认值就可以正常工作。

Log Format

Spring Boot 的默认日志输出类似于以下示例:

2023-09-21T10:34:07.743Z  INFO 34473 --- [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.8.1 with PID 34473 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2023-09-21T10:34:07.748Z INFO 34473 --- [ main] o.s.b.d.f.logexample.MyApplication : No active profile set, falling back to 1 default profile: "default"
2023-09-21T10:34:09.089Z INFO 34473 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-09-21T10:34:09.102Z INFO 34473 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-09-21T10:34:09.103Z INFO 34473 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.13]
2023-09-21T10:34:09.338Z INFO 34473 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-09-21T10:34:09.343Z INFO 34473 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1524 ms
2023-09-21T10:34:09.836Z INFO 34473 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-09-21T10:34:09.848Z INFO 34473 --- [ main] o.s.b.d.f.logexample.MyApplication : Started MyApplication in 2.7 seconds (process running for 3.114)

输出以下项目:

  • 日期和时间:毫秒精度且易于排序
  • 日志级别: ERRORWARNINFODEBUGTRACE
  • 进程 ID
  • 用于区分实际日志消息开始的 --- 分隔符
  • 线程名称:用方括号括起来(可能会被截断以用于控制台输出)
  • 记录器名称:这通常是源类名称(通常是缩写)
  • 日志消息

Console Output

默认日志配置会在写入消息时将消息回显到控制台。默认情况下,记录 ERROR 级别、 WARN 级别和 INFO 级别消息。您还可以通过使用 --debug 标志启动应用程序来启用“调试”模式。

启用调试模式后,将配置一系列核心记录器(嵌入式容器、Hibernate 和 Spring Boot)来输出更多信息。启用调试模式不会将您的应用程序配置为记录 DEBUG 级别的所有消息。

或者,您可以通过使用 --trace 标志(或 application.properties 中的 trace=true )启动应用程序来启用“跟踪”模式。这样做可以为选定的核心记录器(嵌入式容器、Hibernate 模式生成和整个 Spring 产品组合)启用跟踪日志记录。

Log Levels

  • ALL:打印所有日志
  • TRACE:追踪框架详细流程日志,一般不使用
  • DEBUG:开发调试细节日志
  • INFO:关键、感兴趣信息日志
  • WARN:警告但不是错误的信息日志,比如:版本过时
  • ERROR:业务错误日志,比如出现各种异常
  • FATAL:致命错误日志,比如jvm系统崩溃
  • OFF:关闭所有日志记录

所有支持的日志系统都可以使用 logging.level.<logger-name>=<level>Spring Environment 中设置记录器级别(例如,在 application.properties/yaml 中),其中 levelTRACEDEBUGINFOWARNERRORFATALOFF 之一。可以使用 logging.level.root 配置 root 记录器。

以下示例显示了 application.properties 中潜在的日志记录设置:

logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
logging:
level:
root: "warn"
org.springframework.web: "debug"
org.hibernate: "error"

还可以使用环境变量设置日志记录级别。例如, LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG 会将 org.springframework.web 设置为 DEBUG

Log Groups

将相关记录器分组在一起通常很有用,以便可以同时配置它们。例如,您可能通常会更改所有 Tomcat 相关记录器的日志记录级别,但您无法轻松记住顶级包。

为了帮助解决这个问题,Spring Boot 允许您在 Spring Environment 中定义日志记录组。例如,以下是如何通过将tomcat组添加到 application.properties 来定义它:

logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat

# 定义后,您可以使用一行更改组中所有记录器的级别:
logging.level.tomcat=trace

Spring Boot 包含以下可以开箱即用的预定义日志记录组

Name Loggers
web org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

File Output

默认情况下,Spring Boot 只记录日志到控制台,不写入日志文件。如果除了控制台输出之外还想写入日志文件,则需要设置 logging.file.namelogging.file.path 属性(例如,在 application.properties 中)。

下表显示了如何一起使用 logging.* 属性:

logging.file.name logging.file.path Example Description
(none) (none) Console only logging.
Specific file (none) my.log Writes to the specified log file. Names can be an exact location or relative to the current directory.
(none) Specific directory /var/log Writes spring.log to the specified directory. Names can be an exact location or relative to the current directory.

File Rotation

如果您使用 Logback,则可以使用 application.propertiesapplication.yaml 文件微调日志轮换设置。对于所有其他日志系统,您需要自己直接配置轮换设置(例如,如果您使用 Log4j2,则可以添加 log4j2.xmllog4j2-spring.xml 文件)。

支持以下轮换策略属性:

Name Description
logging.logback.rollingpolicy.file-name-pattern 用于创建日志存档的文件名模式。
logging.logback.rollingpolicy.clean-history-on-start 应用程序启动时是否应进行日志归档清理。
logging.logback.rollingpolicy.max-file-size 归档之前日志文件的最大大小。
logging.logback.rollingpolicy.total-size-cap 日志归档在被删除之前可以占用的最大大小。
logging.logback.rollingpolicy.max-history 要保留的归档日志文件的最大数量(默认为 7)。

Custom Log Configuration

可以通过在类路径中包含适当的库来激活各种日志记录系统,并且可以通过在类路径的根目录中或在以下 Spring Environment 属性指定的位置中提供适当的配置文件来进一步自定义: logging.config

您可以通过使用 org.springframework.boot.logging.LoggingSystem 系统属性强制 Spring Boot 使用特定的日志系统。该值应该是 LoggingSystem 实现的完全限定类名。您还可以使用 none 值完全禁用 Spring Boot 的日志记录配置。

由于日志记录是在创建 ApplicationContext 之前初始化的,因此无法控制 Spring @Configuration 文件中 @PropertySources 的日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

建议在日志记录配置中使用 -spring 变体(例如, logback-spring.xml 而不是 logback.xml )。如果使用标准配置位置, Spring 无法完全控制日志初始化。