Перейти к основному содержимому

HTTP метод PUT или POST в REST API

· 4 мин. чтения

1. Обзор

В этом руководстве мы кратко рассмотрим два важных метода HTTP — PUT и POST — которые часто используются в архитектуре REST. Не секрет, что разработчики иногда пытаются выбрать между этими двумя методами при разработке веб-службы RESTful. Поэтому мы решим эту проблему с помощью простой реализации приложения RESTful в Spring Boot.

2. Дилемма PUT и POST

В типичной архитектуре REST клиент отправляет серверу запросы в виде методов HTTP для создания, извлечения, изменения или уничтожения ресурсов. Хотя и PUT, и POST могут использоваться для создания ресурсов, между ними есть существенные различия с точки зрения их предполагаемого применения.

В соответствии со стандартом RFC 2616 метод POST следует использовать для запроса на сервер принять вложенный объект в качестве подчиненного существующего ресурса, идентифицированного Request-URI. Это означает , что вызов метода POST создаст дочерний ресурс в наборе ресурсов.

С другой стороны, следует использовать метод PUT, чтобы запросить у сервера сохранение вложенного объекта под предоставленным Request-URI. Если Request-URI указывает на существующий ресурс на сервере, предоставленный объект будет считаться измененной версией существующего ресурса. Следовательно, вызов метода PUT либо создаст новый ресурс, либо обновит существующий .

Другое важное различие между методами заключается в том, что PUT является идемпотентным методом, а POST — нет . Например, многократный вызов метода PUT либо создаст, либо обновит один и тот же ресурс. Напротив, несколько запросов POST приведут к созданию одного и того же ресурса несколько раз.

3. Образец заявления

Чтобы продемонстрировать разницу между PUT и POST, мы собираемся создать простое веб-приложение RESTful с использованием Spring Boot . Приложение будет хранить имена и адреса людей.

3.1. Зависимости Maven

Для начала нам нужно включить зависимости для Spring Web, Spring Data JPA и базы данных H2 в памяти в наш файл pom.xml :

<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. Интерфейс объекта домена и репозитория

Давайте начнем с создания объекта домена. Для адресной книги давайте определим класс Entity с именем Address , который мы будем использовать для хранения информации об адресах отдельных лиц. Для простоты мы будем использовать три поля — name , city и postalCode — для нашей сущности Address :

@Entity
public class Address {

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

// constructors, getters, and setters
}

Следующим шагом является доступ к данным из базы данных. Для простоты мы будем использовать JpaRepository Spring Data JPA . Это позволит нам выполнять функции CRUD для данных без написания дополнительного кода:

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

3.3. REST-контроллер

Наконец, нам нужно определить конечные точки 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-запросы

Теперь мы можем протестировать наше разработанное приложение, используя cURL для отправки примеров HTTP-запросов на наш сервер.

Для создания нового адреса мы заключим данные в формате JSON и отправим их через POST-запрос:

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

Теперь давайте обновим содержимое созданного нами адреса. Мы отправим запрос PUT, используя идентификатор этого адреса в URL-адресе. В этом примере мы обновим город и раздел postalCode адреса, который мы только что создали — предположим, что он был сохранен с 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 .