5

我想根据响应对象错误动态返回 HTTPStatus 代码,如 400、400、404 等。我被提到了这个问题 - Programmatically change http response status using spring 3 restful但它没有帮助。

我有这个带有@ExceptionHandler方法的 Controller 类

@ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseEntity<?> handleException(CustomException e) {
        return new ResponseEntity<MyErrorResponse>(
                new MyErrorResponse(e.getCode(), ExceptionUtility.getMessage(e.getMessage())), 
                ExceptionUtility.getHttpCode(e.getCode()));
    }

ExceptionUtility是一个类,我有上面使用的两种方法(getMessagegetCode)。

public class ExceptionUtility {
    public static String getMessage(String message) {
        return message;
    }

    public static HttpStatus getHttpCode(String code) {
        return HttpStatus.NOT_FOUND; //how to return status code dynamically here ?
    }
}

我不想检查 if 条件并相应地返回响应代码,还有其他更好的方法吗?

4

3 回答 3

3

第一种方法:

您可以在 customException 类中使用 HTTPStatus 字段。例如

    class CustomException {
         HttpStatus httpStatus;
         ....other fields
    }

您可以抛出如下错误:

throw new CustomException(otherField , HttpStatus.CREATED);

在您的异常处理程序中,您可以执行以下操作:

@ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseEntity<?> handleException(CustomException e) {
        return new ResponseEntity<MyErrorResponse>(
                new MyErrorResponse(e.getCode(), ExceptionUtility.getMessage(e.getMessage())), 
                e.getHttpStatus());
    }

其中,e.getHttpStatus()返回HTTPStatus

第二种方法:

或者您可以像这样为您的代码声明枚举:

public enum ErrorCode {


    MyErrorCode(HttpStatus.OK);

    HttpStatus status;

//getter for httpstatus
}

然后您可以将异常处理程序修改为

@ExceptionHandler(CustomException.class)
        @ResponseBody
        public ResponseEntity<?> handleException(CustomException e) {
            return new ResponseEntity<MyErrorResponse>(
                    new MyErrorResponse(e.getCode(), ExceptionUtility.getMessage(e.getMessage())), 
                    e.getHttpStatus());
        }

其中 e.getHttpStatus() 又是对枚举的方法调用,但为此,您必须在自定义异常中更改代码字段类型,如果您也不想这样做,那么您可以在枚举中编写一个辅助方法喜欢:

HttpStatus getHttpStatus(String code) {
   return ErrorCode.valueOf(code.toUpperCase()).getHttpStatus();
}

对不起,我错过了上述方法中的空指针异常,但您可以根据需要修改它,只是给出一个想法。:)

于 2021-05-25T12:07:35.307 回答
2

您的@ExceptionHandler方法需要两件事: (i)有一个HttpServletResponse参数,以便您可以设置响应状态码;( ii)没有@ResponseStatus注释。

@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseEntity<?> handleException(HttpServletResponse resp, CustomException e) {
    resp.setStatus(ExceptionUtility.getHttpCode(e.getCode()).value());
    return new ResponseEntity<MyErrorResponse>(
            new MyErrorResponse(e.getCode(), ExceptionUtility.getMessage(e.getMessage())),
            ExceptionUtility.getHttpCode(e.getCode()));
}

我已经使用这种@ExceptionHandler来处理NestedServletException,这是 Spring 有时会创建一个异常来包装需要处理的“实际”异常(下面的代码)。请注意@ExceptionHandler,如果需要,该方法可以将请求和响应对象作为参数。

@ExceptionHandler(NestedServletException.class)
@ResponseBody
public Object handleNestedServletException(HttpServletRequest req, HttpServletResponse resp, 
        NestedServletException ex) {
    Throwable cause = ex.getCause();
    if (cause instanceof MyBusinessLogicException) {
        resp.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
        return createStructureForMyBusinessLogicException((MyBusinessLogicException) cause);
    }
    if (cause instanceof AuthenticationException) {
        resp.setStatus(HttpStatus.UNAUTHORIZED.value());
    } else if (cause instanceof AccessDeniedException) {
        resp.setStatus(HttpStatus.FORBIDDEN.value());
    } else {
        resp.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
    }
    return createStructureForOtherErrors(req, cause.getMessage(), resp.getStatus());
}
于 2018-10-18T19:58:47.397 回答
1

您需要为不同的异常定义不同的异常处理程序,然后使用@ResponseStatus如下:

@ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler({ UnAuthorizedException.class })
    public @ResponseBody ExceptionResponse unAuthorizedRequestException(final Exception exception) {

        return response;
    }

@ResponseStatus(HttpStatus.CONFLICT)
    @ExceptionHandler({ DuplicateDataException.class })
    public @ResponseBody ExceptionResponse DuplicateDataRequestException(final Exception exception) {

        return response;
    }

@ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({ InvalidException.class })
    public @ResponseBody ExceptionResponse handleInvalidException(final Exception exception) {

        return response;
    }

这里的InvalidException.classDuplicateDataException.class是例子。您可以定义自定义异常并从控制器层抛出它们。例如,您可以定义 a并从异常处理程序UserAlreadyExistsException返回错误代码。HttpStatus.CONFLICT

于 2016-09-20T08:39:32.810 回答