# Spring Boot 3 入门

# Spring Boot 介绍

Spring Boot 可以帮助我们创建独立运行、生产级别的基于 Spring 的应用程序。Spring Boot 遵循约定大于配置的思想,以便我们可以轻松上手。大多数 Spring Boot 应用程序只需要很少的 Spring 配置。

使用 Spring Boot,我们可以通过 java -jar 的方式或更传统的 war 包方式部署来启动 Java 应用程序。Spring Boot 没有什么特别之处,它只是我们可以使用的另一个库。

Spring Boot 主要特性如下:

  1. 为所有 Spring 应用程序开发提供根本上更快且可广泛使用的入门体验。

  2. 开箱即用,但随着需求快速变化,我们需要开始修改默认配置。

  3. 提供大型项目(例如嵌入式服务器、安全、性能指标、健康检查和外部化配置等)通用的一系列非功能性特性。

  4. 绝对没有代码生成,也不需要 XML 配置。

# Spring Boot 3 系统要求

Spring Boot 3 开始,Java 17 是最低要求,还需要 Spring Framework 6.0.0 或更高版本,并且为以下构建工具提供了显式构建支持:

Build Tool Version
Maven 3.5+
Gradle 7.x (7.4 或更高版本)

Spring Boot 3 支持以下嵌入式 servlet 容器:

Name Servlet Version
Tomcat 10.0 5.0
Jetty 11.0 5.1
Undertow 2.2(Jakarta EE 9 variant) 5.0

我们还可以将 Spring Boot 3 应用程序部署到任何 servlet 5.0+ 兼容的容器中。

# Spring Boot 3 应用程序开发

Spring Boot 不需要与任何特殊工具集成,我们可以使用任何 IDE 甚至文本编辑器开发。Spring Boot 应用程序没有什么特别之处,我们可以像运行任何其他 Java 程序一样运行和调试 Spring Boot 应用程序。

在开发之前,使用以下命令来检查当前的 Java 安装:

$ java -version

Spring 3.0.0 需要 Java 17 或更高版本。

  1. Maven 安装

Spring Boot 3 支持使用 Apache Maven 3.5+ 来构建。如果我们还没有安装 Maven,可以按照 maven.apache.org 上的文档进行安装。

  1. 创建 POM 文件

创建项目的 Maven 构建文件 pom.xml,并添加以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.github.xxyopen</groupId>
    <artifactId>novel</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0-SNAPSHOT</version>
    </parent>

    <!-- Additional lines to be added here... -->

    <!-- (you do not need this if you are using a .RELEASE version) -->
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots><enabled>true</enabled></snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>https://repo.spring.io/snapshot</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>
</project>

Spring Boot 依赖项使用 org.springframework.boot groupId,我们需要在 Maven POM 文件中继承 spring-boot-starter-parent 项目,Spring Boot 提供了许多 Starters(启动器),Starter 提供了我们在开发特定类型的应用程序时可能需要的依赖项,可以批量将相关的依赖 jar 添加到 classpath 类路径中。spring-boot-starter-parent 是一个特殊的 Starter,它提供了有用的 Maven 默认值(java 版本、源码编码等)、合理的插件配置以及一个从 POM 继承来的 dependency-management 部分,方便我们可以省略很多公共依赖项的 version 标签,因为目前使用的是snapshots(快照)版本,所以我们还需要在 repositories 和 pluginRepositories 元素中添加适当的 napshots repositorie 和 napshots pluginRepository。

我们可以通过运行以下命令来查看我们项目当前拥有的依赖树:

$ mvn dependency:tree

[INFO] io.github.xxyopen:novel:jar:0.0.1-SNAPSHOT
  1. 添加 Maven 依赖

因为我们正在开发 Web 应用程序,所以我们需要在 POM 文件中添加一个 spring-boot-starter-web 依赖项

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

再次运行 mvn dependency:tree 查看依赖树,我们会发现多了许多依赖项,包括 Tomcat、Spring Boot 等。

[INFO] io.github.xxyopen:novel:jar:0.0.1-SNAPSHOT
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:3.0.0-SNAPSHOT:compile
[INFO]    +- org.springframework.boot:spring-boot-starter:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  +- org.springframework.boot:spring-boot:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  +- org.springframework.boot:spring-boot-autoconfigure:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  +- org.springframework.boot:spring-boot-starter-logging:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  |  +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO]    |  |  |  +- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO]    |  |  |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO]    |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO]    |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO]    |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO]    |  +- jakarta.annotation:jakarta.annotation-api:jar:2.0.0:compile
[INFO]    |  +- org.springframework:spring-core:jar:6.0.0-SNAPSHOT:compile
[INFO]    |  |  \- org.springframework:spring-jcl:jar:6.0.0-SNAPSHOT:compile
[INFO]    |  \- org.yaml:snakeyaml:jar:1.30:compile
[INFO]    +- org.springframework.boot:spring-boot-starter-json:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.2.1:compile
[INFO]    |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.2:compile
[INFO]    |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.13.2:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.2:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.2:compile
[INFO]    |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.2:compile
[INFO]    +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.0.0-SNAPSHOT:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.0.18:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.0.18:compile
[INFO]    |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.0.18:compile
[INFO]    +- org.springframework:spring-web:jar:6.0.0-SNAPSHOT:compile
[INFO]    |  \- org.springframework:spring-beans:jar:6.0.0-SNAPSHOT:compile
[INFO]    \- org.springframework:spring-webmvc:jar:6.0.0-SNAPSHOT:compile
[INFO]       +- org.springframework:spring-aop:jar:6.0.0-SNAPSHOT:compile
[INFO]       +- org.springframework:spring-context:jar:6.0.0-SNAPSHOT:compile
[INFO]       \- org.springframework:spring-expression:jar:6.0.0-SNAPSHOT:compile

  1. 编写代码

创建一个 Java 类文件,添加以下代码:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableAutoConfiguration
public class NovelApplication {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

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

}

NovelApplication 类的第一个注解是 @RestController,它可以看作是 @Controller + @ResponseBody 的组合注解,表明我们的类是一个 Web 控制器,Spring 在处理Http 请求时会扫描它,并且将处理结果作为 json 字符串返回。

@RequestMapping 注解提供路由信息。它告诉 Spring 任何带有该路径的 HTTP 请求都应该映射到该 home 方法。

@EnableAutoConfiguration 注解开启自动配置,告诉 Spring Boot 根据我们添加的 jar 依赖来推测我们想如何配置 Spring。由于spring-boot-starter-web 添加了 Tomcat 和 Spring MVC,自动配置推测正在开发 Web 应用程序并相应地设置 Spring。

自动配置旨在与 Starter 配合使用,但这两个概念并没有直接联系。我们可以自由选择 Starter 之外的 jar 依赖项,Spring Boot 仍然会自动配置应用程序。

main 方法是一种 Java 约定的应用程序入口点标准方法,通过将调用委托给 Spring Boot 的 SpringApplication 类的 run 方法执行。 SpringApplication 引导我们的应用程序,启动 Spring,然后启动自动配置的 Tomcat Web 服务器。我们需要将 NovelApplication.class 作为参数传递给该 run 方法,告诉 SpringApplication 哪个是主要的 Spring 组件。该 args 数组也被传递以公开命令行参数。

  1. 运行

因为我们项目继承了 spring-boot-starter-parent POM,所以可以直接在项目根目录下通过命令 mvn spring-boot:run 启动应用程序。

$ mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v3.0.0-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started NovelApplication in 5.524 seconds (JVM running for 9.373)

打开 Web 浏览器访问localhost:8080,我们可以看到以下输出:

Hello World!

如果要优雅地退出应用程序,直接按 ctrl + c 即可。

  1. 打包

spring-boot-maven-plugin 可以帮我们创建一个可以在生产环境中运行的完全独立的可执行 jar 文件,可执行 jars(有时称为“fat jars”)是包含已编译类以及代码需要运行的所有 jar 依赖项的存档。

Java 不提供加载嵌套 jar 文件(包含在 jar 中的 jar 文件)的标准方法。如果我们希望分发一个独立的应用程序,可能会出现问题。

为了解决这个问题,很多开发人员使用 “uber” jars。一个 uber jar 将所有应用程序依赖项中的所有类打包到一个存档中。这种方法的问题是很难看到应用程序中有哪些库。如果在多个 jar 中使用相同的文件名(但内容不同),也可能会出现问题。

Spring Boot 采用了不同的方法,让我们可以直接嵌套 jar。

在项目 POM 文件中添加如下的插件配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

运行 mvn package 命令打包,如下:

$ mvn package

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< io.github.xxyopen:novel >-----------------------
[INFO] Building novel 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ novel ---
[INFO] Building jar: /Users/xiongxiaoyang/java/springboot3/target/novel-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:3.0.0-SNAPSHOT:repackage (repackage) @ novel ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

查看 target 目录,可以看到 novel-0.0.1-SNAPSHOT.jar,该文件的大小在 10 MB 左右。

target 目录下还有一个小得多的文件 novel-0.0.1-SNAPSHOT.jar.original,这是在被 Spring Boot 重新打包之前 Maven 创建的原始 jar 文件。

要运行应用程序,请使用以下 java -jar 命令:

$ java -jar target/novel-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v3.0.0-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started NovelApplication in 3.187 seconds (JVM running for 9.373)

要退出应用程序,请按 ctrl + c。

# Spring Boot 升级

Spring Boot 项目 的 wiki (opens new window)上提供了关于如何从早期版本的 Spring Boot 升级的说明,我们可以通过查看发行说明 (opens new window)来获取每个版本的新的主要功能列表。

升级到新版本时,某些属性可能已经重命名或移除,Spring Boot 提供了一种在启动时分析应用程序环境和打印诊断信息的功能,还可以在运行时临时迁移属性。要启用该功能,需要将在项目 POM 文件中添加以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
    <scope>runtime</scope>
</dependency>

完成迁移后,请从项目的依赖项中删除此模块。

上次更新: a year ago