Spring Cloud Gateway端点超时后Post过滤器未执行问题咨询
问题分析与解决方案
这是Spring Cloud Gateway的预期行为
当端点返回4xx/5xx时,chain.filter(exchange)会正常完成(后端返回了合法响应),因此你通过.then()绑定的Post逻辑会执行。但504网关超时是HttpClient层面触发的异常,此时chain.filter(exchange)会以异常终止,而.then()仅在前置Mono成功完成时才会执行,所以你的Post过滤器逻辑不会被触发——这属于框架的预期行为,并非缺陷。
解决方案:改用doFinally替代then
要让Post过滤器在所有场景(包括超时、异常)下都执行,需要将.then()替换为.doFinally(),它会在Mono生命周期结束时(无论成功、失败、取消)触发逻辑。修改后的过滤器代码如下:
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange) .doFinally(signalType -> { final ResponseCookie resCookie = ResponseCookie.from(this.cookieName, "invalidated") .httpOnly(true) .secure(true) .path("/") .maxAge(0) .build(); // 避免响应已提交时修改响应抛出异常 if (!exchange.getResponse().isCommitted()) { exchange.getResponse().addCookie(resCookie); } }); } @Override public int getOrder() { return POST_FILTER_BASE_ORDER - 3; // POST_FILTER_BASE_ORDER = 1000 }
补充说明
- 添加
!exchange.getResponse().isCommitted()判断,是为了防止在响应已经发送到客户端后尝试修改响应(会触发异常)。 doFinally中的逻辑必须是非阻塞的,符合Reactor编程模型要求。
其他可选方案(针对超时做特殊处理)
如果需要对超时异常单独处理,可以结合onErrorResume捕获超时异常,再执行通用Post逻辑:
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange) .onErrorResume(TimeoutException.class, ex -> { // 这里可添加超时专属处理逻辑 return Mono.error(ex); }) .doFinally(signalType -> { final ResponseCookie resCookie = ResponseCookie.from(this.cookieName, "invalidated") .httpOnly(true) .secure(true) .path("/") .maxAge(0) .build(); if (!exchange.getResponse().isCommitted()) { exchange.getResponse().addCookie(resCookie); } }); }
内容的提问来源于stack exchange,提问作者Deepak Chhetri
相关产品推荐
相关产品推荐

