如何在Spring Boot错误响应中更改状态代码?

时间:2019-07-01 18:05:46

标签: java spring rest spring-boot controller

我正在制作一个简单的rest服务,该服务使用RestTemplate进行一些http调用并聚合数据。

有时我会收到NotFound错误,有时还会收到BadRequest错误。

我想用相同的状态代码对我的客户端进行响应,Spring似乎已经开箱即用了这种映射。消息正常,但状态代码始终为500 Internal Server error。

我想将我的状态代码映射到我最初收到的代码

    "timestamp": "2019-07-01T17:56:04.539+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "400 Bad Request",
    "path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}

我希望这样

    "timestamp": "2019-07-01T17:56:04.539+0000",
    "status": 400,
    "error": "Internal Server Error",
    "message": "400 Bad Request",
    "path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}

它抛出HttpClientErrorException.BadRequest或HttpClientErrorException.NotFound

我的代码是一个简单的端点:

    @GetMapping("/{id}")
    public MyModel getInfo(@PathVariable String id){
        return MyService.getInfo(id);
    }

4 个答案:

答案 0 :(得分:3)

您可以使用@ControllerAdvice注释创建全局异常处理。像这样:

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = YourExceptionTypes.class)
    protected ResponseEntity<Object> handleBusinessException(RuntimeException exception, WebRequest request) {
        return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE, request);
    }
}

当引发异常时,处理程序将捕获并转换为所需的响应。原始的异常不会传播。

答案 1 :(得分:1)

我花了很多时间研究这个问题,包括这里答案中的解决方案,但这些解决方案对我不起作用(或者我没有正确实施)。

我终于有了突破。我没有抛出诸如 throw new Exception(message) 之类的通用异常,而是创建了扩展 Exception 类以用于特定异常类型的类 - 带有各自的 HTTP 错误代码和消息

@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class BadRequestException extends Exception{

    public BadRequestException(String message) {
       super(message);
    }
}

在您的应用程序逻辑中,您现在可以使用类似 throw new BadRequestException("Invalid Email") 的消息抛出错误请求异常。这将导致抛出异常:

{
"timestamp": "2021-03-01T17:56:04.539+0000",
"status": 400,
"error": "Bad Request",
"message": "Invalid Email",
"path": "path to controller"
}

您现在可以按照上述示例并更改 @ResponseStatus 中的 value 参数,为所需的不同异常创建其他自定义异常类,以匹配所需的响应代码。例如,对于 NOT FOUND 异常 @ResponseStatus (value = HttpStatus.NOT_FOUND),Java 通过 HttpStatus 枚举提供不同的 HTTP 状态代码。

For more context

我希望这足够详细并且可以帮助某人:)

答案 2 :(得分:0)

Spring Resttemplate exception handling的可能重复项您的代码需要控制器建议才能处理正在调用的服务中的异常。

答案 3 :(得分:0)

使用@ControllerAdvice接受的解决方案是不够的。可以肯定地用响应的自定义状态代码标记响应。但是,它不会以JSON的形式返回所需的响应正文,而只是以简单字符串(异常消息)返回。

DefaultErrorAttributes可以帮助获取正确的状态代码和默认错误正文。

@ControllerAdvice
public class PackedTemplateNotRecodableExceptionControllerAdvice extends ResponseEntityExceptionHandler {
    @Autowired
    private DefaultErrorAttributes defaultErrorAttributes;

    @ExceptionHandler(PackedTemplateNotRecodableException.class)
    public ResponseEntity<Object> handlePackedTemplateNotRecodableException(final RuntimeException exception, final WebRequest webRequest) {
        // build the default error response
        webRequest.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, HttpStatus.BAD_REQUEST.value(), RequestAttributes.SCOPE_REQUEST);
        final Map<String, Object> errorAttributes = defaultErrorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());

        // return the error response with the specific response code
        return handleExceptionInternal(exception, errorAttributes, new HttpHeaders(), HttpStatus.BAD_REQUEST, webRequest);
    }
}

这样,您将收到所需的错误响应,例如像这样的东西:

{
    "timestamp": "2019-07-01T17:56:04.539+0000",
    "status": 400,
    "error": "Internal Server Error",
    "message": "400 Bad Request",
    "path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}