异常子句
Exception Clause
你可以在 Java DSL 中使用异常子句(Exception Clause),通过 onException() 方法针对每种异常类型指定所需的错误处理方式。在深入讲解其工作原理之前,我们先给出一个简单的示例。
例如,如果你想在抛出某个特定异常时执行一段特定的处理逻辑,只需这样即可:
- Java
- XML
- YAML
onException(ValidationException.class)
.to("activemq:validationFailed");
from("seda:inputA")
.to("validation:foo/bar.xsd", "activemq:someQueue");
from("seda:inputB")
.to("direct:foo")
.to("rnc:mySchema.rnc", "activemq:anotherQueue");<onException>
<exception>org.apache.camel.ValidationException</exception>
<to uri="activemq:validationFailed"/>
</onException>
<route>
<from uri="seda:inputA"/>
<to uri="validation:foo/bar.xsd"/>
<to uri="activemq:someQueue"/>
</route>
<route>
<from uri="seda:inputB"/>
<to uri="direct:foo"/>
<to uri="rnc:mySchema.rnc"/>
<to uri="activemq:anotherQueue"/>
</route>- onException:
exception:
- org.apache.camel.ValidationException
steps:
- to:
uri: activemq:validationFailed
- route:
from:
uri: seda:inputA
steps:
- to:
uri: validation:foo/bar.xsd
- to:
uri: activemq:someQueue
- route:
from:
uri: seda:inputB
steps:
- to:
uri: direct:foo
- to:
uri: rnc:mySchema.rnc
- to:
uri: activemq:anotherQueue如果处理 seda:inputA 或 seda:inputB 时抛出 ValidationException(例如由 Validation 组件进行 XSD 校验所导致),那么该消息将被发送到 activemq:validationFailed 队列。
你可以定义多个 onException 子句来实现不同的行为:
- Java
- XML
- YAML
onException(ValidationException.class)
.to("activemq:validationFailed");
onException(com.foo.ShipOrderException.class)
.to("activemq:shipFailed");
from("seda:order")
.to("bean:processOrder");<onException>
<exception>org.apache.camel.ValidationException</exception>
<to uri="activemq:validationFailed"/>
</onException>
<onException>
<exception>com.foo.ShipOrderException</exception>
<to uri="activemq:shipFailed"/>
</onException>
<route>
<from uri="seda:order"/>
<to uri="bean:processOrder"/>
</route>- onException:
exception:
- org.apache.camel.ValidationException
steps:
- to:
uri: activemq:validationFailed
- onException:
exception:
- com.foo.ShipOrderException
steps:
- to:
uri: activemq:shipFailed
- route:
from:
uri: seda:order
steps:
- to:
uri: bean:processOrder作用域
异常子句的作用域分为两类:
- 全局(对 Java DSL 而言,即每个
RouteBuilder实例的作用域,用于复用,见下方说明) - 或路由特定
其中全局作用域最为简单,也最容易理解。在进阶章节中,我们会深入讲解路由特定的用法,甚至将两者结合使用。不过——
Java DSL 的全局作用域是按 RouteBuilder 实例划分的,因此如果你想在多个 RouteBuilder 类之间共享,可以创建一个抽象的 RouteBuilder 基类,把错误处理逻辑放在它的 configure 方法中。然后让其他类继承该类,并确保调用 super.configure()。这只是在运用 Java 的继承技术。
Camel 如何选择由哪个子句处理抛出的异常?
Camel 使用 DefaultExceptionPolicyStrategy 来决定抛出的异常应由哪个 onException 子句处理。该策略如下:
onException的配置顺序具有优先级。Camel 会按定义的先后顺序(从第一个…到最后一个)依次测试。- Camel 会从最底层(嵌套的 caused by)开始,在异常层次结构中逐级向上递归查找,直到找到第一个匹配的
onException子句。 - 测试给定异常是否匹配
onException子句所定义的异常列表时,使用instanceof测试。如果存在精确的instanceof匹配,则始终采用该匹配;否则,将选择其定义的异常是所抛出异常最近的父类的那个onException子句(沿异常层次结构递归向上)。
下面通过一个例子来说明最为清楚:
仅限 Java:异常策略的选择顺序
onException(IOException.class)
.maximumRedeliveries(3);
onException(OrderFailedException.class)
.maximumRedeliveries(2);在上面的示例中,我们定义了两个异常,其中 IOException 位于第一位,因此一旦发生匹配,Camel 就会捕获该异常。也就是说,范围更广的 IOException 会被优先选中。
因此,如果抛出的异常具有如下继承层次:
+ RuntimeCamelException (wrapper exception by Camel)
+ OrderFailedException
+ IOException
+ FileNotFoundException然后 Camel 将按以下顺序尝试测试异常:FileNotFoundException、IOException、OrderFailedException 和 RuntimeCamelException。由于我们定义了 onException(IOException.class),Camel 会选择它,因为这是最接近的匹配。
如果我们添加第三个带有 FileNotFoundException 的 onException 子句:
仅 Java:添加更具体的异常子句
onException(IOException.class)
.maximumRedeliveries(3);
onException(OrderFailedException.class)
.maximumRedeliveries(2);
onException(FileNotFoundException.class)
.handled(true)
.to("log:nofile");接着,在前面的示例中,Camel 将使用最后一个 onException(FileNotFoundException.class),因为它是精确匹配。由于这是精确匹配,它将覆盖之前用于处理同一异常的通用 IOException。
现在考虑一种新情况,如果抛出的是这个异常:
+ RuntimeCamelException (wrapper exception by Camel)
+ OrderFailedException
+ OrderNotFoundException那么将会选中 onException(OrderFailedException.class)——这一点毫不意外。
下面这个示例演示了 instanceof 测试的特性:当异常是 onException 子句中所定义异常的实例时,Camel 将会选中该子句。示例如下:
+ RuntimeCamelException (wrapper exception by Camel)
+ SocketException由于 SocketException 是 IOException 的 instanceof,Camel 将选择 onException(IOException.class) 子句。
更多信息
有关特定主题的详细文档,请参阅以下子页面:
评论
登录后参与评论
KnowForge