如何处理 Spring Boot 重定向到 /error?

Posted

技术标签:

【中文标题】如何处理 Spring Boot 重定向到 /error?【英文标题】:How to handle Spring Boot's redirection to /error? 【发布时间】:2016-03-22 23:40:18 【问题描述】:

我遇到了与 this question 中相同的问题,使用 Spring Boot 1.3.0 并且没有使用 @RestController 注释我的控制器,只是 @Path@Service。正如该问题中的 OP 所说,

对我来说,这绝不是明智的

我也无法理解他们为什么要将它重定向到 /error。而且我很可能遗漏了什么,因为我只能将 404 或 200 还给客户​​。

我的问题是他的解决方案似乎不适用于 1.3.0,所以我有以下请求流程:假设我的代码抛出了 NullPointerException。它将由我的ExceptionMappers 之一处理

@Provider
public class GeneralExceptionMapper implements ExceptionMapper<Throwable> 

    private static final Logger LOGGER = LoggerFactory.getLogger(GeneralExceptionMapper.class);

    @Override
    public Response toResponse(Throwable exception) 
        LOGGER.error(exception.getLocalizedMessage());
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    

我的代码返回 500,但它没有将其发送回客户端,而是尝试将其重定向到 /error。如果我没有其他资源,它会发回 404。

2015-12-16 18:33:21.268  INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 1 * Server has received a request on thread http-nio-8080-exec-1
1 > GET http://localhost:8080/nullpointerexception
1 > accept: */*
1 > host: localhost:8080
1 > user-agent: curl/7.45.0

2015-12-16 18:33:29.492  INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 1 * Server responded with a response on thread http-nio-8080-exec-1
1 < 500

2015-12-16 18:33:29.540  INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 2 * Server has received a request on thread http-nio-8080-exec-1
2 > GET http://localhost:8080/error
2 > accept: */*
2 > host: localhost:8080
2 > user-agent: curl/7.45.0

2015-12-16 18:33:37.249  INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 2 * Server responded with a response on thread http-nio-8080-exec-1
2 < 404

和客户端(卷曲):

$ curl -v http://localhost:8080/nullpointerexception
* STATE: INIT => CONNECT handle 0x6000572d0; line 1090 (connection #-5000)
* Added connection 0. The cache now contains 1 members
*   Trying ::1...
* STATE: CONNECT => WAITCONNECT handle 0x6000572d0; line 1143 (connection #0)
* Connected to localhost (::1) port 8080 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000572d0; line 1240 (connection #0)
* STATE: SENDPROTOCONNECT => DO handle 0x6000572d0; line 1258 (connection #0)
> GET /nullpointerexception HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.45.0
> Accept: */*
>
* STATE: DO => DO_DONE handle 0x6000572d0; line 1337 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x6000572d0; line 1464 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x6000572d0; line 1474 (connection #0)
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 404 Not Found
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Content-Length: 0
< Date: Wed, 16 Dec 2015 17:33:37 GMT
<
* STATE: PERFORM => DONE handle 0x6000572d0; line 1632 (connection #0)
* Curl_done
* Connection #0 to host localhost left intact

所以它总是 404。除非我确实有这样的 /error 资源,否则怎么办?我应该返回什么?那时我所拥有的只是对 /error 的 GET 请求。而且我不希望那些额外的请求消耗资源并污染我的日志。

我错过了什么?如果没有,我应该如何处理我的异常?

【问题讨论】:

【参考方案1】:

您可以将 Jersey 属性 ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR 设置为 true

只要响应状态为4xx5xx,就可以在容器特定的响应实现上选择sendErrorsetStatus。例如。在 servlet 容器上 Jersey 可以调用 HttpServletResponse.setStatus(...)HttpServletResponse.sendError(...)

调用sendError(...) 方法通常会重置实体、响应标头并提供指定状态码的错误页面(例如servlet error-page 配置)。但是,如果您想对响应进行后处理(例如通过 servlet 过滤器),唯一的方法是在容器响应对象上调用 setStatus(...)

如果属性值为 true,则使用方法 Response.setStatus(...) 而不是默认的 Response.sendError(...)

属性值的类型是boolean。默认值为false

您只需在 ResourceConfig 子类构造函数中调用 property(key, value) 即可设置 Jersey 属性。

【讨论】:

以上是关于如何处理 Spring Boot 重定向到 /error?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理“太多 HTTP 重定向”错误

如何处理 Codeigniter 上的多语言 uri 重定向?

Service Worker:如何处理 302 重定向响应

python requests库如何处理302重定向?

如何处理表单提交而不对用户可见重定向

如何处理 C++ 重定向进程的输出