状态未设置为响应

状态未设置为响应

本文介绍了Spring Boot 自定义 ErrorAttributes http 状态未设置为响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

遵循 Spring Boot 文档 我定义了自己的 ErrorAttributes bean(见下文),通过使用自定义异常包装该信息并生成错误,我能够使 json 响应显示我想要的信息,包括我自己的错误代码和消息来自它的回应.唯一的问题是响应的 http 状态与我在 status 属性中定义的状态不匹配,它没有被覆盖.

Following Spring Boot documentation I defined my own ErrorAttributes bean (see below), I was able to make the json response to show the information I wanted, including my own error code and message by using a custom exception to wrap that information and generate the error response from it. The only issue with this is that the http status of the response is not matching the one I define in the status attribute, it is not been overridden.

@Bean
public ErrorAttributes errorAttributes() {
    return new DefaultErrorAttributes() {
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {

            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);

            Throwable error = getError(requestAttributes);

            if (error instanceof MyException) {
                MyException myException = (MyException) error;

                errorAttributes.put("errorCode", myException.getErrorCode());
                errorAttributes.put("message", myException.getMessage());
                errorAttributes.put("status", myException.getStatus());

                HttpStatus correspondentStatus = HttpStatus.valueOf(myException.getStatus());
                errorAttributes.put("error", correspondentStatus.getReasonPhrase());
            }

            return errorAttributes;
        }
    };
}

响应的http状态与json中的状态不匹配,例如:

The response's http status is not matching the status in the json, for example:

HTTP/1.1 500
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 01 Mar 2017 18:48:22 GMT
{
   "timestamp": "2017-03-01T18:48:21.894+0000",
   "status": 403,
   "error": "Forbidden",
   "exception": "com.myapp.MyException",
   "message": "You are not authorized. This user doesn't exist in the db",
   "path": "/account",
   "errorCode": "00013"
}

推荐答案

我找到了一种从创建自定义 ErrorAttributes bean 的逻辑中设置 http 状态的方法,这样我就可以重用框 Spring Boot 错误响应创建并使用我的自定义信息更新它,而无需异常处理程序和控制器建议.

I found a way of setting the http status from within the logic that creates my custom ErrorAttributes bean, this way I am able to re-use the out of the box Spring Boot error response creation and update it with my custom information without the need of exception handlers and controller advices.

通过添加下一行,您可以设置覆盖 requestAttributes 中当前状态的 http 状态.

By adding the next line you can set the http status which overrides the current one in the requestAttributes.

requestAttributes.setAttribute("javax.servlet.error.status_code", httpStatus, 0);

其中 httpStatus 是您要设置的状态.

Where httpStatus is the status you want to set.

这是添加了一行的完整 bean 定义:

Here is the full bean definition with the added line:

@Bean
public ErrorAttributes errorAttributes() {
    return new DefaultErrorAttributes() {
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {

            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);

            Throwable error = getError(requestAttributes);

            if (error instanceof MyException) {
                MyException myException = (MyException) error;
                int httpStatus = myException.getStatus();

                errorAttributes.put("errorCode", myException.getErrorCode());
                errorAttributes.put("message", myException.getMessage());
                errorAttributes.put("status", httpStatus);

                HttpStatus correspondentStatus = HttpStatus.valueOf(httpStatus);
                errorAttributes.put("error", correspondentStatus.getReasonPhrase());
                requestAttributes.setAttribute("javax.servlet.error.status_code", httpStatus, 0);
            }

            return errorAttributes;
        }
    };
}

我是怎么找到的?通过查看 DefaultErrorAttributes 类,我发现有一个私有方法 addStatus,但它显示了代码用于生成响应的 http-status 的属性的名称,这就是我正在寻找的线索:

How did I find it? By looking at the DefaultErrorAttributes class, I found there is a method addStatus which is private, but it shows the name of the attribute that is used by the code to generate the response's http-status, that was the clue I was looking for:

private void addStatus(Map<String, Object> errorAttributes, RequestAttributes requestAttributes) {
    Integer status = (Integer)this.getAttribute(requestAttributes, "javax.servlet.error.status_code");
...

查看更多代码,我发现正在调用的 getAttribute 方法实际上是从 RequestAttributes 接口调用该方法:

Looking more into the code I found that the getAttribute method that is being called there is actually calling the method from RequestAttributes interface:

private <T> T getAttribute(RequestAttributes requestAttributes, String name) {
    return requestAttributes.getAttribute(name, 0);
}

检查该接口内部,我发现还有一个 setAttribute 方法.成功了.

Checking inside that interface I found there is also a setAttribute method. It worked.

HTTP/1.1 403
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 01 Mar 2017 20:59:33 GMT
{
   "timestamp": "2017-03-01T20:59:32.774+0000",
   "status": 403,
   "error": "Forbidden",
   "exception": "com.myapp.MyException",
   "message": "You are not authorized. This user doesn't exist in the db",
   "path": "/account",
   "errorCode": "00013"
}

这篇关于Spring Boot 自定义 ErrorAttributes http 状态未设置为响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 06:18