java - Spring boot Rest 以空主体响应异常,而不是在我的@ControllerAdvice 中覆盖的异常

标签 java spring spring-boot controller-advice

我有一个扩展了 ResponseEntityExceptionHandler 的 @ControllerAdvice,作为我尝试控制 API 调用工作流中引发的任何异常的标准响应。

没有 Controller 的建议。我得到了 spring 生成的基于 HTML 的通用响应,响应 header 正确。但是当我添加我的@ControllerAdvice 时,Spring 不会响应一般错误主体。正文为空,响应 header 正确

@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request) {

        String erroMessage = "Required Parameter: '"+ex.getParameterName()+"' was not available in the request.";
        TrsApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, erroMessage, ex, ApiErrorCode.INVALID_REQUEST);
        return buildResponseEntity(apiError);
}

因此,现在如果请求中缺少必需的参数,流程会完美地触发我覆盖的实现并使用描述错误的 JSON 有效负载进行响应。但是,如果出现 HttpMediaTypeNotAcceptableException 等任何其他异常,spring 将以空主体响应。

在我添加我的建议之前,spring 正在响应一般错误响应。我是 spring boot 生态系统的新手。需要帮助来理解这是否是预期的行为,以及是否有更好的方法来实现集中式错误处理。

最佳答案

我想当 ControllerAdvice 类扩展 ResponeEntityExceptionHandler 时,我找到了吞噬 body 的解决方案。在我的例子中,设置如下所示:

@ControllerAdvice
@Slf4j
class GlobalExceptionHandlers extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
                                      MethodArgumentNotValidException exception,
                                      HttpHeaders headers,
                                      HttpStatus status,
                                      WebRequest request) {
        // logic that creates apiError object (object with status, message, errorCode, etc)
        //...
        return handleExceptionInternal(exception, apiError, headers, status, request);
    }

对于 MethodArgumentNotValidException 类的异常,这就像一个魅力。但它破坏了由 ResponseEntityExceptionHandler 处理的所有其他异常,并为它们返回空响应主体。

但修复很简单,只需覆盖 ResponseEntityExceptionHandler 中的 handleExceptionInternal:

@ControllerAdvice
@Slf4j
class GlobalExceptionHandlers extends ResponseEntityExceptionHandler {

    /// ... code from previous snippet

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(
                                      Exception exception, 
                                      Object body, 
                                      HttpHeaders headers, 
                                      HttpStatus status, 
                                      WebRequest request) {
        // for all exceptions that are not overriden, the body is null, so we can
        // just provide new body based on error message and call super method
        var apiError = Objects.isNull(body) 
                ? new ApiError(status, exception.getMessage()) // <-- 
                : body;
        return super.handleExceptionInternal(exception, apiError, headers, status, request);
    }
}

关于java - Spring boot Rest 以空主体响应异常,而不是在我的@ControllerAdvice 中覆盖的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56527952/

相关文章:

java - 带反射的模块化共闭包原理

java - 您应该同步对 Java 中的属性的访问吗?

java - 为什么有关线程的代码显示a = 1和b = 3?为什么添加 "volatile"不起作用?

java - 无法在 Spring 3.2.8 和 junit 4.4 中 Autowiring 现场执行 Junit 测试

java - 如何在Spring Data中进行Mongo聚合查询?

docker - 未能执行 objective-c om.spotify :docker-maven-plugin:0. 4.3:构建异常捕获:HttpHostConnectException:连接到 localhost:2375

spring - Jhipster:在没有 Web 服务器的情况下运行 junit 测试

java - 如何解决 Spring boot 2.2.6 无法在端口已在使用的情况下启动应用程序的问题?

java - .restart smali 关键字有什么作用?

java - Android 客户端 - Java 服务器 : how many clients can a server support at the same time?