Прежде чем мы углубимся в 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 будут генерировать одно и то же сообщение об ошибке и код состояния в ответе.
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, аргументы конструктора:
- status - статус HTTP установлен на HTTP-ответ
- причина - сообщение, объясняющее исключение, установленное для ответа HTTP
- причина - одноразовая причина ResponseStatusException
Примечание: в Spring HandlerExceptionResolver перехватывает и обрабатывает любое исключение, вызванное и не обработанное контроллером.
Один из этих обработчиков, ResponseStatusExceptionResolver, ищет любые исключения ResponseStatusException или uncaught, аннотированные @ResponseStatus, а затем извлекает код и причину состояния HTTP и включает их в ответ HTTP.
Преимущества ResponseStatusException
Использование ResponseStatusException имеет несколько преимуществ:
- Во-первых, исключения одного и того же типа могут обрабатываться отдельно, а в ответе могут быть установлены разные коды состояния, уменьшая жесткую связь
- Во-вторых, избегает создания ненужных дополнительных классов исключений
- Наконец, он обеспечивает больший контроль над обработкой исключений, поскольку исключения могут создаваться программно
Spring 5 представил класс ResponseStatusException. Мы можем создать его экземпляр, предоставив HttpStatus и, возможно, причину и причину:
@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);
}
}
Каковы преимущества использования ResponseStatusException?
- Отлично подходит для создания прототипов: мы можем довольно быстро реализовать базовое решение
- Один тип, несколько кодов состояния. Один тип исключения может привести к нескольким различным ответам. Это уменьшает жесткую связь по сравнению с @ ExceptionHandler
- Нам не нужно создавать столько пользовательских классов исключений
- Больше контроля над обработкой исключений, поскольку исключения могут создаваться программно
А как насчет компромиссов?
- Единого способа обработки исключений не существует: реализовать некоторые соглашения для всего приложения труднее, чем @ControllerAdvice, который обеспечивает глобальный подход
- Дублирование кода: мы можем оказаться копирующими код на нескольких контроллерах
Следует также отметить, что в одном приложении можно комбинировать разные подходы.
Например, мы можем реализовать @ControllerAdvice глобально, а также ResponseStatusExceptions локально. Однако мы должны быть осторожны: если одно и то же исключение может быть обработано несколькими способами, мы можем заметить некоторое неожиданное поведение. Возможное соглашение - обрабатывать одно конкретное исключение всегда одним способом.