Spring Boot 与 Docker
观察 GraphQL 的实际运行

本指南将引导您使用 Spring 创建一个“Hello, World” RESTful Web 服务的过程。

你将构建什么

您将构建一个服务,该服务将在 http://localhost:8080/greeting 接受 HTTP GET 请求。它将返回一个问候语的 JSON 表示,如下面的代码所示:

{"id":1,"content":"Hello, World!"}

您可以通过查询字符串中的可选 name 参数来定制问候语,如下列表所示:

http://localhost:8080/greeting?name=User

name 参数值会覆盖默认值 World,并在响应中体现,如下列示例所示:

{"id":1,"content":"Hello, User!"}

所需条件

如何完成本指南

与大多数 Spring 入门指南一样,您可以从头开始并完成每个步骤,或者可以跳过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到可运行的代码。

从头开始,请继续阅读从 Spring Initializr 开始

跳过基础知识,请执行以下操作:

完成后,您可以将结果与 gs-rest-service/complete 中的代码进行对比。

从 Spring Initializr 开始

您可以使用这个预初始化项目,点击生成以下载ZIP文件。该项目已配置为适合本教程中的示例。

要手动初始化项目:

  1. 访问 https://start.spring.io。该服务会为您拉取应用程序所需的所有依赖项,并完成大部分设置工作。

  2. 选择 Gradle 或 Maven 以及您想要使用的语言。本指南假设您选择了 Java。

  3. 点击 Dependencies 并选择 Spring Web

  4. 点击 Generate

  5. 下载生成的 ZIP 文件,这是一个根据您的选择配置好的 Web 应用程序的归档文件。

如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成这个过程。

您还可以从 Github 上 fork 该项目,并在您的 IDE 或其他编辑器中打开它。

创建一个资源表示类

现在,您已经设置好了项目和构建系统,可以开始创建您的 Web 服务了。

首先,从思考服务交互开始。

该服务将处理对 /greetingGET 请求,查询字符串中可以包含一个可选的 name 参数。GET 请求应返回一个 200 OK 响应,并在响应体中以 JSON 格式返回问候语。它应该类似于以下输出:

{
    "id": 1,
    "content": "Hello, World!"
}

id 字段是问候语的唯一标识符,content 是问候语的文本内容。

为了建模问候语的表示形式,需要创建一个资源表示类。为此,可以为 idcontent 数据提供一个 Java record 类,如下面的代码清单(来自 src/main/java/com/example/restservice/Greeting.java)所示:

package com.example.restservice;

public record Greeting(long id, String content) { }

该应用程序使用 Jackson JSON 库自动将 Greeting 类型的实例序列化为 JSON。Jackson 默认包含在 web starter 中。

创建资源控制器

在 Spring 构建 RESTful web 服务的方法中,HTTP 请求由控制器处理。这些组件通过 @RestController 注解来标识,下面列出(来自 src/main/java/com/example/restservice/GreetingController.java)的 GreetingController 通过返回 Greeting 类的新实例来处理 /greetingGET 请求:

package com.example.restservice;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @GetMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}

该控制器简洁明了,但其内部却进行了大量操作。我们逐步分解。

@GetMapping 注解确保了对 /greeting 的 HTTP GET 请求被映射到 greeting() 方法。

其他HTTP动词也有相应的注解(例如,@PostMapping用于POST)。还有一个@RequestMapping注解,其他注解都源自它,并且可以作为同义词使用(例如,@RequestMapping(method=GET))。

@RequestParam 将查询字符串参数 name 的值绑定到 greeting() 方法的 name 参数上。如果请求中缺少 name 参数,则使用默认值 World

方法体的实现基于 counter 的下一个值创建并返回一个包含 idcontent 属性的新 Greeting 对象,并使用问候语 template 格式化给定的 name

传统的 MVC 控制器与前面展示的 RESTful Web 服务控制器之间的一个关键区别在于 HTTP 响应体的创建方式。不同于依赖视图技术在服务器端将问候数据渲染为 HTML,此 RESTful Web 服务控制器填充并返回一个 Greeting 对象。对象数据将直接以 JSON 格式写入 HTTP 响应。

此代码使用了 Spring 的 @RestController 注解,它将类标记为控制器,其中每个方法都返回一个领域对象而非视图。它是 @Controller@ResponseBody 的组合简写。

Greeting 对象必须转换为 JSON。得益于 Spring 的 HTTP 消息转换器支持,您无需手动进行此转换。由于 Jackson 2 在类路径中,Spring 的 MappingJackson2HttpMessageConverter 会自动被选择用于将 Greeting 实例转换为 JSON。

运行服务

Spring Initializr 为您创建了一个应用程序类。在这种情况下,您无需进一步修改该类。以下代码片段(来自 src/main/java/com/example/restservice/RestServiceApplication.java)展示了该应用程序类:

package com.example.restservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RestServiceApplication {

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

}

@SpringBootApplication 是一个便捷的注解,它添加了以下所有内容:

  • @Configuration: 将该类标记为应用上下文的 bean 定义源。

  • @EnableAutoConfiguration: 告诉 Spring Boot 根据类路径设置、其他 bean 和各种属性设置开始添加 bean。例如,如果类路径上有 spring-webmvc,该注解会将应用程序标记为 Web 应用程序,并激活关键行为,例如设置 DispatcherServlet

  • @ComponentScan: 告诉 Spring 在 com/example 包中查找其他组件、配置和服务,以便它能够找到控制器。

main() 方法使用 Spring Boot 的 SpringApplication.run() 方法来启动应用程序。您是否注意到没有一行 XML 代码?也没有 web.xml 文件。这个 Web 应用程序是 100% 纯 Java 的,您无需处理任何配置管道或基础设施。

构建可执行的 JAR 文件

您可以使用 Gradle 或 Maven 从命令行运行应用程序。您还可以构建一个包含所有必要依赖项、类和资源的可执行 JAR 文件并运行它。构建可执行 JAR 文件使得在整个开发周期中、跨不同环境等场景下,能够轻松地发布、版本化和部署服务。

如果您使用 Gradle,可以通过 ./gradlew bootRun 来运行应用程序。或者,您可以使用 ./gradlew build 构建 JAR 文件,然后按如下方式运行 JAR 文件:

java -jar build/libs/gs-rest-service-0.1.0.jar

如果你使用 Maven,可以通过 ./mvnw spring-boot:run 来运行应用程序。或者,你也可以使用 ./mvnw clean package 构建 JAR 文件,然后运行该 JAR 文件,如下所示:

java -jar target/gs-rest-service-0.1.0.jar

这里描述的步骤创建了一个可运行的 JAR 文件。您也可以构建一个经典的 WAR 文件

日志输出已显示。服务应在几秒钟内启动并运行。

测试服务

现在服务已经启动,请访问 http://localhost:8080/greeting,您应该会看到:

{"id":1,"content":"Hello, World!"}

通过访问 http://localhost:8080/greeting?name=User 提供一个 name 查询字符串参数。请注意,content 属性的值从 Hello, World! 变为 Hello, User!,如下所示:

{"id":2,"content":"Hello, User!"}

这一变化证明了 GreetingController 中的 @RequestParam 配置按预期工作。name 参数已被赋予默认值 World,但可以通过查询字符串显式覆盖。

同时注意 id 属性如何从 1 变为 2。这证明您在多个请求中使用的是同一个 GreetingController 实例,并且它的 counter 字段在每次调用时按预期递增。

总结

恭喜!您刚刚使用 Spring 开发了一个 RESTful Web 服务。

另请参阅

以下指南也可能有所帮助:

本页目录