【问题标题】:How to set different status code for different type of Exception如何为不同类型的异常设置不同的状态码
【发布时间】:2018-06-07 12:12:42
【问题描述】:

我正在尝试使用 @ControllerAdvice 处理 Spring Boot 应用程序中的异常。我不想为每种类型的异常使用单独的方法。我想只使用一种方法处理所有类型的异常,主类为@ExceptionHandler(Exception.class)

我尝试像下面这样正确处理异常,但问题是我还想为不同类型的异常设置不同类型的状态代码。

在这里,对于每种类型的异常,我都会收到 500

谁能告诉我如何为不同类型的异常设置不同的状态码?

    @ControllerAdvice
    public class RestExceptionHandler {

        @ExceptionHandler(Exception.class)
        public  ResponseEntity<Object>  handleAllExceptionMethod(Exception ex,WebRequest requset) {

            ExceptionMessage exceptionMessageObj = new ExceptionMessage();                                   

            exceptionMessageObj.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            exceptionMessageObj.setMessage(ex.getLocalizedMessage());
            exceptionMessageObj.setError(ex.getClass().getCanonicalName());     
            exceptionMessageObj.setPath(((ServletWebRequest) requset).getRequest().getServletPath());

            return new ResponseEntity<>(exceptionMessageObj, new HttpHeaders(),HttpStatus.INTERNAL_SERVER_ERROR);       
        }
    }

【问题讨论】:

  • 从代码的最后一行开始。
  • 您将状态码设置为HttpStatus.INTERNAL_SERVER_ERROR,因此您将获得 500
  • 我需要改变什么才能获得灵活的状态码,但有例外

标签: java spring spring-boot exception-handling


【解决方案1】:

您还可以使用不同的 Spring 方法。请注意,它不适用于本机 Java 异常(因为您需要在 Exception 类定义中添加注释),您可能会接受也可能不会接受。

  1. 为要显示的状态代码定义自定义异常(或重用当前业务逻辑中的现有异常)。
  2. @ResponseStatus 添加到每个例外的顶部。
  3. 在您的控制器中,仅抛出这些异常。

这样,您不需要对异常进行任何类型检查。您甚至不需要定义自己的@ControllerAdvice。 Spring 将处理显示正确的 HTTP 状态代码。如果您确实选择仍然使用此方法实现您的@ControllerAdvice,您可以使用注释来获取正确的状态代码:

import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation

HttpStatus resolveAnnotatedResponseStatus(Exception exception) {
    ResponseStatus annotation = findMergedAnnotation(exception.getClass(), ResponseStatus.class);
    if (annotation != null) {
        return annotation.value();
    }
    return HttpStatus.INTERNAL_SERVER_ERROR;
}

(注解解析方法原贴here

【讨论】:

    【解决方案2】:

    您可以检查哪个实例是您的异常并相应地返回:

    @ControllerAdvice
    public class RestExceptionHandler {
    
     @ExceptionHandler(Exception.class)
     public ResponseEntity < Object > handleAllExceptionMethod(Exception ex, WebRequest requset) {
    
      if (ex instanceof MyCustomException1) {
       // Return error code 500
      } else {
       // return error code 404
      }
     }
    

    【讨论】:

      【解决方案3】:

      我会先质疑您的需求。为什么要将所有异常处理集中在一个地方?

      这与另一个需要相反 - 可配置响应代码。

      你有两个选择:

      • 创建一个包含异常实例的讨厌的 if/else 开关
      • 不要用一种方法处理所有事情

      我更喜欢后一种,如果你担心你的代码会被复制 - 请看下面:

      @RestControllerAdvice
      public class ExceptionHandler {
      
          @ExceptionHandler(YourException1.class)
          public ResponseEntity<ExceptionMessage> handleYourException1(YourException1 ex, WebRequest requset) {
              return commonHandler(HttpStatus.INTERNAL_SERVER_ERROR, ex, requset);
          }
      
          public ResponseEntity<ExceptionMessage> commonHandler(HttpStatus status, Exception ex, WebRequest requset) {
              ExceptionMessage exceptionMessageObj = new ExceptionMessage();
      
              exceptionMessageObj.setStatus(status.value());
              exceptionMessageObj.setMessage(ex.getLocalizedMessage());
              exceptionMessageObj.setError(ex.getClass().getCanonicalName());
              exceptionMessageObj.setPath(((ServletWebRequest) requset).getRequest().getServletPath());
      
              return new ResponseEntity<>(exceptionMessageObj, status);
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可以根据异常类型设置不同的状态码。

        HttpStatus statuscode = HttpStatus.INTERNAL_SERVER_ERROR;
        
        if(ex instanceof ExceptionClass1){
           statuscode = HttpStatus.BAD_REQUEST;
        }else if(ex instanceof ExceptionClass2){
          statuscode = HttpStatus.FORBIDDEN;
        }
        

        【讨论】:

          【解决方案5】:
          @ControllerAdvice
          public class RestExceptionHandler {
          
              @ExceptionHandler(Exception.class)
              public ResponseEntity<?> handleAllExceptions(Exception e) {
                  log.error("IOException: " + e.getMessage());
          
                  final Map<String, String> message = new HashMap<>();
                  message.put("message", "Something went wrong...");
          
                  // My custom IOException handler :)
                  if (e instanceof IOException) {
                      return ResponseEntity.unprocessableEntity().body(message);
                  }
          
                  return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
              }
          
          }
          

          【讨论】:

            【解决方案6】:

            您可以使用switch语句并创建多个案例:

            @ExceptionHandler(Exception.class)
            public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
                ErrorResponse errorResponse = new ErrorResponse(new DescriptionInErrorResponse());
                errorResponse.getError().setText(ex.getMessage());
            
                HttpStatus httpStatus = HttpStatus.UNPROCESSABLE_ENTITY;
            
                if (ex instanceof CustomException) {
                    switch (((CustomException) ex).getCode()) {
                        case BAD_REQUEST:
                            errorResponse.getError().setCode(ErrorCode.BAD_REQUEST.getName());
                            httpStatus = HttpStatus.BAD_REQUEST;
                            break;
                        case NOT_FOUND:
                            errorResponse.getError().setCode(ErrorCode.NOT_FOUND.getName());
                            httpStatus = HttpStatus.NOT_FOUND;
                            break;
                        case METHOD_ARGUMENT_NOT_VALID:
                            errorResponse.getError().setCode(ErrorCode.METHOD_ARGUMENT_NOT_VALID.getName());
                            httpStatus = HttpStatus.BAD_REQUEST;
                            break;
            
                        default:
                            errorResponse.getError().setCode(ErrorCode.UNKNOWN.getName());
                            httpStatus = HttpStatus.UNPROCESSABLE_ENTITY;
                            break;
                    }
                } else if (ex instanceof ConstraintViolationException
                        || ex instanceof javax.validation.ConstraintViolationException) {
                    errorResponse.getError().setCode(ErrorCode.BAD_REQUEST.getName());
                    httpStatus = HttpStatus.BAD_REQUEST;
                } else if (ex instanceof MethodArgumentNotValidException) {
                    errorResponse.getError().setCode(ErrorCode.METHOD_ARGUMENT_NOT_VALID.getName());
                    httpStatus = HttpStatus.BAD_REQUEST;
            
                } else if (ex instanceof DataIntegrityViolationException) {
                    errorResponse.getError().setCode(ErrorCode.INTERNAL_SERVER_ERROR.getName());
                    httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
                } else if (ex instanceof HttpMessageNotReadableException) {
                    errorResponse.getError().setCode(ErrorCode.BAD_REQUEST.getName());
                    httpStatus = HttpStatus.BAD_REQUEST;
                } else if (ex instanceof ServletRequestBindingException){
                    errorResponse.getError().setCode(ErrorCode.BAD_REQUEST.getName());
                    httpStatus = HttpStatus.BAD_REQUEST;
                }
                else {
            
                    log.error(ex.getMessage(), ex);
                    errorResponse.getError().setCode(ErrorCode.INTERNAL_SERVER_ERROR.getName());
                    httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
                }
            
                return ResponseEntity.status(httpStatus).body(errorResponse);
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-08-14
              • 2015-07-07
              • 2018-01-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多