2.3.3. doTry、doCatch 和 lastly

概述

要在路由内部处理异常,您可以使用 doTrydoCatchdoFinally 子句的组合,该子句以类似于 Java 的 尝试捕获最终 块的方式处理异常。

doCatch 和 Java 捕获之间的相似性

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

  • 在单一 do Try 块中可以有多个 doCatch 子句,其中有多个 doCatch 子句。doCatch 子句按照它们显示的顺序进行测试,就像 Java catch () 语句一样。Apache Camel 执行与引发异常匹配的第一个 doCatch 子句。

    注意

    这个算法与 Exception 子句计算机上计算机上使用 的异常匹配算法不同,请参阅 第 2.3.1 节 “onException Clause” 了解详细信息。

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

doCatch 的特殊功能

但是,doCatch () 子句有一些特殊功能,但在 Java catch () 语句中没有模拟。以下功能专用于 doCatch ()

Example

以下示例演示了如何在 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 中,或等效于 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,则当前交换将发送到 mock: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>

使用 onWhen 捕获条件异常

Apache Camel doCatch () 子句的一个特殊功能是您可以根据运行时评估的表达式对异常进行破坏。换句话说,如果您使用表格的子句捕获异常,那么 doCatch (ExceptionList).doWhen ( Expression ) 只会在运行时捕获异常(如果 predicate 表达式,表达式 )评估为 true

例如,只有异常消息中包含该异常时,以下 doTry 块会捕获异常 IOExceptionIllegalStateException

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 中,或等效于 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>

doTry 中的嵌套条件

有不同的选项可用于将 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();