Camel使用onException捕获路由异常时如何获取异常抛出的具体位置
解决方案
你可以通过Camel内置的Exchange属性、自定义标识两种方式快速定位异常来源,无需在每个调用节点单独加try-catch:
方法1:直接使用Camel内置的异常跟踪属性
Camel触发onException时,会自动把异常相关的上下文信息存入Exchange的属性中,你在ExceptionListener的process方法里可以直接读取:
Exchange.FAILURE_ENDPOINT:返回异常抛出时正在调用的端点URI,比如调用xyz服务时该值为你配置的对应端点地址(如http://xxx/xyz)、调用Bean时为bean:xxxBean格式,直接解析该值就能区分不同的服务调用场景。Exchange.FAILURE_ROUTE_ID:返回异常发生所在的路由ID,适合跨路由的错误来源区分。Exchange.FAILURE_NODE_ID:返回异常抛出的路由节点ID,如果你给节点设置了自定义id可以直接匹配。
示例代码如下:
public class ExceptionListener implements Processor { @Override public void process(Exchange exchange) throws Exception { // 获取异常实例 Exception e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); // 获取出错的端点 String failEndpoint = exchange.getProperty(Exchange.FAILURE_ENDPOINT, String.class); // 按端点区分处理逻辑 if (failEndpoint.contains("xyz")) { // 服务xyz报错处理逻辑 } else if (failEndpoint.contains("abc")) { // 服务abc报错处理逻辑 } else if (failEndpoint.startsWith("bean")) { // Bean调用报错处理逻辑 } } }
注:你原示例代码中的
onException(Excepction.class)存在拼写错误,正确写法为Exception.class。
方法2:自定义错误来源标识
如果端点规则复杂不好解析,你可以在每个需要区分的调用节点前添加一行自定义Header/Property,标识当前调用的来源,该值会在异常触发时保留在Exchange中:
路由配置示例:
// 调用xyz服务前加标识 .setHeader("errorSource", constant("service_xyz")) .to("http://xxx/xyz") // 调用abc服务前加标识 .setHeader("errorSource", constant("service_abc")) .to("http://xxx/abc") // 调用Bean前加标识 .setHeader("errorSource", constant("bean_xxx")) .bean(XXXBean.class)
之后在ExceptionListener里直接读取该Header即可区分场景:
String errorSource = exchange.getIn().getHeader("errorSource", String.class);
这种方式的匹配逻辑更清晰,也不会让路由代码变得臃肿,仅比原有配置多一行设置Header的代码。
内容的提问来源于stack exchange,提问作者Marc
相关产品推荐
相关产品推荐

