【问题标题】:Kotlin - Spring REST - ControllerAdvice with ExceptionHandler won't get invokedKotlin - Spring REST - 带有 ExceptionHandler 的 ControllerAdvice 不会被调用
【发布时间】:2018-03-24 17:23:59
【问题描述】:

为了简化我的错误处理,我想要一个 ExceptionHandler,我使用了 http://www.baeldung.com/exception-handling-for-rest-with-spring 上的 4. 点。

我的异常处理程序类如下所示:

@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 似乎禁用了此功能。

【问题讨论】:

  • 当您调用closeLobby() 时,您是否在日志中看到异常?
  • 不,我什么都没看到。
  • 你得到什么 http 响应? 404?
  • 我收到 400 响应。但是,它不是来自我的例外,因为即使我在那边改变它,我也会得到 400。
  • 听起来您只是没有正确提出请求。如果删除异常并返回正确的值会发生什么?

标签: java spring rest exception kotlin


【解决方案1】:

我搞定了,这是我的代码。

@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)

我的控制器:

@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 中尝试它时,它就像一个魅力,但在 kotlin 中却没有。
  • 我不知道在这种情况下是否有任何与 kotin 相关的特定错误尝试扩大搜索范围
【解决方案2】:

现在我有一个解决方案,尽管这不应该是我认为的理想方式。

因为无论如何我的控制器都没有基类,所以我没有创建一个包含处理异常的函数的BaseController,这些函数只是用ExceptionHandler 注释,并且它们的方法列表包含它们应该处理的Exception

由于BasicController 类没有扩展任何其他处理异常的 Spring 类,它不会覆盖处理格式错误请求等问题的默认行为。

我很乐意接受任何更好的解决方案,因为我认为这不应该是理想的方式。

【讨论】:

    【解决方案3】:

    请在此处阅读:https://newbedev.com/setting-precedence-of-multiple-controlleradvice-exceptionhandlers

    关于:

    @ControllerAdvice
    @Order(Ordered.HIGHEST_PRECEDENCE)
    

    @ControllerAdvice
    @Order(Ordered.LOWEST_PRECEDENCE)
    

    你可以先结合这些来处理更具体的异常

    【讨论】:

      猜你喜欢
      • 2021-05-22
      • 2013-04-16
      • 1970-01-01
      • 2021-05-27
      • 2017-12-05
      • 2012-04-12
      • 2013-05-15
      • 2018-12-10
      • 2021-03-24
      相关资源
      最近更新 更多