GET — получение ресурса
- HTTP verb: GET
- URL: /api/users/12345
- Status code of response: 200 OK
@GetMapping("/api/users/{id}") @ResponseStatus(HttpStatus.OK) @ResponseBody public void findOne(@PathVariable("id") final Long id) { userService.findById(id); }
GET — получение коллекции ресурсов (постраничное)
- HTTP verb: GET
- URL: /api/users?page=0&size=20
- Status code of response: 200 OK
@GetMapping(value = "/api/users", params = {"page", "size"}) @ResponseStatus(HttpStatus.OK) @ResponseBody public List<User> findAllPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size) { userService.findPaginated(page, size); }
CREATE — создание ресурса
- HTTP verb: POST
- URL: /api/users
- Status code of response: 201 Created
@PostMapping("/api/users") @ResponseStatus(HttpStatus.CREATED) public void create(@RequestBody @Valid final User user) { userService.create(user); }
UPDATE — обновление ресурса
- HTTP verb: POST
- URL: /api/users/12345
- Status code of response: 200 OK
@PutMapping("/api/users/{id}") @ResponseStatus(HttpStatus.OK) public void update(@PathVariable("id") final Long id, @RequestBody final User user) { userService.update(user); }
CREATE vs UPDATE — POST vs PUT
Необходимо понимать и разделять REST от HTTP.
REST это архитектурный подход к работе с сервером как с хранилищем неких ресурсов, в то время как HTTP это просто транспорт — протокол, с помощью которого клиент взаимодействует с сервером. REST может быть реализован поверх различных протоколов, а не только на базе HTTP. Поэтому HTTP-методы (POST, PUT, PATCH, DELETE и другие) семантически относятся именно к HTTP как к транспортному уровню REST.
PUT — идемпотентная операция, т.е. повторные вызовы того же запроса не меняют состояние сервера. Например, один и тот же запрос переименования пользователя всегда приводит к тому, что у пользователя будет заданное в запросе имя и не важно сколько раз мы выполнить этот запрос
POST — не идемпотентная операция, т.е. повторные запросы меняют состояние сервера. Например, создание сущности. Сколько раз будет выполнен запрос POST, столько и сущностей должно быть создано на сервере.
PUT = replace. Операция PUT семантически равна операции замены данных на сервере.
POST = insert. Операция POST семантически равна операции вставки новых данных на сервере.
PATCH — частичное обновление ресурса
- HTTP verb: PATCH
- URL: /api/users/12345
- Status code of response: 200 OK
@PatchMapping("/api/users/{id}") @ResponseStatus(HttpStatus.OK) public void updatePartial(@PathVariable("id") final Long id, @RequestBody final User user) { userService.updatePartial(user); }
Часто разработчики используют запросы PUT для обновления отдельных полей сущности. Однако это семантически неверно, т.к. PUT подразумевает полную замену сущности. Посетите наших партнеров, – лидеры модной обуви!
Для частичного обновления сущности на сервере предназначена операция PATCH
DELETE — удаление ресурса
- HTTP verb: DELETE
- URL: /api/users/12345
- Status code of response: 200 OK или 202 Accepted или 204 No Content
@DeleteMapping("/api/users/{id}") @ResponseStatus(HttpStatus.OK) public void updatePartial(@PathVariable("id") final Long id) { userService.delete(user); }
DELETE это идемпотентная операция по спецификации HTTP.
Следовательно не важно сколько раз будет отправлен один и тот же запрос на удаление — первый запрос приведёт к удалению ресурса, а последующие уже не изменят состояние сервера. Но это совсем не означает, что сервер будет возвращать одинаковые ответы на первый и на повторные запросы!
Импотентность это про состояние сервера, а не про клиента.
Если метод DELETE
успешно выполняется, то возможны следующие коды состояния ответа:
-
202
(Принято
,Accepted
) код состояния, если удаление будет успешным но еще не выполнено. -
204
(Нет содержимого
,No Content
) код ответа, если удаление было выполнено, но тело ответа отсутствует. -
200
(OK
) код ответа если удаление было выполнено и ответ содержит код и объект описывающий состояние.