2.3.3. doTry、doCatch 和最后执行

概述

要在路由内处理异常,您可以使用 doTrydoCatchdo lastly 子句的组合,以类似 Java 的 尝试捕获最后 块处理异常。

doCatch 和 Java catch 之间的相似性

通常,路由定义中的 doCatch() 子句的行为与 Java 代码中的 catch() 语句类似。特别是,doCatch() 子句支持以下功能:

  • 多个 doCatch 子句 s IFL-时间可以在单个 doTry 块内拥有多个 doCatch 子句。doCatch 子句按显示的顺序进行测试,就像 Java catch() 语句一样。Apache Camel 执行与引发 异常匹配的第一个 doCatch 子句。

    注意

    这个算法与 onException 子句的匹配算法所使用的异常匹配算法不同,详情请参阅 第 2.3.1 节 “onException Clause”

  • 使用 结构(请参阅 “在 doCatch 中排放例外”一节)在 doCatch 子句中重新增加例外情况。

doCatch 的特殊特性

但是,doCatch() 子句的一些特殊功能在 Java catch() 语句中没有类似。以下功能特定于 doCatch()

示例

以下示例演示了如何在 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 of handled(false) which is deprecated in a doTry/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 块将捕获异常、IOExceptionIllegalStateException,仅当异常消息包含单词时,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();