java Spring Boot自定义http错误响应?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26236811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:32:24  来源:igfitidea点击:

Spring Boot customize http error response?

javaresterror-handlingspring-boot

提问by matsev

How can I customize the response status code and the data in the response body if an exception occurs in a Spring Boot web application?

Spring Boot Web 应用程序发生异常时,如何自定义响应状态码和响应正文中的数据?

I have created a web app that throws a custom exception if something unexpected occurs due to some bad internal state. Consequently, the response body of the request that triggered the error looks something like:

我创建了一个 Web 应用程序,如果由于某些错误的内部状态而发生意外,它会抛出自定义异常。因此,触发错误的请求的响应正文类似于:

HTTP/1.1 500 Internal Server Error
{
    "timestamp": 1412685688268,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "com.example.CustomException",
    "message": null,
    "path": "/example"
}


Now, I would like to change the status code and set the fields in the response body. One solution that crossed my mind was something like:

现在,我想更改状态代码并设置响应正文中的字段。我想到的一个解决方案是:

@ControllerAdvice
class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    ErrorMessage handleBadCredentials(CustomException e) {
        return new ErrorMessage("Bad things happened");
    }
}

@XmlRootElement
public class ErrorMessage(
    private String error;

    public ErrorMessage() {
    }

    public ErrorMessage(String error) {
        this.error = error;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
)

However, that created (as suspected) a completely different response:

然而,这产生了(如怀疑的)完全不同的反应:

HTTP/1.1 400 Bad Request
{
    "error": "Bad things happened"
}

采纳答案by matsev

The http response status code can be changed by using the HttpServletResponse.sendError(int)method, e.g.

可以使用HttpServletResponse.sendError(int)方法更改 http 响应状态代码,例如

@ExceptionHandler
void handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value());
}

Alternatively, you can declare the exception type in the @ExceptionHandlerannotation if you have two or more exceptions to generate the same response status:

或者,@ExceptionHandler如果您有两个或多个异常生成相同的响应状态,您可以在注释中声明异常类型:

@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class})
void handleBadRequests(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value());
}

More information can be found in my blog post.

更多信息可以在我的博客文章中找到。

回答by itzg

As @zeroflagL mentioned, Spring Boot fabricates the "standard" error response body in org.springframework.boot.autoconfigure.web.DefaultErrorAttributes. Similar to your needs, I wanted to leverage all of that, but simply augment one more "type" field that was provided by some of my exceptions.

正如@zeroflagL 所提到的,Spring Boot 在org.springframework.boot.autoconfigure.web.DefaultErrorAttributes. 与您的需求类似,我想利用所有这些,但只需增加一个由我的一些例外提供的“类型”字段。

I did that by implementing a Componentthat sub-classed DefaultErrorAttributes. Spring Boot automatically picked it up and used mine instead of the default.

我通过实现一个Component子类来做到这一点 DefaultErrorAttributes。Spring Boot 自动选择它并使用我的而不是默认的。

@Component
public class ExtendedErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
        final Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);

        final Throwable error = super.getError(requestAttributes);
        if (error instanceof TypeProvider) {
            final TypeProvider typeProvider = (TypeProvider) error;
            errorAttributes.put("type", typeProvider.getTypeIdentifier());
        }

        return errorAttributes;
    }
}

With that, I get an augmented JSON response body, such as

有了这个,我得到了一个增强的 JSON 响应体,例如

{
  "timestamp": 1488058582764,
  "status": 429,
  "error": "Too Many Requests",
  "exception": "com.example.ExternalRateLimitException",
  "message": "DAILY_LIMIT: too many requests",
  "path": "/api/lookup",
  "type": "DAILY_LIMIT"
}