Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Ответы и коды статуса

Каждый ответ HTTP начинается с кода статуса — трёхзначного числа, по которому клиент понимает, чем закончился запрос. По умолчанию Spring отвечает 200 OK. Но для созданной статьи правильнее 201 Created, а для удалённой — 204 No Content. Код задают через класс ResponseEntity или аннотацию @ResponseStatus.

Основные коды

КодНазваниеКогда
200OKДанные получены или изменены
201CreatedСоздан новый объект
204No ContentУспех, но тела ответа нет — например, после удаления
400Bad RequestКлиент прислал неверные данные
401UnauthorizedНужен вход
403ForbiddenВход есть, но прав не хватает
404Not FoundОбъекта нет
500Internal Server ErrorОшибка в коде сервера

Создание: 201 и адрес новой статьи

// src/main/java/com/example/blog/PostController.java
@PostMapping
public ResponseEntity<Post> create(@RequestBody NewPostRequest request) {
    Post post = postService.create(request);
    return ResponseEntity.created(URI.create("/api/posts/" + post.id())).body(post);
}

ResponseEntity — это весь ответ целиком: код, заголовки и тело. created(...) ставит код 201 и заголовок Location с адресом новой статьи, body(...) кладёт саму статью.

curl -i -X POST http://localhost:8080/api/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"Привет, Spring","body":"Первая статья","author":"anna"}'
HTTP/1.1 201
Location: /api/posts/1
Content-Type: application/json
 
{"id":1,"title":"Привет, Spring","body":"Первая статья","author":"anna","createdAt":"2026-10-04T08:50:07.494425300Z"}

Изменение

// src/main/java/com/example/blog/PostController.java
@PutMapping("/{id}")
public Post update(@PathVariable Long id, @RequestBody NewPostRequest request) {
    return postService.update(id, request);
}
// src/main/java/com/example/blog/PostService.java
public Post update(Long id, NewPostRequest request) {
    Post old = findById(id);
    return repository.save(new Post(id, request.title(), request.body(), request.author(), old.createdAt()));
}

PUT заменяет статью целиком, поэтому принимает тот же NewPostRequest. Дата создания берётся из старой версии. Ответ — обычный 200 с обновлённой статьёй.

Удаление: 204 без тела

// src/main/java/com/example/blog/PostController.java
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long id) {
    postService.delete(id);
}
// src/main/java/com/example/blog/PostService.java
public void delete(Long id) {
    findById(id);
    repository.deleteById(id);
}

Когда возвращать нечего, удобнее @ResponseStatus: метод возвращает void, а код задан аннотацией. Вызов findById в сервисе выбросит PostNotFoundException, если статьи нет.

curl -i -X DELETE http://localhost:8080/api/posts/2
HTTP/1.1 204

ResponseEntity или @ResponseStatus

ЗадачаЧто выбрать
Код всегда один и тот же@ResponseStatus или ничего (будет 200)
Нужен заголовок, например LocationResponseEntity
Код зависит от условияResponseEntity, например ResponseEntity.notFound().build()

Частая ошибка

Ответ 200 на создание формально работает, но клиенты API ждут 201 и заголовок Location. Ещё хуже возвращать 200 с текстом ошибки внутри JSON: программа-клиент проверяет код статуса и решит, что всё прошло успешно. Код статуса должен говорить правду о результате.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.