2.3.3. doTry、doCatch 和最后执行
概述
要在路由内处理异常,您可以使用 doTry
、doCatch
和 do lastly
子句的组合,以类似 Java 的 尝试
、捕获
和 最后
块处理异常。
doCatch 和 Java catch 之间的相似性
通常,路由定义中的 doCatch()
子句的行为与 Java 代码中的 catch()
语句类似。特别是,doCatch()
子句支持以下功能:
多个 doCatch 子句 s IFL-时间可以在单个
doTry
块内拥有多个doCatch
子句。doCatch
子句按显示的顺序进行测试,就像 Javacatch()
语句一样。Apache Camel 执行与引发 异常匹配的第一个doCatch
子句。注意这个算法与
onException
子句的匹配算法所使用的异常匹配算法不同,详情请参阅 第 2.3.1 节 “onException Clause”。-
使用 结构(请参阅 “在 doCatch 中排放例外”一节)在
doCatch
子句中重新增加例外情况。
doCatch 的特殊特性
但是,doCatch()
子句的一些特殊功能在 Java catch()
语句中没有类似。以下功能特定于 doCatch()
:
-
通过向 doCatch 子句附加
onWhen
sub-clause to thedoCatch
子句(请参阅 “使用 When 捕获条件异常”一节)可以有 条件捕获 异常捕获(请参阅 )。
示例
以下示例演示了如何在 Java DSL 中写入 doTry
块,执行 doCatch()
子句的位置,如果 IOException
异常或 IllegalStateException
异常进行引发,并且会 始终执行 doFinally()
子句,无论是否引发异常,是否引发异常。
from("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class, IllegalStateException.class) .to("mock:catch") .doFinally() .to("mock:finally") .end();
或者,在 Spring XML 中:
<route> <from uri="direct:start"/> <!-- here the try starts. its a try .. catch .. finally just as regular java code --> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <!-- catch multiple exceptions --> <exception>java.io.IOException</exception> <exception>java.lang.IllegalStateException</exception> <to uri="mock:catch"/> </doCatch> <doFinally> <to uri="mock:finally"/> </doFinally> </doTry> </route>
在 doCatch 中排放例外
可以使用构造在 doCatch ()
子句中重新增加异常,如下所示:
from("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class) .to("mock:io") // Rethrow the exception using a construct instead ofhandled(false)
which is deprecated in adoTry/doCatch
clause. .throwException(new IllegalArgumentException("Forced")) .doCatch(Exception.class) // Catch all other exceptions. .to("mock:error") .end();
您还可以使用在 doTry/doCatch
子句中弃用的处理器 (false)
来重新增加异常:
.process(exchange -> {throw exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);})
在前面的示例中,如果 doCatch()
可以发现 IOException
,则当前交换将发送到 模拟:io
端点,然后重新进行 IOException
。这会在路由开始时(在 from()
命令中)为使用者端点提供处理异常的机会。
以下示例演示了如何在 Spring XML 中定义相同的路由:
<route> <from uri="direct:start"/> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <to uri="mock:io"/> <throwException message="Forced" exceptionType="java.lang.IllegalArgumentException"/> </doCatch> <doCatch> <!-- Catch all other exceptions. --> <exception>java.lang.Exception</exception> <to uri="mock:error"/> </doCatch> </doTry> </route>
使用 When 捕获条件异常
Apache Camel doCatch()
子句的一个特殊功能是,您可以根据运行时评估的表达式来对异常的捕获进行条件化。换而言之,如果您使用表的条款捕获一个异常,则 doCatch(ExceptionList).doWhen(Expression)
.doWhen( Expression )只会被发现,如果 predicate 表达式、表达式、在运行时评估为 true
。
例如,以下 doTry
块将捕获异常、IOException
和 IllegalStateException
,仅当异常消息包含单词时,Sever e
:
from("direct:start")
.doTry()
.process(new ProcessorFail())
.to("mock:result")
.doCatch(IOException.class, IllegalStateException.class)
.onWhen(exceptionMessage().contains("Severe"))
.to("mock:catch")
.doCatch(CamelExchangeException.class)
.to("mock:catchCamel")
.doFinally()
.to("mock:finally")
.end();
或者,在 Spring XML 中:
<route> <from uri="direct:start"/> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <exception>java.io.IOException</exception> <exception>java.lang.IllegalStateException</exception> <onWhen> <simple>${exception.message} contains 'Severe'</simple> </onWhen> <to uri="mock:catch"/> </doCatch> <doCatch> <exception>org.apache.camel.CamelExchangeException</exception> <to uri="mock:catchCamel"/> </doCatch> <doFinally> <to uri="mock:finally"/> </doFinally> </doTry> </route>
嵌套条件
可以选择将 Camel 异常处理添加到 JavaDSL 路由。dotry()
创建尝试或捕获块来处理异常,对于特定于路由的错误处理非常有用。
如果要捕获 ChoiceDefinition
内的异常,您可以使用以下 doTry
块:
from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut) .doTry() .to("https4://wayne-token-service") .choice() .when().simple("${header.CamelHttpResponseCode} == '200'") .convertBodyTo(String.class) .setHeader("wayne-token").groovy("body.replaceAll('\"','')") .log(">> Wayne Token : ${header.wayne-token}") .endChoice() .doCatch(java.lang.Class (java.lang.Exception>) .log(">> Exception") .endDoTry(); from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut) .doTry() .to("https4://wayne-token-service") .doCatch(Exception.class) .log(">> Exception") .endDoTry();