Чтобы упростить обработку ошибок, мне нужен ExceptionHandler, я использовал точку 4. на http://www.baeldung.com/exception-handling-for-rest-with-spring.
Мой класс обработчика исключений выглядит следующим образом:
@ControllerAdvice
class APIExceptionHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(value = [(TestException::class)])
fun handleConflict(exception: TestException, request: WebRequest): ResponseEntity<Any> {
println("Handle")
return handleExceptionInternal(exception, "Response Body", HttpHeaders(), HttpStatus.BAD_REQUEST, request)
}
}
TestException - это простой Exception, расширяющий RuntimeException
class TestException : RuntimeException()
Во всяком случае, в моем RestController я просто бросаю исключение, как только делается любой вызов:
@GetMapping("/lobby/close")
fun closeLobby(@RequestParam(value = "uuid") uuid: String, @RequestHeader(value = "userSession") userSession: String): ResponseEntity<Any> {
throw TestException()
}
Но обработчик исключений не вызывается.
Однако вызывая это:
@GetMapping("/lobby/error")
fun error(): ResponseEntity<Any> {
throw TestException()
}
он вызывается.
Я не совсем понимаю, в чем разница, кроме первой версии, ожидающей параметров и определенного заголовка.
ОБНОВЛЕНИЕ 24.03.2018
Проблема, похоже, в том, что ExceptionHandler не вызывается, если запрос клиентов был искажен.
По умолчанию искаженный запрос приводит к довольно подробному отчету об ошибке, но пользовательский ExceptionHandler, похоже, отключает эту функцию.
Нет, я ничего не вижу.
Какой HTTP-ответ вы получите? 404?
Я получаю 400 ответов. Однако это не из-за моего исключения, потому что я получаю 400, даже если я поменяю его там.
Похоже, вы просто неправильно делаете запрос. Что произойдет, если вы удалите исключение и вернете правильное значение?
@Todd, вы правы, это не работает, только если запрос искажен, но в любом случае обработчик исключений не должен нарушать все остальные случаи обработки исключений, не так ли?




На данный момент у меня есть решение, хотя я думаю, что это не должно быть желаемым способом.
Поскольку у моих контроллеров в любом случае не было базового класса, я не создавал BaseController, который содержит функции, обрабатывающие исключения, эти функции просто аннотируются с помощью ExceptionHandler, а их список методов содержит Exception, которые они должны обрабатывать.
Поскольку класс BasicController не расширяет какой-либо другой класс Spring, который обрабатывает исключения, он не отменяет поведение по умолчанию для обработки таких проблем, как искаженные запросы.
Я с радостью принимаю любое лучшее решение, потому что не думаю, что это должно быть желаемым способом.
У меня все заработало, вот мой код.
@ControllerAdvice
class ControllerAdviceRequestError : ResponseEntityExceptionHandler() {
@ExceptionHandler(value = [(UserAlreadyExistsException::class)])
fun handleUserAlreadyExists(ex: UserAlreadyExistsException,request: WebRequest): ResponseEntity<ErrorsDetails> {
val errorDetails = ErrorsDetails(Date(),
"Validation Failed",
ex.message!!
)
return ResponseEntity(errorDetails, HttpStatus.BAD_REQUEST)
}
}
Класс исключения
class UserAlreadyExistsException(override val message: String?) : Exception(message)
Класс данных
data class ErrorsDetails(val time: Date, val message: String, val details: String)
MyController:
@PostMapping(value = ["/register"])
fun register(@Valid @RequestBody user: User): User {
if (userService.exists(user.username)) {
throw UserAlreadyExistsException("User with username ${user.username} already exists")
}
return userService.create(user)
}
Я пробовал это, он работает ТОЛЬКО, если мне нужно обрабатывать определенные исключения. Он терпит неудачу, как только у меня есть 2 метода, один для пользовательских исключений и один для общих исключений. Всякий раз, когда создавалось определяемое пользователем исключение, оно перехватывалось методом, аннотированным @ExceptionHandler(Exception::class), а не @ExceptionHandler(UserAlreadyExistsException::class). Какие-нибудь решения? Когда я попробовал это в java, он работал как шарм, но не в котлине.
Я не знаю, есть ли какая-то конкретная ошибка, связанная с котином, в этом случае попробуйте расширить поиск
Когда вы вызываете
closeLobby(), видите ли вы исключение в журналах?