本章内容包括:
- 介绍Spring Boot
- 项目结构和一个生成的项目的各种元素
- 创建可执行的JAR文件和生成的JAR文件结构
- Spring Boot Starter、自动配置、故障分析器和actuator的概述
- 介绍Spring Boot开发者工具,以提高开发者的生产力

欢迎来到Spring Boot,这是目前最受欢迎的Java框架!它彻底改变了Spring应用程序,或更具体地说,Java应用程序的开发方式。Spring Boot是Spring Framework的开源扩展,旨在简化Spring应用程序的开发。Spring Boot之所以受欢迎,主要归功于它能够快速创建独立、可投入生产的基于Spring的应用程序,而且您几乎无需担心配置问题。
本章将对Spring Boot进行概述,讨论Spring Boot是什么,它的目的是什么,项目结构以及一些关键的Spring Boot特性。准备好了吗?让我们启动我们的旅程吧!
1.1 介绍Spring Boot
在本节中,我们将介绍Spring Boot框架,并简要回答一些关于Spring Boot的常见问题。我们将讨论为什么需要Spring Boot框架,介绍框架的各种特性以及框架的各个组件。
1.1.1 为什么需要Spring Boot
当我们踏上这个美妙的旅程,开始熟悉Spring Boot时,首先出现在我们脑海中的问题是:为什么我们要首先学习它?为了找到这个问题的答案,让我们先了解一下Spring Boot承诺要解决的问题。
Spring Framework开始了简化Java企业应用程序开发的旅程。它因其简化的应用程序开发策略和强大的框架特性而广受欢迎。随着Spring作为一个框架的使用增加,进一步简化Spring应用程序开发过程的需求也日益增加。
尽管Spring为开发者提供了很多支持,使得他们可以专注于解决业务问题,但在Spring Boot出现之前,开发者仍然需要做大量的工作来让事情正常运行。举个例子,一旦您开始开发基于Spring的Web应用程序,您将面临以下一些挑战:
- 理解Servlet以及相关的部署描述符web.xml的概念。
- 熟悉WAR和EAR目录结构,以打包应用程序组件。
- 在部署应用程序时了解特定于应用服务器的概念,比如域名、端口、线程和数据源。
- 处理复杂的类加载策略、应用程序监控、管理概念(management concepts)和日志记录功能。
有太多的技术术语存在。如果您只需要编写应用程序的业务逻辑,构建一个可执行文件,然后在命令行中运行它,而不需要定义复杂的XML配置或进行应用服务器部署或其他技术上的复杂操作,那该有多好?所有这些谜团都会被一些经验丰富的魔术师神奇地解决,是不是很令人印象深刻?好吧,您很快会发现Spring Boot就是这个魔术师。
Spring Boot作为Spring Framework的一个子项目推出,旨在为开发者提供快速的启动体验,并减免他们大部分的配置困扰。在您继续Spring Boot的旅程中,您会注意到Spring Boot如何无缝地解决了许多配置和集成问题。例如,在您的Spring Boot项目中,您不需要强制定义部署描述符web.xml文件。除非您明确决定在应用服务器上运行应用程序,否则您也不需要使用应用服务器来运行您的应用程序。大多数情况下,Spring Boot的默认配置就可以满足您的需求。
1.1.2 Spring Boot是什么
Spring Boot于2014年4月发布,旨在减轻开发Java Web应用程序时的一些负担。它允许开发者更多地专注于业务逻辑,而不是繁琐的技术代码和相关配置。Spring Boot的目标是为应用程序开发者创建基于Spring的独立的、可投入生产的应用程序,减少了开发者在配置方面的工作量。它对Spring Framework采取了一种具有明确观点的看法,使应用程序开发者能够迅速开始所需的工作。它为用户提供了一个额外的层,用于简化某些配置方面的操作。
图1.1展示了Spring Boot如何置身于您(作为应用程序开发者)和Spring Framework之间。作为一个中间层,Spring Boot执行许多配置,如果您直接与Spring Framework进行交互,您将需要自行完成这些配置。
图1.1 显示了Spring Boot的开发者视图。它置身于开发者和Spring Framework之间。Spring Boot根据开发者使用的Spring组件自动配置了一些Spring Framework组件。

1.1.3 Spring Boot的核心特性
Spring Boot有几个显著的特点使其在其他框架中脱颖而出:
- 快速启动:Spring Boot的主要目标之一是提供快速启动体验,让Spring应用程序的开发变得迅速。使用传统方式构建一个Spring的Web应用程序可能需要以下步骤:配置一个包含Spring MVC依赖的Maven或Gradle项目。配置Spring MVC的DispatcherServlet。将应用程序组件打包成WAR文件。将WAR文件部署到Servlet容器(例如,Apache Tomcat)。
使用Spring Boot,您只需指定应用程序所需的依赖,Spring Boot将为您处理其余的事情。 - 自动配置:Spring Boot自动配置Spring应用程序的最小组件。它基于类路径中的JAR文件的存在或配置在各种属性文件中的属性来完成自动配置。例如,如果Spring Boot在类路径中检测到数据库驱动的JAR文件(例如H2内存数据库JAR),它将自动配置相应的数据源以连接到数据库。
- 观点明确:Spring Boot是一个观点明确的框架。它自动配置多个组件来启动Spring应用程序。Spring Boot通过一组起始依赖项实现这一点。起始依赖项针对应用程序开发的特定领域,提供了相关的依赖项。例如,如果您需要开发Web应用程序,可以配置spring-boot-starter-web依赖项,它会确保所有与Web应用程序开发相关的依赖项,如spring-web和spring-webmvc,在应用程序的类路径中可用。
- 独立运行:Spring Boot应用程序内嵌了一个Web服务器,因此它们可以独立运行,不一定需要外部的Web或应用服务器。这使得Spring Boot应用程序可以打包成可执行的JAR文件,并使用java -jar命令运行。这也使得Spring Boot应用程序可以很容易地被容器化,成为云原生应用程序开发的候选者。
- 生产就绪:Spring Boot提供了一些有用的生产就绪功能,用于监控和管理应用程序一旦部署到生产环境中,例如健康检查、线程转储(thread dumps)和其他有用的指标。
1.1.4 Spring Boot的组件
Spring Boot由多个组件组成,每个组件专注于应用程序开发的特定领域。其中一些是核心组件,您将在几乎每个Spring Boot项目中经常使用。例如,spring-boot是几乎每个Spring Boot项目中主要使用的组件。图1.2显示了Spring Boot的组件,并以下面的列表简要介绍这些组件:
- spring-boot:这是主要的Spring Boot组件,为其他组件提供支持。它包含SpringApplication类,其中包含几个静态方法用于创建独立的Spring Boot应用程序。它还提供对嵌入式Web服务器(例如Tomcat)的支持,并支持外部化的应用程序配置(例如您的应用程序的数据库详细信息)等。
- spring-boot-autoconfigure:这个组件提供了对Spring Boot应用程序的自动配置所需的支持。Spring Boot自动配置根据类路径中的依赖项和配置的属性来猜测和配置Spring bean。但是,如果检测到用户配置的具有自定义配置的bean,自动配置会撤回默认配置。
- spring-boot-starters:starter依赖是一组预配置的依赖项描述符,用于方便开发者。Spring Boot Starter可以帮助开发者获取一组Spring和相关技术,否则开发者需要自行管理。
- spring-boot-CLI:这是一个友好的开发者命令行工具,用于编译和运行Groovy代码。它还可以监听文件的变化,因此在对应用程序进行修改时不需要重新启动应用程序。这个CLI工具免除了您使用Maven或Gradle等依赖管理工具的需要。同时,它允许您快速原型化Spring应用程序,无需过多担心依赖管理和其他构建相关问题。有关如何使用Spring Boot CLI,请参阅附录A。
- spring-boot-actuator:这个组件提供了用于与Spring Boot应用程序交互、监控和审计的actuator端点。在Spring Boot中,actuator可以通过JMX或HTTP端点进行管理。Spring Boot提供了一组预定义的actuator端点,涵盖了多个应用程序方面。如果这不能满足您的需求,您还可以创建与应用程序特定的自定义actuator端点。Spring Boot actuator还提供配置,让您决定要启用哪些actuator端点,并提供了多种方式来保护它们,防止未经授权的访问。
- spring-boot-actuator-autoconfigure:这个组件支持根据类路径自动配置actuator端点。例如,如果类路径中存在Micrometer(https://micrometer.io)的依赖项,则Spring Boot会自动配置MetricsEndpoint。
- spring-boot-test:这个模块包含注解和方法,用于编写Spring Boot应用程序的测试用例。
- spring-boot-test-autoconfigure:这个组件支持自动配置应用程序的测试用例。
- spring-boot-loader:这个组件允许将Spring Boot应用程序打包为单个的fat JAR文件,包括所有依赖项和内嵌的Web服务器,可以独立运行。您不会独立使用这个模块,而是与Maven或Gradle插件一起使用。
- spring-boot-devtools:这个组件包含额外的开发者工具,用于提供Spring Boot应用程序的顺畅开发体验。工具包括自动检测应用程序代码更改和LiveReload服务器,可自动刷新浏览器中的任何HTML更改。开发者工具旨在提高开发者的生产率。
图1.2 Spring Boot的组件

1.2 代码示例
在本节中,我们将讨论代码示例以及我们将用于开发示例的技术。我们将介绍构建系统、编程语言和在本书中使用的数据库。我们还将向您介绍Lombok,它可以通过简单的注解帮助我们简化POJO类的定义。
1.2.1 Maven vs. Gradle
Spring Boot允许您使用Apache Maven或Gradle构建工具创建Spring Boot项目。在Spring Initializr(https://start.spring.io/)工具中,您可以选择您喜欢的构建系统并生成项目。在本书中,我们将使用Gradle作为首选的构建系统。
1.2.2 Java vs. Kotlin
您可以在Spring Boot项目中同时使用Java和Kotlin(https://kotlinlang.org/)编程语言。Spring Framework 5.0已经整合了对Kotlin的支持,自那时以来,Spring Framework一直在不断努力提供更好的Kotlin支持。例如,在Spring Security 5.3中,Spring团队引入了Kotlin版本的特定领域语言(DSL)支持到Spring Security。您可以在https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0上了解更多关于Spring Framework对Kotlin的支持。
在本书中,我们将主要在大部分代码示例中使用Java作为首选语言。我们将在第10章中介绍Spring Framework(通过Spring Boot)中的主要Kotlin特性。
1.2.3 数据库支持
本书中的几个代码示例需要数据库访问来演示概念。Spring Boot扩展了对一系列SQL和NoSQL数据库的支持。为了方便测试代码示例,我们将在所有代码示例中(有几个例外)使用H2内存SQL数据库。
1.2.4 Lombok
Lombok是一个Java库,它根据普通Java对象(POJO)类中的几个注解自动生成构造函数、getter、setter、toString等方法。您只需要在POJO类中使用适当的注解。例如,要为POJO类中的所有成员变量生成getter方法,您可以在类中指定@Getter注解。在本书的代码示例中,我们将使用Lombok。
如果您不想使用Lombok,您可以简单地按照代码中适用的情况提供getter、setter和构造函数。代码示例应该按预期工作。
记录类(Records Classes)
Java 14引入了Java语言中的记录类(Records Classes)。记录类是不可变的数据类,您只需指定字段的类型和名称。然后,Java编译器会自动生成equals、hashCode和toString方法。它还会生成私有final字段、getter方法和公共构造函数。如果您不想使用第三方库,比如Lombok,您可以考虑使用记录类。记录类可以定义如下:
public record Course(int id, String name, String description, int rating) {}
编译器将生成带有所有定义字段的公共构造函数,并提供与字段名称相同的getter方法(例如,id(),name()等),以及equals和hashCode方法。您可以在https://docs.oracle.com/en/java/javase/14/language/records.html找到关于Java记录类的更多信息。
1.3 开始使用Spring Boot
您现在对Spring Boot有了一个概览,并且了解了这个框架的目的。在本节中,您将学习如何生成一个Spring Boot项目以及生成的项目的各个部分。
1.3.1 你的第一个Spring Boot项目
Spring Boot提供了一个名为Spring Initializr的工具,可以让您生成一个简单的Spring Boot项目框架。您可以访问Spring Initializr工具的网址:https://start.spring.io。此外,Spring Boot还提供了API,允许主流的集成开发环境(IDE)集成Spring Initializr,并在IDE中提供内置支持来生成Spring Boot项目。如果您对Spring Initializr还不熟悉,请参考附录A,了解创建Spring Boot项目的各种方法。
将下面的链接拷贝到您的浏览器,并打开,点击下方的GENERATE按钮,将创建本章要使用的Spring Boot项目结构:
https://start.spring.io/#!type=gradle-project&language=java&platformVersion=3.1.1&packaging=jar&jvmVersion=17&groupId=com.sbip.ch01&artifactId=spring-boot-app-demo&name=spring-boot-app-demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.sbip.ch01&dependencies=web
1.3.2 Spring Boot项目结构
生成的Spring Boot项目结构相对简单,只包含您在进行Spring Boot应用程序开发时所需的组件。它包含以下组件:
- 一个build.gradle文件,其中包含您在项目生成过程中选择的依赖项。
- 一个gradle wrapper相关的文件,允许您在本地机器上不安装Gradle的情况下构建项目。
- 一个包含源代码和测试Java文件的包结构,分别位于src/main/java和src/test/java下。源代码包含一个带有main方法的Java类,而测试包中有一个空的测试类。
- 一个资源文件夹位于src/main/resources,并包含一个空的application.properties文件。
tree spring-boot-app-demo
spring-boot-app-demo
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── HELP.md
├── settings.gradle
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── sbip
│ │ └── ch01
│ │ └── SpringBootAppDemoApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── com
└── sbip
└── ch01
└── SpringBootAppDemoApplicationTests.java
让我们详细讨论生成的项目的关键组件:
build.gradle文件
生成的项目的build.gradle文件如下所示:
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.sbip.ch01'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
id 'org.springframework.boot' version '3.1.1' 引入了Spring Boot的gradle插件。id 'io.spring.dependency-management' version '1.1.0'引入了Spring的依赖管理gradle插件。
Spring Boot的Gradle插件提供了很多Gradle任务,简化了许多应用程序的构建管理工作。表1.1显示了Spring Boot Gradle插件的的可用任务列表和简要描述。
表1.1 Spring Boot Gradle插件提供的task列表
task名称 | 描述 |
bootBuildImage | 使用bootJar任务的输出构建应用程序的OCI镜像 |
bootJar | 构建一个可执行的JAR存,其中包含main classes和它们的依赖项 |
bootRun | 直接运行这个Spring Boot应用程序 |
bootTestRun | 使用测试运行时类路径将该项目作为Spring Boot应用程序运行 |
例如如果你想在直接在项目目录上直接运行当前的Spring Boot应用程序,可以直接在终端上执行以下命令gradle bootRun:
gradle bootRun
executing gradlew instead of gradle
> Task :bootRun
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.1)
INFO--- [main] c.s.ch01.SpringBootAppDemoApplication : Starting SpringBootAppDemoApplication using Java 17.0.4.1 with PID 3566379
INFO--- [main] c.s.ch01.SpringBootAppDemoApplication : No active profile set, falling back to 1 default profile: "default"
INFO--- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
INFO--- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
INFO--- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.10]
INFO--- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
INFO--- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 756 ms
INFO--- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
INFO--- [main] c.s.ch01.SpringBootAppDemoApplication : Started SpringBootAppDemoApplication in 1.361 seconds (process running for 1.585)
<==========---> 80% EXECUTING [18s]
> :bootRun
build.gradle文件的dependencies{}块中包含两个spring-boot-starter-web和spring-boot-starter-test两个Spring Boot启动器依赖项。spring-boot-starter-web启动器依赖项包含构建Web应用程序所需的必要JAR文件,而spring-boot-starter-test启动器依赖项允许您为应用程序编写测试用例。
Spring Boot starter dependency
Spring Boot启动器依赖项旨在使Spring Boot应用程序的开发变得简单、快速和高效。如果您之前有使用Apache Maven或Gradle等构建工具开发Java应用程序的经验,您可能记得管理依赖项是应用程序开发者面临的主要挑战之一。
首要的挑战是确定开发应用程序特定组件所需的库(依赖项)。一旦确定了这些库,您需要找到正确的库版本。即使找到了正确的库和版本,在应用程序开发这个快节奏的世界中,很容易与库版本不同步。此外,您选择的依赖项还有它们自己的依赖项,或者更准确地说是传递性依赖项。在某些情况下,您甚至需要对这些依赖项进行控制。Spring Boot启动器依赖项是Spring Boot中的解决方案,可解决上述所有问题。
启动器依赖项将一组您可能需要开发应用程序某个部分所需的依赖项组合在一起。如果您选择使用Spring Boot开发Web应用程序,您很可能会选择spring-boot-starter-web依赖项。它确保您的应用程序中可用于开发Web应用程序的所有必需依赖项。当然,这是有偏见的,您将得到Spring团队建议开发Web应用程序所需的一组依赖项。然而,关键的部分在于,您不必再担心依赖项版本控制、升级以及许多其他问题。
启动器依赖项还可以依赖于另一个启动器依赖项。例如,spring-boot-starter-web需要一些常用的启动器依赖项,例如spring-boot-starter,spring-boot-starter-tomcat和spring-boot-starter-json依赖项。这些启动器又分别引入了与Spring Boot、Tomcat和JSON相关的其他一组依赖项。您可以参考Spring Boot文档以获取可用的Spring Boot启动器列表,网址为:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.build-systems.starters。
启动器依赖项的概念是可扩展的。Spring Boot允许您构建自定义启动器,供应用程序使用。对于大型应用程序,这对于模块化和管理依赖项非常有用。您将在本书后面学习如何创建自定义启动器。
spring-boot-starter-test为测试Spring Boot应用程序提供了必要的测试支持,从Spring Boot 3.x开始引入的用于编写测试的框架和库如下:
- Spring Boot Test & Spring Test
- JUnit 5 - JUnit Platform + JUnit Jupiter
- AssertJ - 流式风格断言框架
- Hamcrest - 断言匹配器框架
- Mockito - Mock框架
spring boot main class
在生成的项目中,你会发现Spring Initializr生成了一个包含Java main()方法的Java类。以下内容显示了这个类的代码。
package com.sbip.ch01;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootAppDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAppDemoApplication.class, args);
}
}
让我们来查看一下生成的Java文件中的包含以下组件:
- 使用了main()方法
- 使用了@SpringBootApplication注解
- SpringApplication类的作用
通常,要运行一个Web应用程序,您需要将应用程序组件构建和打包成WAR或EAR存档文件,并将其部署到Web服务器(如Apache Tomcat)或应用程序服务器(如Red Hat JBoss)中。Spring Boot在一定程度上简化了这个过程。它不强制你构建应用程序的WAR或EAR文件。相反,它允许你像运行普通的Java应用程序一样,使用传统的main()方法来运行Spring Boot应用程序。
尽管Spring Boot遵循一个熟悉的方法,让开发者的工作简单,但它在幕后执行了相当多的工作。例如,基于Servlet的Web应用程序只能在Servlet容器(如Apache Tomcat或Jetty)中运行。Spring Boot通过在应用程序中默认使用嵌入式的Apache Tomcat服务器来实现这种支持。因此,当您使用main()方法启动Spring Boot应用程序时,Spring Boot会启动一个嵌入式的Apache Tomcat服务器实例,并在其中运行Web应用程序。
如果你进一步探索spring-boot-starter-web依赖项,你会发现它有一个对spring-boot-starter-tomcat模块的传递依赖。您可以在build.gradle文件所在的路径上执行gradle dependencies命令,来探索应用程序的依赖树。
生成的Java文件中的SpringBootAppDemoApplication类被标注了@SpringBootApplication注解。这是一个方便的注解,它包含了三个注解:@EnableAutoConfiguration、@ComponentScan和@SpringBootConfiguration,每个注解在应用程序中执行特定的任务。
让我们根据它们的功能来了解这些注解:
- @EnableAutoConfiguration:Spring Boot提供了几个@Enable*注解,用于在Spring Boot应用程序中启用特定功能。@EnableAutoConfiguration注解提供了必要的支持,使Spring Boot能够根据应用程序类路径中存在的JAR依赖项自动配置你的应用程序。你将在第4章中更多地了解自动配置。
- @ComponentScan:提供了对应用程序中Spring组件包的扫描支持。在Spring中,组件是由Spring管理并且带有@Component、@Bean或特定组件注解的Java bean。有了@ComponentScan注解,Spring Boot应用程序将扫描根包及其子包中的所有组件,并管理它们的生命周期。需要记住的关键点是@ComponentScan从根包开始扫描,并继续到所有子包。因此,如果您有不在根包或其子包中的包,这些组件将不会被组件扫描所发现。
- @SpringBootConfiguration:该注解表示被注解的类提供Spring Boot应用程序的配置。它是用Spring的@Configuration元注解进行注解,以便Spring Boot可以自动找到被注解类中的配置。因此,在这个主类中定义的bean可以被Spring自动检测和加载。
此外,注意Spring Boot应用程序的main class需要位于应用程序的根包中,因为在该类中配置了@SpringBootApplication注解。@SpringBootApplication注解使用根包作为base包。Spring Boot会自动扫描此base包及其所有子包,以加载Spring组件(例如,使用@Component、@Configuration和其他Spring注解配置的类)和其他类型的组件。https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.structuring-your-code.locating-the-main-class中有更多的详细信息。
接下来,生成的Java文件中使用了SpringApplication类。SpringApplication类由Spring Boot提供,用于方便地启动Spring Boot应用程序。大多数情况下,您将使用SpringApplication的静态run()方法来启动和运行应用程序。执行run()方法时,Spring Boot会执行以下几个活动:
- 基于类路径中存在的库创建一个ApplicationContext实例。
- 注册一个CommandLinePropertySource,将命令行参数公开为Spring属性。
- 刷新在步骤1中创建的ApplicationContext,以加载所有的单例bean。
- 触发在应用程序中配置的ApplicationRunners和CommandRunners。
关于ApplicationContext
绝大多数Java应用程序都由对象组成。这些对象相互交互,并且它们之间存在依赖关系。为了有效地管理对象的创建和相互依赖,Spring使用了依赖注入(DI)的原理。这种依赖注入或控制反转(IoC)的方法让Spring创建对象(或者更恰当地说,在Spring术语中是"bean")并从外部注入依赖关系。Bean的定义可以通过XML bean定义文件(例如applicationContext.xml)或通过基于注解的配置(@Configuration注解)提供给Spring。Spring会加载这些bean的定义,并将它们保留在Spring IoC容器中。
ApplicationContext接口充当Spring IoC容器。Spring根据应用程序类型(Servlet或Reactive应用程序)、bean定义配置(例如从类路径加载还是基于注解加载)等,提供了大量的ApplicationContext实现。可以参考ApplicationContext接口的Java文档来了解更多关于它及其可用子类型的信息。
SpringApplication类尝试根据类路径中存在的JAR依赖项创建一个ApplicationContext实例。Spring Boot Web应用程序可以是基于Servlet的,也可以是响应式(reactive)的类型。通过利用Spring的类加载技术,并根据类路径中的类的可用性,Spring推断当前应用程序的类型。一旦应用程序类型确定,Spring Boot采用以下策略来加载ApplicationContext:
- 如果应用程序被识别为基于Servlet的Web应用程序,Spring Boot尝试创建AnnotationConfigServletWebServerApplicationContext类的实例。
- 或者,如果应用程序是响应式类型,Spring Boot创建AnnotationConfigReactiveWebServerApplicationContext类的实例。
- 如果应用程序既不是基于Servlet的,也不是响应式应用程序,Spring Boot尝试创建AnnotationConfigApplicationContext类的实例。
你可以使用SpringApplication类的静态run()方法来启动Spring Boot应用程序。虽然使用静态run()方法很方便,但Spring Boot还允许你创建SpringApplication类的实例来自定义应用程序的引导模式。例如,如果你了解应用程序的类型,可以直接在SpringApplication实例中设置它,如下面的示例所示:
package com.sbip.ch01;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootAppDemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringBootAppDemoApplication.class);
springApplication.setWebApplicationType(WebApplicationType.SERVLET);
springApplication.run(args);
}
}
SpringApplication还提供了一些setter方法,可以用来控制各种Spring Boot功能,例如设置额外的Spring配置文件或设置资源加载器来加载应用程序资源。可以参考最新版本的Spring Boot参考手册来了解更多关于SpringApplication的信息,例如你可以了解如何定制Spring Boot应用程序在启动时打印输出的banner信息。
使用application.yml文件进行配置管理
Spring Initializr会在src/main/resources文件夹中生成一个空的application.properties文件。这个属性文件允许进行将各种应用配置。这个属性文件允许您以键值对格式指定配置,其中键和关联的值由=字符分隔。下面的示例显示了在application.properties文件中配置Spring Boot应用程序的服务器地址和端口的示例配置。
server.address=localhost
server.port=8081
management.endpoints.web.exposure.include=*
更推荐使用YAML文件格式来配置应用程序属性。YAML允许你以层次结构的方式定义属性。如果你想使用YAML文件格式,可以将现有的application.properties文件重命名为application.yml,并以YAML格式指定属性。以下示例显示了与之前属性文件的等效YAML配置。
server:
address: localhost
port: 8080
management:
endpoints:
web:
exposure:
include: '*'
可以在Spring Boot文档的https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html中,查看支持的application.properties属性列表。随着我们进一步的学习,你会惊讶的发现,仅通过添加一个应用程序配置属性,就可以在应用程序行为上实现巨大的变化。
在本节中,已经探索了Spring Boot应用程序的核心组件。现在,你应该熟悉了整个Spring Boot项目结构,build.gradle文件的组件,@SpringBootApplication注解,SpringApplication类以及强大的application.properties属性配置。通过这些属性配置,你可以通过各种内置和自定义属性来控制Spring Boot应用程序的行为。
1.3.3 创建可执行的jar文件
从Spring Boot项目创建可执行的JAR文件最简单的方法是使用gradle bootJar命令。一个JAR文件将被创建在项目的build/libs目录下。生成的JAR文件可以通过命令行中的java -jar命令来执行,以启动应用程序。
1.3.4 探索jar文件
如果您探索生成的JAR文件,您会发现如下所示的结构,如下所示:
jar -xvf spring-boot-app-demo-0.0.1-SNAPSHOT.jar
tree .
.
├── BOOT-INF
│ ├── classes
│ │ ├── application.properties
│ │ ├── com
│ │ │ └── sbip
│ │ │ └── ch01
│ │ │ └── SpringBootAppDemoApplication.class
│ │ ├── static
│ │ └── templates
│ ├── classpath.idx
│ ├── layers.idx
│ └── lib
│ ├── <dependencies jars>
├── META-INF
│ └── MANIFEST.MF
├── org
│ └── springframework
│ └── boot
│ └── loader
│ ├── <spring boot loader classes>
我们可以将结构大致分为四个部分:
- META-INF - 此部分包含MANIFEST.MF文件,其中包含需要执行的JAR的许多关键信息。在该文件中提供的两个关键参数是Main-Class和Start-Class的详细信息。Manifest-Version: 1.0 Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.sbip.ch01.SpringBootAppDemoApplication Spring-Boot-Version: 3.1.1 Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Spring-Boot-Layers-Index: BOOT-INF/layers.idx Build-Jdk-Spec: 17 Implementation-Title: spring-boot-app-demo Implementation-Version: 0.0.1-SNAPSHOT
- Spring Boot加载器组件(spring boot loader) — Spring Boot加载器提供了几种加载器实现,用于加载可执行文件。例如,JarLauncher类加载JAR文件,WarLauncher类加载WAR文件,而PropertiesLauncher类允许您通过一组loader.*属性自定义类加载。
- BOOT-INF\classes — 所有应用程序类文件都打包在此文件夹中。
- BOOT-INF\lib — 此文件夹包含应用程序的所有依赖项。
需要注意的一点是在MANIFEST.MF文件中使用Main-Class和Start-Class参数。Main-Class包含Launcher类名,该类使用在Start-Class中指定的类来启动应用程序。在Spring Boot可执行JAR中,Start-Class始终是您的Spring Boot main class。
classpath.idx文件是一个索引文件,它列出了依赖项以及类加载器应该加载它们的顺序。layer.idx文件用于允许将JAR分成逻辑层以进行Docker或OCI镜像创建的JAR。在第9章中,当您从Spring Boot应用程序创建Docker镜像时,您将探索如何使用layer.idx文件。
1.3.5 关闭Spring Boot应用程序
关闭和执行Spring Boot应用程序可能相当简单。如果您通过命令行将JAR作为前台进程执行,您可以使用Ctrl-C(在Windows和Linux中)终止Java进程。同样,如果应用程序作为后台进程运行,您可以使用适当的操作系统特定命令来终止Java进程。
在没有任何额外配置的情况下,上述讨论的方法会立即终止Spring Boot应用程序,并且不会为其提供任何范围来处理当前正在执行的请求(如果有的话)。这可能会影响应用程序的用户体验。因此,您需要确保应用程序进行优雅的关闭,应该允许当前请求得到处理,但在最终终止之前不应该接收新的请求。
Spring Boot提供了额外的配置来在应用程序中启用优雅的关闭。您可以在application.yml文件中配置这些属性,如下面的示例所示。
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 1m
server.shutdown属性的默认值是immediate,表示应用程序立即关闭。一旦您配置了优雅的关闭,您还可以配置应用程序等待当前请求完成的超时时间。请注意,spring.lifecycle.timeout-per-shutdown-phase属性的默认值为30s。如果默认值对您的应用程序不合适,您可以配置自定义的超时值。在上面的示例中,我们将超时时间配置为1分钟。
1.4 Spring Boot的其他概念
在本节中,我们将简要介绍一些有用的Spring Boot概念。其中一些是该框架的关键概念,我们将在随后的章节中进行详细讨论。
1.4.1 Spring Boot启动事件
Spring框架的事件管理机制促进了应用程序中事件发布者和订阅者的解耦,允许您订阅框架的内置事件以及定义自定义事件。
Spring Boot框架还提供了几个内置事件,您可以订阅这些事件以执行特定的操作。例如,如果您的Spring Boot应用程序完全初始化后需要调用外部REST API,那么这里可能有这样的需求。在本节中,我们将介绍几个Spring Boot事件,在应用程序启动和初始化的不同阶段发布:
- ApplicationStartingEvent:在应用程序启动的开始阶段发布,一旦Listeners注册完成。Spring Boot的LoggingSystem使用此事件来在应用程序初始化之前执行任何需要的操作。
- ApplicationEnvironmentPreparedEvent:在应用程序启动时发布,Environment已准备好供检查和修改。Spring Boot内部使用此事件来预初始化几个服务,例如MessageConverter、ConversionService、初始化Jackson等。
- ApplicationContextInitializedEvent:在ApplicationContext准备好时发布,执行ApplicationContextInitializer,但尚未加载任何bean定义。可以在Spring容器中的bean初始化之前执行任务。
- ApplicationPreparedEvent:在ApplicationContext准备好时发布,bean定义已加载但未刷新。此阶段的Environment已准备好供使用。
- ContextRefreshedEvent:在ApplicationContext刷新时发布。此事件来自Spring而不是Spring Boot。此事件不继承自SpringApplicationEvent。Spring Boot的ConditionEvaluationReportLoggingListener监听此事件,并在发布此事件后打印自动配置报告。
- WebServerInitializedEvent:在Web服务器准备就绪时发布。根据应用程序的类型,此事件有两个变体:ServletWebServerInitializedEvent用于基于Servlet的应用程序,ReactiveWebServerInitializedEvent用于响应式应用程序。此事件不继承SpringApplicationEvent。
- ApplicationStartedEvent:在ApplicationContext刷新之后但在调用ApplicationRunner和CommandLineRunners之前发布。
- ApplicationReadyEvent:由SpringApplication发布,表示应用程序已准备好处理请求。不建议更改应用程序的内部状态,因为所有应用程序初始化步骤都已完成。
- ApplicationFailedEvent:当有一些异常发生,应用程序无法启动时发布。此事件对于执行脚本或通知启动失败等任务很有用。
1.4.2 在Spring Boot应用程序中监听事件
在应用程序启动时,Spring Boot事件提供有关应用程序初始化的各个阶段的有用信息。如果您需要对应用程序启动行为进行编程控制,这些事件非常有用。最简单的方法是订阅这些事件并采取必要的操作。例如,如果您需要修改Environment中的任何参数,您可以订阅ApplicationEnvironmentPreparedEvent并进行修改。Spring Boot在内部使用这些事件来初始化应用程序的多个组件。
让我们讨论订阅这些事件的不同方法。最简单的方法是使用Spring Framework的@EventListener注解。例如,要监听ApplicationReadyEvent事件,您可以使用以下代码片段:
@EventListener(ApplicationReadyEvent.class)
public void applicationReadyEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("Application Ready Event generated at " + new Date(applicationReadyEvent.getTimestamp()));
}
上面的代码片段打印了ApplicationReadyEvent生成时的时间戳。虽然@EventListener在大多数情况下工作得很好,但对于在应用程序启动非常早期发布的事件,例如ApplicationStartingEvent和ApplicationEnvironmentPreparedEvent,它可能不起作用。在本节中,我们将讨论另外两种在Spring Boot应用程序中监听事件的方法。
使用SpringApplication
通常,在生成的Spring Boot项目中,应用程序类会调用SpringApplication的静态run()方法来启动应用程序。然而,SpringApplication类还提供了一些setter方法,用于自定义应用程序的启动行为。例如,它允许您通过各种setter方法添加ApplicationContextInitializer、设置ApplicationListener等等。要使用SpringApplication来监听事件,您可以创建一个合适的ApplicationListener类,并实现onApplicationEvent()方法。下面的示例展示了一个自定义监听器,用于监听Spring Boot的ApplicationStartingEvent事件:
创建一个自定义的ApplicationListener:
package com.sbip.ch01;
import java.util.Date;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationListener;
public class ApplicationStartingEventListener implements ApplicationListener<ApplicationStartingEvent> {
@Override
public void onApplicationEvent(ApplicationStartingEvent event) {
System.out.println("Application Starting Event logged at " + new Date(event.getTimestamp()));
}
}
然后,您可以将此监听器添加到SpringApplication中,这样一旦发布了ApplicationStartingEvent事件,相应的监听器就会被调用。以下是SpringApplication的实现示例:
package com.sbip.ch01;
import java.util.Date;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
@SpringBootApplication
public class SpringBootAppDemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringBootAppDemoApplication.class);
springApplication.addListeners(new ApplicationStartingEventListener());
springApplication.run(args);
}
}
在上述代码示例中,将自定义监听器添加到了SpringApplication实例中。addListeners(..)方法接受可变参数,因此您可以使用此方法添加任意数量的监听器。
使用SpringApplication的方法需要您在Spring Boot应用程序类中进行代码更改。如果这不方便,Spring Boot还提供了另一种方法,通过spring.factories属性文件来注册自定义监听器。让我们在下一节中探讨这种方法。
使用spring.factories文件
spring.factories文件为您提供了在Spring Boot框架中配置和定制某些应用程序功能的扩展点。例如,Spring Boot广泛使用此文件来配置初始化器、应用程序监听器、自动配置、故障分析器、模板提供程序等等。spring.factories文件是一个由键值对组成的属性文件。
一般来说,spring.factories文件甚至在Spring Boot之前就存在了,它是Spring Framework的一个核心特性之一。您可以在spring-beans JAR(Spring框架组件)内找到这个文件。
然而,Spring Boot提供了一种通过这个文件来配置某些自定义组件(例如ApplicationListener)的方法。spring.factories文件位于META-INF文件夹中,该文件夹位于src\main\resources文件夹内。以下是一个示例spring.factories文件的内容:
org.springframework.context.ApplicationListener=com.sbip.ch01.ApplicationStartingEventListener
在上面的示例中,属性的key是您正在配置的组件的类类型,而值是关联实现的完全限定类名。例如,在配置一个ApplicationListener时,键是完全限定的类类型org.springframework.context.ApplicationListener,而值是自定义监听器类com.sbip.ch01.ApplicationStartingEventListener。您可以用逗号分隔来配置多个监听器实现。在后面的章节中,您将详细了解在配置自定义自动配置、故障分析器等时使用spring.factories文件的方法。
1.4.3 自定义Spring Boot starters
在之前的示例中,您可能注意到了官方的Spring Boot starters的使用,这些starters由Spring Boot开发和维护。Starters是Spring Boot的一个关键特性,它简化了Spring Boot应用程序中的依赖管理。这个starters的概念也可以扩展到专有的代码和配置。Spring Boot扩展了其基础架构,让您可以定义自定义的starters,这样您就可以像定义其他应用程序构件一样定义和维护它们。在本书的后半部分,我们将演示如何定义一个自定义的starter。
1.4.4 自定义autoconfiguration
在本章的介绍中,我们提到Spring Boot是一种强有力的框架。在应用程序启动时,Spring Boot会根据可用的依赖、配置和其他因素自动配置各种应用程序组件。自动配置策略使得Spring Boot可以对某些应用程序组件表达自己的意见,并在Spring Boot应用程序的初始化和执行中起着重要作用。另外,自动配置特性也是可扩展的,您可以定义自己的自动配置。在本书的后面部分,我们将演示如何定义自定义的自动配置。
1.4.5 故障分析器
Spring Boot使用故障分析器的概念来分析应用程序的故障,并提供有关故障的详细诊断报告。故障分析器接受一个异常,并提供详细的FailureAnalysis(故障分析)信息。下面显示了在控制台上为PortInUseException打印的故障分析报告。如果您用于启动Spring Boot应用程序的端口不可用,就会出现此异常。
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 31080 was already in use.
Action:
Identify and stop the process that's listening on port 31080 or configure this application to listen on another port.
您可以扩展故障分析器的概念,并定义自己的自定义异常和故障分析器。例如,除了自定义自动配置之外,定义您的领域特定异常,并通过详细的故障分析报告来定义故障分析器的实现非常有用。在本书的后面部分,您将学习如何创建自定义的故障分析器。
1.4.6 Spring Boot actuator
Spring Boot的actuator功能允许您监视和与Spring Boot应用程序进行交互。在任何生产应用程序中,监视多个健康参数是相当普遍的。例如,您可以在应用程序中执行健康检查,以确定应用程序是否正常运行。此外,您还可以捕获应用程序的线程转储或堆转储,以进行各种分析。Spring Boot的actuator提供了大量用于生产环境的功能。要启用Spring Boot的actuator,您需要在build.gradle中包含spring-boot-starter-actuator依赖项。以下示例显示了这个依赖项的配置:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
默认情况下,Spring Boot将/actuator作为访问其他端点的基础端点暴露出来。默认情况下,仅启用/health和/info端点的HTTP访问。例如,如果您访问http://localhost:8080/actuator,您将看到如下内容:
curl -s http://localhost:8080/actuator | jq
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
}
}
}
如果您访问http://localhost:8080/actuator/health,您可以找到应用程序的状态。如果应用程序正在运行,状态将显示为UP。我们将在第四章详细讨论Spring Boot的actuator功能。
curl -s http://localhost:8080/actuator/health | jq
{
"status": "UP"
}
1.4.7 Spring Boot开发者工具(Developer Tools)
为了提高开发人员的生产力,Spring Boot提供了一组工具,使开发体验更加愉快。例如,它监视类路径的变化,并在任何更改时自动构建应用程序。此外,它还提供了内嵌的LiveReload服务器,可以在资源被修改时触发浏览器刷新。要在Spring Boot项目中包含开发者工具,您需要在build.gradle中添加spring-boot-devtools依赖项,如以下示例所示:
developmentOnly 'org.springframework.boot:spring-boot-devtools'
在运行完全打包的应用程序时,开发者工具会自动禁用。如果您的应用程序是通过java -jar命令启动的,或者使用特殊的类加载器启动的,那么它被视为“生产应用程序”。您可以通过使用spring.devtools.restart.enabled系统属性来控制这种行为。为了启用开发者工具,不管是哪种类加载器启动您的应用程序,设置-Dspring.devtools.restart.enabled=true系统属性。但在生产环境中绝对不要这样做,因为运行开发者工具可能带来安全风险。要禁用开发者工具,可以排除依赖项或设置-Dspring.devtools.restart.enabled=false系统属性。
在Maven中将依赖项标记为可选,或者在Gradle中使用developmentOnly配置(如上所示),可以防止开发者工具被传递应用到使用您的项目的其他模块。
总结
Spring Boot使您能够创建独立的、适用于生产环境的应用程序,您可以在不过多担心配置方面的情况下运行它。其自动配置和基于starter的依赖管理可以完成应用程序配置的大部分工作,使您可以专注于应用程序的业务方面。
在本章中,我们从各个方面对Spring Boot的特性和组件进行了概述。我们探讨了以下主要内容:
- Spring Boot是什么,以及相对于传统Spring应用程序它提供的优势。
- Spring Boot的特性及其各个组件。
- 生成的Spring Boot项目的结构和组件。
- 如何从Spring Boot项目创建可执行的JAR文件以及生成的JAR文件的结构。
- 如何优雅地关闭运行中的Spring Boot应用程序。
- Spring Boot的启动事件以及监听事件的各种方式。
- 自定义starter、自动配置、故障分析器和actuator的概述。
- Spring Boot开发者工具的介绍,以提高开发生产力。
本书的其余部分将专注于介绍在使用Spring Boot时解决常见问题的实际技术。您将了解广泛的主题领域,从Spring Boot应用程序开发、安全性、响应式应用程序开发,到基于云的部署等。