Spring позволяет настраивать глобальное поведение для контроллеров через @ ControllerAdvice
Классы, аннотированные @ControllerAdvice, могут содержать аннотированные методы @ExceptionHandler, @InitBinder и @ModelAttribute, и эти методы будут применяться к методам @RequestMapping. во всех иерархиях контроллеров, в отличие от иерархии контроллеров, в которой они объявлены.
Обычно мы используем его для обработки исключений глобально с @ExceptionHandler
, но это не ваш случай. (@InitBinder
, @ModelAttribute
тоже)
Существует ResponseBodyAdvice
, но нет ResponseStatusAdvice
Так что, похоже, прямого решения не существует
Обходной путь:
Это довольно грязный хак, и я действительно рекомендую просто использовать @ResponseStatus каждый раз, но если вы действительно хотите решить эту проблему глобально, тогда:
Вы можете объединить обработку ошибок и ResponseBodyAdvice
Вы должны создать класс исключения
class NoContentException: RuntimeException()
и создать обработчик для него. Он должен быть вызван после @ControllerAdvice
, который вызовет исключение NoContentException, поэтому он имеет @Order(1)
@ControllerAdvice
@Order(1)
class NoContentErrorHandler {
@ExceptionHandler(NoContentException::class)
fun handleNoContent() = ResponseEntity.noContent().build<Unit>()
}
и в конце создаст подсказку тела ответа, которая выдает фактическое исключение:
@ControllerAdvice
@Order(0)
class ThrowingNoContentExceptionResponseBodyAdvice : ResponseBodyAdvice<Unit> {
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean {
return returnType.parameterType == Void.TYPE
}
override fun beforeBodyWrite(
body: Unit?,
returnType: MethodParameter,
selectedContentType: MediaType,
selectedConverterType: Class<out HttpMessageConverter<*>>,
request: ServerHttpRequest,
response: ServerHttpResponse
): Unit? {
throw NoContentException()
}
}
Таким образом, он работает следующим образом: запрос -> метод с ответным вызовом модуля -> рекомендация, выдающая исключение -> рекомендация, обрабатывающая исключение и преобразующая его в состояние NO_CONTENT