如何为不同类型的Exception设置不同的状态代码

时间:2018-06-07 12:12:42

标签: java spring spring-boot exception-handling

我正在尝试使用@ControllerAdvice处理Spring启动应用程序中的异常。我不希望每种类型的异常都有单独的方法。我想只使用一个主类为@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);       
        }
    }

6 个答案:

答案 0 :(得分:3)

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

  1. 为要显示的状态代码定义自定义例外(或重用当前业务逻辑中的现有代码)。
  2. @ResponseStatus添加到每个例外的顶部。
  3. 在您的控制器中,只抛出这些例外。
  4. 这样,您就不需要对异常进行任何类型检查。您甚至不需要定义自己的save()。 Spring将处理正确的HTTP状态代码。如果您确实选择使用此方法实现@ControllerAdvice,则可以使用注释来获取正确的状态代码:

    @ControllerAdvice

    (最初发布的注释解析方法here

答案 1 :(得分:1)

您可以检查您的例外情况,并相应地返回:

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

答案 2 :(得分:1)

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

HttpStatus statuscode = HttpStatus.INTERNAL_SERVER_ERROR;

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

答案 3 :(得分:1)

我首先质疑你的需求。为什么要在一个地方进行所有异常处理?

与其他需求相反 - 让响应代码可配置。

您有两种选择:

  • 创建一个令人讨厌的if / else开关,其中包含您的异常instanceofs
  • 不用一种方法处理所有内容

我更喜欢后者,如果你害怕你的代码会被复制 - 请看下面的内容:

@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 :(得分:0)

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

}

答案 5 :(得分:0)

您可以使用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);
}