6.1.2 向服务器发送数据

到目前为止,API 能够返回 12 个最近创建的 tacos。但是这些 tacos 是如何产生的呢?

还没有从第 2 章中删除任何代码,所以仍然拥有原始的 DesignTacoController,它显示一个 taco 设计表单并处理表单提交。这是获得一些测试数据以测试创建的 API 的好方法。但是,如果要将 Taco Cloud 转换为单页面应用程序,则需要创建 Angular 组件和相应的端点来替代第 2 章中的 Taco 设计表单。

已经通过定义一个名为 DesignComponent 的新 Angular 组件(在一个名为 design.component.ts 的文件中)处理了 taco 设计表单的客户端代码。与处理表单提交相关,DesignComponent 有一个 onSubmit() 方法,如下所示:

onSubmit() {
    this.httpClient.post(
        'http://localhost:8080/design',
        this.model, {
            headers: new HttpHeaders().set('Content-type', 'application/json'),
        }).subscribe(taco => this.cart.addToCart(taco));
    
    this.router.navigate(['/cart']);
}

在 onSubmit() 方法中,调用 HttpClient 的 post() 方法,而不是 get()。这意味着不是从 API 获取数据,而是将数据发送到 API。具体地说,使用 HTTP POST 请求将模型变量中包含的 taco 设计发送到 API 的 /design 端点。

这意味着需要在 DesignTacoController 中编写一个方法来处理该请求并保存设计。通过将以下 postTaco() 方法添加到 DesignTacoController 中,可以让控制器做到这一点:

@PostMapping(consumes="application/json")
@ResponseStatus(HttpStatus.CREATED)
public Taco postTaco(@RequestBody Taco taco) {
    return tacoRepo.save(taco);
}

因为 postTaco() 将处理 HTTP POST 请求,所以它使用 @PostMapping 而不是 @GetMapping 进行注解。这里没有指定 path 属性,所以 postTaco() 方法将处理 DesignTacoController 上的类级 @RequestMapping 中指定的 /design 请求。

但是,确实设置了 consumer 属性。consumer 属性用于处理输入,那么 produces 就用于处理输出。这里使用 consumer 属性,表示该方法只处理 Content-type 与 application/json 匹配的请求。

方法的 Taco 参数添加了 @RequestBody 注解,以指示请求体应该转换为 Taco 对象并绑定到参数。这个注解很重要 —— 如果没有它,Spring MVC 会假设将请求参数(查询参数或表单参数)绑定到 Taco 对象。但是 @RequestBody 注解确保将请求体中的 JSON 绑定到 Taco 对象。

postTaco() 接收到 Taco 对象后,将其传递给 TacoRepository 上的 save() 方法。

这里在 postTaco() 方法上使用了 @ResponseStatus(HttpStatus.CREATED) 注解。在正常情况下(当没有抛出异常时),所有响应的 HTTP 状态码为 200(OK),表示请求成功。尽管 HTTP 200 响应总是好的,但它并不总是具有足够的描述性。对于 POST 请求,HTTP 状态 201(CREATED)更具描述性,它告诉客户机,请求不仅成功了,而且还创建了一个资源。在适当的地方使用 @ResponseStatus 将最具描述性和最准确的 HTTP 状态代码传递给客户端总是一个好想法。

虽然已经使用 @PostMapping 创建了一个新的 Taco 资源,但是 POST 请求也可以用于更新资源。即便如此,POST 请求通常用于创建资源,PUT 和 PATCH 请求用于更新资源。让我们看看如何使用 @PutMapping 和 @PatchMapping 更新数据。

最后更新于