11. 开发第一个 Spring Boot 应用

本节描述如何开发一个简单的 “Hello World!” web 应用,通过应用来强调 Spring Boot 的一些关键特性。由于大多数 IDE 都支持 Maven,因此我们用 Maven 来构建这个项目。

[Tip] Tip

spring.io 网站上有许多使用 Spring Boot 的新手入门指南。如果你想解决某个具体问题,先去网站上看一下。

你可以到 start.spring.io 上选择依赖搜索器中的 web 启动器来简化你的步骤。这会自动生成一个新的项目结构,以便你可以立即开始 编写代码。更多详细信息请查看 Spring 初始化文档。

在开始之前,打开终端来检查一下你已经安装了有效的 Java 版本和 Maven 版本:

$ java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
$ mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T14:33:14-04:00)
Maven home: /usr/local/Cellar/maven/3.3.9/libexec
Java version: 1.8.0_102, vendor: Oracle Corporation
[Note] Note

此示例需要创建它自己的文件夹。后续的介绍假设你已经创建了合适的文件夹,并且该文件夹是你的当前目录。

11.1 创建 POM

我们需要先创建一个 Maven pom.xml 文件。 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>myproject</artifactId>
	<version>0.0.1-SNAPSHOT</version>

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

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

	<!-- (you don't 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>

前面的清单应该给你一个可以工作的构建,你可以通过运行 mvn package 来测试一下(你现在可以忽略 “jar will be empty - no content was marked for inclusion!” 警告)。

[Note] Note

在这个地方你可以将工程导入到 IDE 中(大多数现代 Java IDE 都有对 Maven 的内置支持)。为了简便,在这个示例中我们将继续使用普通的文本编辑器。

11.2 添加类路径依赖项

Spring Boot 提供了大量启动器,以便添加 jar 到类路径中。示例应用已经在 POM 的 parent 部分中使用了 spring-boot-starter-parent。 spring-boot-starter-parent 是一个特别的启动器,它能提供有用的 Maven 默认设置。它还提供了 依赖管理 部分,因此你可以对保佑的依赖项忽略其 version 标签。

其它的启动器简单的提供了开发特定类型应用时可能需要的依赖项。由于我们正在开发一个 web 应用,我们将添加 spring-boot-starter-web 依赖。但在那之前,使用下面的命令来让我们先看一下目前有什么。

$ mvn dependency:tree

[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT

mvn dependency:tree 命令将你的项目依赖打印成一棵树的形式。你可以看到 spring-boot-starter-parent 本身不提供依赖。为了添加必须的依赖,编辑你的 pom.xml 文件,并在 parent 部分添加 spring-boot-starter-web 依赖:

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

如果你再次运行 mvn dependency:tree,你将会看到许多额外的依赖关系,包括 Tomcat web 服务器和 Spring Boot 本身。

11.3 编写代码

为了完成我们的应用,我们需要创建一个 Java 文件。Maven 默认从 src/main/java 编译源码,因此你需要创建对应的文件结构,然后添加名为 src/main/java/Example.java 的文件并包含以下代码:

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

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

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

}

尽管这里没有太多的代码,但是发生了许多事情。我们将在后面一些小节一步步浏览这些重要的部分。

11.3.1 @RestController 和 @RequestMapping 注解

在 Example 类中第一个注解是 @RestController。这是一个模块化的注解。它为阅读代码的人提供了提示,对于 Spring 而言,这个类起着特定的作用。在这个例子中,我们的类是一个 web @Controller,所以 Spring 在处理传入的 web 请求时会考虑它。

@RequestMapping 注解提供了路由信息。它告诉 Spring 任何带有路径 “/” 的HTTP请求应该映射到 home 方法上。@RestController 注解告诉 Spring 将结果渲染成字符串形式并直接返回给调用者。

[Tip] Tip

@RestController 和 @RequestMapping 注解是 Spring MVC 注解(它们不是 Spring Boot 特有的)。更多详细信息请参阅 Spring 参考指南中的 MVC 部分。

11.3.2 @EnableAutoConfiguration 注解

第二个类级别的注解是 @EnableAutoConfiguration。这个注解告诉 Spring Boot 基于你添加的 jar 依赖去猜你想怎样配置 Spring。由于 spring-boot-starter-web 添加了 Tomcat 和 Spring MVC,自动配置会假设你正在开发一个 web 应用并相应的设置 Spring。

启动器和自动配置

自动配置被设计成跟启动器能一起很好的工作,但这两个概念没有直接联系。你可以自由的挑选启动器之外的 jar 依赖,Spring Boot 仍会最大程度地自动配置你的应用。

11.3.3 主方法

这个程序的最后部分是 main 方法。这是一个符合 Java 应用程序入口规范的标准方法。主方法中委托 Spring Boot 的 SpringApplication 类调用 run 方法。SpringApplication 将引导我们的应用启动 Spring,Spring 将启动自动配置的 Tomcat web 服务器。我们需要将 Example.class 作为参数传给 run 方法,告诉 SpringApplication 它是主要的 Spring 组件。args 数组会将所有命令行参数传给 run 方法。

11.4 运行示例

此时我们的应用应该工作了。既然我们已经使用了 spring-boot-starter-parent POM,那我们有一个有用的 run 目标,我们使用它来启动应用。在工程的根目录中输入 mvn spring-boot:run 来启动应用。你将看到类似以下的输出:

$ mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v2.1.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)

如果你在浏览器中打开 localhost:8080,你应该会看到下面的内容:

Hello World!

适当的退出应用程序请使用 ctrl-c 组合键。

11.5 创建可执行的 Jar

通过创建一个在生产中能运行的完整的自包含可执行的 jar 文件来结束我们的例子。可执行 jar(有时称为 “fat jars”)是包含编译的类和代码运行所需要的所有 jar 依赖的归档文件。

可执行 jar 和 Java

Java 没有提供任何标准方法来加载嵌套的 jar 文件(例如,jar 文件本身包含在一个 jar 中)。如果你想分发一个自包含的应用,这可能是个问题。

为了解决这个问题,许多开发者使用 “uber” jar。uber jar 简单的将所有 jar 的所有类打包到一个单独的存档文件中。这个方法的问题是很难看到你的应用正在使用的是哪个库。如果多个 jar 使用了相同的文件名(不同的内容)也是个问题。

Spring Boot 采用了一种 不同的方法 来处理这个问题,允许你真正的直接内嵌 jar。

为了创建可执行 jar,我们需要添加 spring-boot-maven-plugin 到 pom.xml 中。在 dependencies 部分的下面插入以下内容:

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

spring-boot-starter-parent POM 包含绑定 repackage 目标的 <executions> 配置。如果你没有使用父 POM,那你需要自己声明这个配置。更多详细信息请参阅 插件文档。

保存你的 pom.xml 并从命令行中运行 mvn package:

$ mvn package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.0.BUILD-SNAPSHOT:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

如果你看一下 target 目录,应该可以看到 myproject-0.0.1-SNAPSHOT.jar。这个文件大小应该在10 Mb左右。如果想查看里面的内容,你可以使用 jar tvf,如下:

$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

你在 target 目录中应该也能看到一个更小的名为 myproject-0.0.1-SNAPSHOT.jar.original 的文件。这是 Spring Boot 重新打包之前 Maven 创建的最初的 jar 文件。

要运行这个应用,请使用 java -jar 命令,如下:

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

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v2.1.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)

像前面一样,适当的退出应用程序请使用 ctrl-c 组合键。

12. 后续内容

希望这部分内容给你提供了一些 Spring Boot 的基本知识,也让你以自己的方式写了自己的应用程序。如果你是一个面向任务的开发人员,你可能想跳到 spring.io ,找出一些 新手入门 指南来解决特定的 “用 Spring 怎样做” 的问题;我们也提供了 Spring Boot 的 “How-to” 参考文档。

Spring Boot 仓库 也有你可以运行的 一些示例。示例是独立于其它代码的(运行或使用示例时你不需要构建其它的内容)。

此外,按逻辑接下来是阅读 章节 III, “使用 Spring Boot”。如果你真的不耐烦,也可以跳过这部分,直接阅读 Spring Boot 特性 。