Spring Framework吞下自定义转换器的例外

时间:2017-09-26 12:09:44

标签: spring spring-mvc kotlin

我遇到了Spring(和kotlin?)的问题,我的全局错误处理程序没有捕获自定义转换器中抛出的任何异常。

我知道spring默认支持string-> UUID映射,但我想明确检查是否实际抛出了异常。这是以下转换器。无论是否有我自己的转换器实现,行为都是一样的。

我的WebMvcConfuguration如下所示:

using Swashbuckle.Application;

[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]

namespace NEOH.Api
{
    public class SwaggerConfig
    {
        public static void Register()
        {

这是我的GlobalExceptionHandler: (它还包含其他处理程序,为简洁起见我省略了)

@Configuration
class WebMvcConfiguration : WebMvcConfigurerAdapter() {

    override fun addFormatters(registry: FormatterRegistry) {
        super.addFormatters(registry)
        registry.addConverter(Converter<String, UUID> { str ->
            try {
                UUID.fromString(str)
            } catch(e: IllegalArgumentException){


         throw RuntimeException(e)
        }
    })
}

最后,控制器:

@ControllerAdvice
class GlobalExceptionHandler : ResponseEntityExceptionHandler() {

    @ExceptionHandler(Exception::class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    fun handleException(ex: Exception): ApiError {
        logger.info(ex.message, ex)
        return ApiError(ex.message)
    }
}

控制器内部的异常(例如NotImplementedError)方法被捕获得很好。但吞下无效UUID时在转换器中抛出的IllegalArgumentException,并且spring返回空400响应。

我现在的问题是:如何捕获这些错误并回复自定义错误消息?

提前致谢!

3 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。 Spring吞噬了任何IllegalArgumentException(在我的情况下为ConversionFailedException)。

获得我正在寻找的行为;即,只处理列出的例外并使用其他例外的默认行为,您不得扩展ResponseEntityExceptionHandler

示例:

@ControllerAdvice
public class RestResponseEntityExceptionHandler{

    @ExceptionHandler(value = {NotFoundException.class})
    public ResponseEntity<Object> handleNotFound(NotFoundException e, WebRequest request){
        return new ResponseEntity<>(e.getMessage(), new HttpHeaders(), HttpStatus.NOT_FOUND);
    }

}

答案 1 :(得分:0)

经过一些试验和错误后,我找到了一个解决方案:

不是使用@ControllerAdvice,而是实现其他人继承的BaseController并添加异常处理程序。

所以我的Base控制器看起来像这样:

abstract class ApiBaseController{

    @ExceptionHandler(Exception::class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    fun handleException(ex: Exception): ApiError {
        return ApiError(ex.message)
    }

}

如果有人可以详细说明它为什么会这样,而不是其他方式,请这样做,我会将你的答案标记为已接受。

答案 2 :(得分:0)

我从@ georg-moser检查了解决方案。起初,它看起来不错,但看起来它还包含另一个问题。它将所有异常转换为HTTP代码500 ,这不是人们一直想要的。

相反,我决定从handleExceptionInternal覆盖ResponseEntityExceptionHandler方法。

在我的情况下,记录错误已足够,所以我得出以下结论:

@Override
@NonNull
protected ResponseEntity<Object> handleExceptionInternal(@Nonnull final Exception e,
                                                         final Object body,
                                                         final HttpHeaders headers,
                                                         final HttpStatus status,
                                                         @Nonnull final WebRequest request) {
    final ResponseEntity<Object> responseEntity = super.handleExceptionInternal(e, body, headers, status, request);
    logGenericException(e);
    return responseEntity;
}

希望对您有帮助!