Spring Webflux中WebClient的onStatus无法处理下游返回406问题问询
问题原因及解决方案
核心原因
406状态码未被onStatus捕获的常见原因有以下3种,按出现概率从高到低排序:
1. 全局默认状态处理器覆盖了单请求配置
如果你在构建WebClient全局实例时,通过defaultStatusHandler方法提前配置了4xx状态码的处理逻辑,单请求声明的onStatus规则会被全局配置覆盖,导致自定义规则不生效。
注意:Spring WebClient的全局默认状态处理器优先级高于单请求的
onStatus配置,相同状态码匹配规则下会优先执行全局处理逻辑。
2. 406响应触发了提前的解码异常
406 Not Acceptable本身代表下游无法返回符合请求Accept头的响应格式,此时下游返回的Content-Type通常和你期望接收的类型不匹配。如果你的WebClient配置了强制校验响应媒体类型,会在onStatus执行前抛出UnsupportedMediaTypeException,直接绕过状态码匹配逻辑。
3. 状态码匹配规则顺序错误
如果你配置了多个onStatus规则,更具体的状态码匹配(比如单独匹配406的规则)写在了通用4xx匹配规则之前,且该规则的处理逻辑没有抛出你自定义的异常,就会导致通用4xx规则不生效。
验证修复方案
你可以按以下步骤排查修复:
- 检查
WebClient实例构建代码,确认没有配置defaultStatusHandler处理4xx状态码,如果有需要删除或者调整全局逻辑 - 调用
retrieve()后立刻声明onStatus规则,确保顺序在bodyToMono/bodyToFlux之前:
// 正确写法 webClient.get() .uri("/your/api") .retrieve() // 先声明onStatus规则 .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new AcceptHeaderNotsupportedException()) ) // 再声明响应体转换逻辑 .bodyToMono(YourDto.class);
- 显式在请求头添加
Accept: */*临时测试,如果406此时可以触发自定义异常,说明是媒体类型校验导致的提前报错,你可以通过在WebClient构建时添加自定义解码器兼容更多媒体类型解决。
内容的提问来源于stack exchange,提问作者Lucho82
相关产品推荐
相关产品推荐

