WebClient onStatus方法抛出的自定义异常无法被对应catch块捕获
问题根因
自定义异常无法被精准捕获,核心是3个问题:
- Reactor响应式异常包装机制:WebClient底层基于Reactor实现,如果你定义的
AuthException是受检异常(直接继承Exception而非RuntimeException),通过Mono.error()抛出时会被Reactor自动包装为运行时异常抛出,外层catch匹配不到原生AuthException类型。 - 调用链路写错:你贴的
getResponse方法try块中调用的是randomService.getResponse(request),根本没有调用包含WebClient逻辑的returnResponse方法,异常不会进入当前try-catch链路。 - 代码笔误导致分支不触发:
onStatus里的401判断写的是if(401)属于无效判断,永远不会进入抛AuthException的分支;另外还有BodyInserters.formatValue不存在、new AuthException("traceid)字符串未闭合的语法错误。
排查方向
- 检查
AuthException的继承关系,确认是否为受检异常 - 梳理调用链路,确认外层try块实际调用了WebClient请求方法
- 在通用Exception捕获分支打印异常栈和
e.getCause(),确认是否存在被包装的AuthException - 校验onStatus中的状态码判断逻辑,确认401场景确实能走到抛自定义异常的分支
正确实现
- 调整自定义异常为运行时异常,避免被Reactor自动包装
public class AuthException extends RuntimeException { public AuthException(String message) { super(message); } }
- 修正WebClient请求逻辑,补全正确判断,增加异常解包处理
public String returnResponse(String request){ return webclient.post() .uri("目标接口地址") .header("头名称","头值") .body(BodyInserters.fromValue(request)) .retrieve() .onStatus(HttpStatus::is4xxClientError, clientRes -> { // 正确判断401状态码 if(clientRes.statusCode().equals(HttpStatus.UNAUTHORIZED)){ return Mono.error(new AuthException("traceid")); } return Mono.error(new InternalServerError("客户端请求异常")); }) .bodyToMono(String.class) // 异常解包,避免被Reactor包装后类型不匹配 .onErrorMap(e -> e.getCause() instanceof AuthException ? e.getCause() : e) .block(); }
- 修正外层调用逻辑,补全兜底的异常类型判断
public String getResponse(String request){ try{ // 调用正确的WebClient请求方法 return returnResponse(request); }catch(AuthException e){ throw new AuthException(e.getMessage()); }catch(Exception e){ // 兜底处理可能存在的包装异常 if(e.getCause() instanceof AuthException authEx){ throw authEx; } throw new InternalServerError(e.getMessage()); } }
补充说明:如果因为业务约束不能把AuthException改成运行时异常,保留上述代码中的
onErrorMap解包和catch块的cause判断逻辑,也可以实现自定义异常的精准捕获。
内容的提问来源于stack exchange,提问作者Esh
相关产品推荐
相关产品推荐

