【问题标题】:Spring boot Exception custom handling - Unexpected HTTP statusSpring Boot 异常自定义处理 - 意外的 HTTP 状态
【发布时间】:2019-02-25 02:14:41
【问题描述】:

我正在尝试在我的 Spring Boot 应用程序中实现一些自定义异常处理程序,这些处理程序将能够处理自定义异常并显示适当的消息和状态代码。

我的问题:即使响应正文是根据我的自定义处理程序获得的 http 状态 = 500。

代码:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler({ BadRequestValidationFailureException.class, Exception.class })
public ResponseEntity<Object> handleAll(Exception ex, WebRequest request) {

    ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getMessage());

    return new ResponseEntity<Object>( apiError, new HttpHeaders(), HttpStatus.BAD_REQUEST );

}

并抛出异常:

throw new BadRequestValidationFailureException( "ERROR_CODE", "THIS IS THE MESSAGE" );

输出是:

{
"timestamp": "2018-09-20T17:44:01.502Z",
"status": 500,
"error": "Internal Server Error",
"exception": "com.hotstar.payment.exception.BadRequestValidationFailureException",
"message": "[ ERROR_CODE ] THIS IS THE MESSAGE",
"path": "/my/api/path"
}

奇怪的是http响应状态是500。

请帮忙。

【问题讨论】:

    标签: spring spring-boot exception-handling


    【解决方案1】:

    找到解决方案。不得不设置另一个注释:

    @ResponseStatus(value = HttpStatus.BAD_REQUEST, code = HttpStatus.BAD_REQUEST, reason = "some reason")
    

    将此添加到handleAll 方法。

    【讨论】:

      【解决方案2】:

      我在以下模式方面取得了很好的经验:

      @ControllerAdvice
      public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
          private static final Map<MyProjectErrorCode, HttpStatus> CODE_STATUS_MAP = new EnumMap<>(MyProjectErrorCode.class);
      
          static {
              CODE_STATUS_MAP.put(MyProjectErrorCode.MYPROJ_ILLEGAL_PROPERTY, HttpStatus.BAD_REQUEST);
              CODE_STATUS_MAP.put(MyProjectErrorCode.MYPROJ_FOO, HttpStatus.BAD_REQUEST);
              CODE_STATUS_MAP.put(MyProjectErrorCode.MYPROJ_THIRDPARTYX_CLIENT, HttpStatus.INTERNAL_SERVER_ERROR);
              CODE_STATUS_MAP.put(MyProjectErrorCode.MYPROJ_UNKNOWN, HttpStatus.INTERNAL_SERVER_ERROR);
              CODE_STATUS_MAP.put(MyProjectErrorCode.THIRDPARTYX_BAR, HttpStatus.BAD_REQUEST);
              CODE_STATUS_MAP.put(MyProjectErrorCode.THIRDPARTYX_UNKNOWN, HttpStatus.INTERNAL_SERVER_ERROR);
          }
      
          @ExceptionHandler(MyProjectException.class)
          public ResponseEntity<ErrorResponse> handleMyProjectException(MyProjectException ex) {
              ErrorResponse errorResponse = createErrorResponse(ex.getErrorCode(), ex.getMessage());
              HttpStatus httpStatus = determineHttpStatus(ex.getErrorCode());
              return handleErrorResponse(errorResponse, httpStatus);
          }
      
          @ExceptionHandler(IllegalArgumentException.class)
          public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
              MyProjectErrorCode errorCode = MyProjectErrorCode.MYPROJ_ILLEGAL_PROPERTY;
              ErrorResponse errorResponse = createErrorResponse(errorCode, ex.getMessage());
              HttpStatus httpStatus = determineHttpStatus(errorCode);
              return handleErrorResponse(errorResponse, httpStatus);
          }
      
          @ExceptionHandler(RuntimeException.class)
          public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
              MyProjectErrorCode errorCode = MyProjectErrorCode.MYPROJ_UNKNOWN;
              ErrorResponse errorResponse = createErrorResponse(errorCode, ex.getMessage());
              HttpStatus httpStatus = determineHttpStatus(errorCode);
              return handleErrorResponse(errorResponse, httpStatus);
          }
      
          private ResponseEntity<ErrorResponse> handleErrorResponse(ErrorResponse errorResponse, HttpStatus httpStatus) {
              return new ResponseEntity<>(errorResponse, httpStatus);
          }
      
          private ErrorResponse createErrorResponse(MyProjectErrorCode errorCode, String message) {
              ErrorResponse errorResponse = new ErrorResponse();
              errorResponse.setErrorCode(errorCode.name());
              errorResponse.setErrorMessage(message);
              return errorResponse;
          }
      
          private HttpStatus determineHttpStatus(MyProjectErrorCode errorCode) {
              return CODE_STATUS_MAP.getOrDefault(errorCode, HttpStatus.INTERNAL_SERVER_ERROR);
      }
      

      客户端可以从 Http 响应中获取 HttpStatus - 无需将其添加到 JSON 正文中。

      项目特定的 MyProjectErrorCode 枚举允许您向客户传达详细的错误代码。客户端可以分析此错误代码并根据错误代码采取适当的措施或显示本地化(特定或通用)错误消息。

      MyProjectErrorCode 还允许您在代码中创建错误(以 MYPROJ_ 开头)或错误是否从第三方“x”服务转发(以 THIRDPARTYX_ 开头)进行通信。

      您还可以创建 MyProjectException 和 ErrorResponse 的子类来为特定情况传输更具体的数据 - 只需为该异常添加一个额外的异常处理方法。

      【讨论】:

        猜你喜欢
        • 2021-07-10
        • 2019-12-10
        • 2023-03-04
        • 2018-12-07
        • 1970-01-01
        • 2022-01-12
        • 2016-12-09
        • 2018-12-30
        • 1970-01-01
        相关资源
        最近更新 更多