1. Обзор
В этом кратком руководстве мы обсудим новый класс ResponseStatusException , представленный весной 5. Этот класс поддерживает применение кодов состояния HTTP к ответам HTTP.
Приложение RESTful может сообщить об успешном или неудачном выполнении HTTP-запроса, вернув правильный код состояния в ответе клиенту . Проще говоря, соответствующий код состояния может помочь клиенту определить проблемы, которые могли возникнуть во время обработки запроса приложением.
2. Статус Ответа
Прежде чем мы углубимся в ResponseStatusException, давайте быстро взглянем на аннотацию @ResponseStatus . Эта аннотация была введена весной 3 для применения кода состояния HTTP к ответу HTTP .
Мы можем использовать аннотацию @ResponseStatus для установки статуса и причины в нашем HTTP-ответе:
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Actor Not Found") public class ActorNotFoundException extends Exception { // ... }
Если это исключение возникает при обработке HTTP-запроса, то в ответе будет указан статус HTTP, указанный в этой аннотации.
Одним из недостатков подхода @ResponseStatus является то, что он создает тесную связь с исключением. В нашем примере все исключения типа Actor NotFoundException будут генерировать одно и то же сообщение об ошибке и код состояния в ответе.
3. ResponseStatusException
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, аргументы конструктора:
- статус – статус HTTP, установленный для ответа HTTP
- причина – сообщение, объясняющее исключение, установленное в HTTP-ответе
- причина – а Throwable причина исключения ResponseStatusException
Примечание: весной 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 .