1. 概述

在本教程中,我们将快速浏览 REST 架构中经常使用的两个重要的 HTTP 方法 - PUT 和 POST。众所周知, 开发人员在设计 RESTful Web 服务时有时会难以在这两种方法之间进行选择 。因此,我们将通过在 Spring Boot 中简单实现 RESTful 应用程序来解决这个问题。

2. PUT 与 POST 困境

在典型的 REST 架构中,客户端以 HTTP 方法的形式向服务器发送请求,以创建、检索、修改或销毁资源。虽然 PUT 和 POST 都可用于创建资源,但它们之间的预期应用程序存在显着差异。

根据RFC 2616标准,应使用 POST 方法来请求服务器接受所包含的实体作为由 Request-URI 标识的现有资源的下属。这意味着 POST 方法调用将在资源集合下创建子资源

另一方面,PUT 方法应该用于请求服务器将所包含的实体存储在所提供的 Request-URI 下。如果请求 URI 指向服务器上的现有资源,则提供的实体将被视为现有资源的修改版本。因此, PUT 方法调用将创建一个新资源或更新现有资源

这些方法之间的另一个重要区别是 PUT 是幂等方法,而 POST 不是 。例如,多次调用 PUT 方法将创建或更新相同的资源。相反,多个POST请求会导致多次创建同一个资源。

3. 示例应用

为了演示 PUT 和 POST 之间的区别,我们将使用Spring Boot创建一个简单的 RESTful Web 应用程序。该应用程序将存储人员的姓名和地址。

3.1. Maven 依赖项

首先,我们需要在 pom.xml 文件中包含 Spring Web、Spring Data JPA 和内存 H2 数据库的依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

3.2.领域实体和存储库接口

让我们首先创建域对象。对于地址簿,我们定义一个名为 Address实体 类,我们将用它来存储个人的地址信息。为了简单起见,我们将为我们的 Address 实体使用三个字段 – namecitypostalCode

@Entity
public class Address {

    private @Id @GeneratedValue Long id;
    private String name;
    private String city;
    private String postalCode;

    // constructors, getters, and setters
}

下一步是从数据库访问数据。为简单起见,我们将利用Spring Data JPA 的 JpaRepository。 这将使我们能够对数据执行 CRUD 功能,而无需编写任何额外的代码:

public interface AddressRepository extends JpaRepository<Address, Long> {
}

3.3.休息控制器

最后,我们需要为应用程序定义 API 端点。我们将创建一个 RestController ,它将使用来自客户端的 HTTP 请求并发回适当的响应。

在这里,我们将 定义一个 @PostMapping 用于创建新地址 并将其存储在数据库中 ,以及一个 @PutMapping 用于根据请求 URI 更新地址簿的内容 。如果没有找到 URI,它将创建一个新地址并将其存储在数据库中:

@RestController
public class AddressController {

    private final AddressRepository repository;

    AddressController(AddressRepository repository) {
        this.repository = repository;
    }

    @PostMapping("/addresses")
    Address createNewAddress(@RequestBody Address newAddress) {
        return repository.save(newAddress);
    }

    @PutMapping("/addresses/{id}")
    Address replaceEmployee(@RequestBody Address newAddress, @PathVariable Long id) {

        return repository.findById(id)
            .map(address -> {
                address.setCity(newAddress.getCity());
                address.setPin(newAddress.getPostalCode());
                return repository.save(address);
            })
            .orElseGet(() -> {
                return repository.save(newAddress);
            });
    }
    //additional methods omitted
}

3.4.卷曲请求

现在我们可以使用 cURL 向我们的服务器发送示例 HTTP 请求来测试我们开发的应用程序。

为了创建新地址,我们将以 JSON 格式封装数据并通过 POST 请求发送:

curl -X POST --header 'Content-Type: application/json' \
    -d '{ "name": "John Doe", "city": "Berlin", "postalCode": "10585" }' \ 
    http://localhost:8080/addresses

现在,让我们更新我们创建的地址的内容。我们将使用 URL 中该地址的 ID 发送 PUT 请求。在此示例中,我们将更新刚刚创建的地址的 城市邮政编码 部分 - 我们假设它是使用 id =1 保存的:

curl -X PUT --header 'Content-Type: application/json' \
  -d '{ "name": "John Doe", "city": "Frankfurt", "postalCode": "60306" }' \ 
  http://localhost:8080/addresses/1

4。结论

在本教程中,我们了解了 HTTP 方法 PUT 和 POST 之间的概念差异。此外,我们还了解了如何使用 Spring Boot 框架来实现这些方法来开发 RESTful 应用程序。

总之,我们应该使用 POST 方法来创建新资源,并使用 PUT 方法来更新现有资源。与往常一样,本教程的代码可在 GitHub 上获取。