【官方教程翻译】SpringBoot 开发 RESTful Web 服务

475 阅读5分钟

原文:spring.io/guides/gs/r…

在项目初始化的部分有删减

本文将带你使用 Spring 开发一个 “Hello, World” RESTful Web 服务。

最终目标

本文最终的目标,是带你开发一个能够在 http://localhost:8080/greeting 接收 HTTP GET 请求的服务,该接口将以 JSON 格式返回一个问候信息,如:

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

该接口还能够通过 url 中的查询字符串( query string )接收一个可选的 name 参数,请求如:

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

这里的 name 参数值将覆盖默认的 World ,此时的接口响应如下:

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

如何完成该教程

和其他的 Spring 教程一样,你可以从零开始建立项目,也可以直接使用已有的代码模板。

  • 若要从零开始,请阅读从零开始建立项目

  • 若要跳过创建项目的部分,请进行如下步骤:

    • 下载本教程的源代码:github.com/spring-guid…
    • 进入 gs-rest-service/initial 目录
    • 直接阅读本文下面的【创建资源表示类】部分
  • 当完成代码后,可以将自己的代码和 gs-rest-service/complete 中的代码进行比较,检查自己的成果。

创建资源表示类(Resource Representation Class)

首先,我们来思考一下服务交互的过程:

服务首先应该接收 /greeting url 上面的 GET 请求,并处理可选的 name 参数。GET 请求应该返回一个 200 OK 的响应并在响应体( body )部分加上最终的 JSON ,样子如下:

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

id 字段是每个问候响应的唯一标识符,content 是问候文本。

我们需要建立一个资源表示类( resource representation class )作为问候响应的数据模型。这个类是一个包含数据(表示 idcontent 的变量其访问他们的方法)、构造器的普通 Java 类,代码如下:

package com.example.restservice;
​
public class Greeting {
    
    private final long id;
    private final String content;
    
    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }
    
    public long getId() {
        return id;
    }
    
    public String getContent() {
        return content;
    }
}

本应用程序使用 Jackson JSON 库来自动将 Greeting 对象转为 JSON。Jackson 默认包含在 Web 初始模板中

创建资源控制器(Resource Controller)

在 Spring 的 RESTful Web 服务中,HTTP 请求都是由控制器来管理的。这些控制器部件都被 @RestController 注解修饰,下面代码中的 GreetingController 会在 /greeting 接收 GET 请求,并返回一个新创建的 Greeting 类实例:

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 的请求映射到 greeting() 方法。

此外还有几个处理其他 HTTP 方法的注解(例如给 POST 用的 @PostMapping ),它们都派生自 @RequestMapping 注解。也可以通过 @RequestMapping(method=GET) 的方法来直接使用 RequestMapping

@RequestParam 能够将请求中的查询字符串参数 name 转为 greeting() 方法的 name 参数。如果请求中不含 name 参数,则将使用defaultValue 的值 World 作为默认参数。

方法体中创建并返回一个 Greeting 实例,并设置其成员变量 counter(通过 incrementAndGet() 方法) 和 content (通过对 templatename 参数来格式化)的值。

传统 MVC 控制器和 RESTful web 服务控制器的关键差异在于他们创建 HTTP 响应体的方式:传统 MVC 会使用服务端渲染(SSR)的方式,将问候数据直接转为 HTML 。而这里的 RESTful web 服务控制器会生成并返回一个 Greeting 对象。该对象的数据会被直接以 JSON 的方式返回给请求者。

这段代码最外面的 @RestController 注解将该类标记为一个控制器,其中的所有方法都会返回一个域对象(domain object),而不会返回一个视图( view )。@RestController 是包含了 @Controller@ResponseBody 的简写。

Greeting 对象需要被转为 JSON 才能返回给请求者,该工作由 Spring HTTP 消息转换支持来实现,因此不需要我们对其进行手动转换。因为 classpath 中包含 Jackson 2 ,因此 Spring 会自动选择 MappingJackson2HttpMessageConverter 来将 Greeting 实例转为 JSON 文本。

@SpringBootApplication 是下面三个注解的简写:

  • @Configuration : 将类标记为应用上下文( application context )bean 的定义;
  • @EnableAutoConfiguration :让 Spring Boot 根据 classpath 设置、其他的属性设置( various property settings )等来添加 bean 。例如:如果 classpath 中有一个 spring-webmvc ,那么该标记就会将应用程序标记为一个 web 应用,并启用相关的行为——比如启动一个 DispatcherServlet
  • @ComponentScan :让 Spring 寻找在 com/example 包下面的其他组件、配置、服务等,并找到所有的控制器。

整个程序的 main() 方法使用 Spring Boot 的 SpringApplication.run() 方法来启动应用程序。在上面的全过程中都不需要我们处理 XML ,也没有 web.xml 文件。该应用是 100% 的纯 Java 程序,不需要配置任何的管道和基础设施( plumbing or infrastructure )。

创建可执行 JAR

写好的程序可以通过命令行或使用 Gradle / Maven 来运行。此外我们也可以将应用构建为一个可执行的 JAR 文件,该文件会包含所有必须的依赖、类和运行所需的资源。构建可执行 JAR 能够方便发布、管理版本以及在不同的环境中部署等。

如果你用 Gradle 管理项目,那么可以使用 ./gradlew bootRun 来运行应用程序。如果想将程序构建为 JAR ,则可以使用 ./gradlew build 构建然后运行,运行方法如下:

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

如果你用 Maven 管理项目,可以通过 ./mvnw spring-boot:run 运行程序。如果要构建为 JAR ,使用命令 ./mvnw clean package 并通过和上面一样的方式运行 jar 文件。

测试服务

程序运行起来之后,使用浏览器访问 http://localhost:8080/greeting ,可以看到

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

也可以在 url 中加上查询参数:http://localhost:8080/greeting?name=User ,显示如下:

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

这说明 GreetingController 中的 @RequestParam 如预期正常工作,原来的默认参数 World 已经变为了 User。此外,id 值也从 1 变为了 2 。这说明多个请求都会被同一个 GreetingController 实例处理,counter 的值也如预期增长。