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

Spring ResponseStatusException

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

1. Обзор

В этом кратком руководстве мы обсудим новый класс ResponseStatusException , представленный в Spring 5. Этот класс поддерживает применение кодов состояния HTTP к ответам HTTP.

Приложение RESTful может сообщать об успешном или неудачном выполнении HTTP-запроса, возвращая правильный код состояния в ответе клиенту . Проще говоря, соответствующий код состояния может помочь клиенту определить проблемы, которые могли возникнуть во время обработки запроса приложением.

2. Статус ответа

Прежде чем мы углубимся в ResponseStatusException, давайте быстро взглянем на аннотацию @ResponseStatus . Эта аннотация была введена в Spring 3 для применения кода состояния HTTP к ответу HTTP .

Мы можем использовать аннотацию @ResponseStatus , чтобы установить статус и причину в нашем HTTP-ответе:

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Actor Not Found")
public class ActorNotFoundException extends Exception {
// ...
}

Если это исключение возникает при обработке HTTP-запроса, ответ будет включать в себя статус HTTP, указанный в этой аннотации.

Одним из недостатков подхода @ResponseStatus является то, что он создает тесную связь с исключением. В нашем примере все исключения типа ActorNotFoundException будут генерировать в ответе одно и то же сообщение об ошибке и код состояния.

3. Исключение состояния ответа

ResponseStatusException — это программная альтернатива @ResponseStatus и базовый класс для исключений, используемых для применения кода состояния к ответу HTTP. Это исключение RuntimeException , поэтому его не требуется явно добавлять в сигнатуру метода.

Spring предоставляет 3 конструктора для генерации ResponseStatusException:

ResponseStatusException(HttpStatus status)
ResponseStatusException(HttpStatus status, java.lang.String reason)
ResponseStatusException(
HttpStatus status,
java.lang.String reason,
java.lang.Throwable cause
)

ResponseStatusException, аргументы конструктора:

  • status — статус HTTP, установленный для ответа HTTP
  • причина — сообщение, объясняющее исключение, установленное для ответа HTTP.
  • причина — Throwable причина ResponseStatusException

Примечание: в Spring HandlerExceptionResolver перехватывает и обрабатывает любое исключение, сгенерированное и не обработанное контроллером.

Один из этих обработчиков, ResponseStatusExceptionResolver, ищет любые ResponseStatusException или необработанные исключения, аннотированные @ResponseStatus , а затем извлекает код и причину состояния HTTP и включает их в ответ HTTP.

3.1. Преимущества ResponseStatusException

Использование ResponseStatusException имеет несколько преимуществ:

  • Во-первых, исключения одного и того же типа могут обрабатываться отдельно, а в ответах могут быть установлены разные коды состояния, что уменьшает тесную связь.
  • Во-вторых, это позволяет избежать создания ненужных дополнительных классов исключений.
  • Наконец, он обеспечивает больший контроль над обработкой исключений, поскольку исключения можно создавать программно.

4. Примеры

4.1. Сгенерировать исключение ResponseStatusException

Теперь давайте посмотрим на пример, который генерирует ResponseStatusException :

@GetMapping("/actor/{id}")
public String getActorName(@PathVariable("id") int id) {
try {
return actorService.getActor(id);
} catch (ActorNotFoundException ex) {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "Actor Not Found", ex);
}
}

Spring Boot предоставляет сопоставление по умолчанию / error , возвращая ответ JSON со статусом HTTP.

Вот как выглядит ответ:

$ curl -i -s -X GET http://localhost:8081/actor/8
HTTP/1.1 404
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 26 Dec 2020 19:38:09 GMT

{
"timestamp": "2020-12-26T19:38:09.426+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/actor/8"
}

Начиная с версии 2.3, Spring Boot не включает сообщение об ошибке на странице ошибки по умолчанию. Причина в том, чтобы снизить риск утечки информации клиенту **

**

Чтобы изменить поведение по умолчанию, мы можем использовать свойство server.error.include-message .

Давайте установим всегда и посмотрим, что произойдет:

$ curl -i -s -X GET http://localhost:8081/actor/8
HTTP/1.1 404
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 26 Dec 2020 19:39:11 GMT

{
"timestamp": "2020-12-26T19:39:11.426+00:00",
"status": 404,
"error": "Not Found",
"message": "Actor Not Found",
"path": "/actor/8"
}

Как мы видим, на этот раз ответ содержит сообщение об ошибке «Актер не найден» .

4.2. Другой код состояния — тот же тип исключения

Теперь давайте посмотрим, как другой код состояния устанавливается для ответа HTTP при возникновении исключения того же типа:

@PutMapping("/actor/{id}/{name}")
public String updateActorName(
@PathVariable("id") int id,
@PathVariable("name") String name) {

try {
return actorService.updateActor(id, name);
} catch (ActorNotFoundException ex) {
throw new ResponseStatusException(
HttpStatus.BAD_REQUEST, "Provide correct Actor Id", ex);
}
}

Вот как выглядит ответ:

$ curl -i -s -X PUT http://localhost:8081/actor/8/BradPitt
HTTP/1.1 400
...
{
"timestamp": "2018-02-01T04:28:32.917+0000",
"status": 400,
"error": "Bad Request",
"message": "Provide correct Actor Id",
"path": "/actor/8/BradPitt"
}

5. Вывод

В этом кратком руководстве мы обсудили, как создать исключение ResponseStatusException в нашей программе.

Мы также подчеркнули, что с программной точки зрения это лучший способ установить коды состояния HTTP в HTTP-ответе, чем аннотация @ResponseStatus .

Как всегда, полный исходный код доступен на GitHub .