Apache Camel指南-第四章:路由径构建之异常处理

摘要

Apache的骆驼提供几种不同的机制,让您在处理不同的粒度级别的例外:您可以通过处理一个路线中的异常doTrydoCatch以及doFinally; 或者您可以指定要采取什么行动每种类型的异常,并应用此规则的所有路由RouteBuilder使用onException; 或者,您可以指定对所有 异常类型采取何种操作,并将此规则应用于RouteBuilderusing中的所有路由errorHandler

onException子句

概览

onException子句是一种用于捕获一条或多条路由中发生的异常的强大机制:它是特定于类型的,使您可以定义不同的操作来处理不同的异常类型;它允许您使用与路由基本相同的(实际上是稍微扩展的)语法来定义动作,从而在处理异常的方式上具有相当大的灵活性。它基于陷阱模型,该模型使单个onException子句能够处理在任何路由中的任何节点上发生的异常。

使用onException捕获异常

onException子句是用于捕获 而不是捕获异常的机制。也就是说,一旦定义了onException子句,它就会捕获路由中任何点发生的异常。这与Java try / catch机制形成对比,在Java try / catch机制中,只有将特定的代码片段显式包含在try块中,才会捕获异常。

定义onException子句时真正发生的是,Apache Camel运行时将每个路由节点隐式地包含在try块中。这就是该onException子句能够在路由的任何点捕获异常的原因。但是这种包装是自动为您完成的;在路由定义中不可见。

Java DSL示例

在以下Java DSL示例中,该onException子句适用于RouteBuilder该类中定义的所有路由。如果ValidationException在处理任何一条路由(from("seda:inputA")from("seda:inputB"))时发生异常,则该onException子句将捕获该异常并将当前交换重定向到validationFailedJMS队列(用作死信队列)。

java 复制代码
// Java
public class MyRouteBuilder extends RouteBuilder {

  public void configure() {
    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");
  }
}
XML DSL示例

前面的示例也可以使用XML DSL来表达,使用onException元素来定义exception子句,如下所示:

xml 复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <onException>
            <exception>com.mycompany.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="rnc:mySchema.rnc"/>
            <to uri="activemq:anotherQueue"/>
        </route>
    </camelContext>

</beans>
捕获多个异常

您可以定义多个onException子句以在RouteBuilder范围中捕获异常。这使您可以针对不同的异常采取不同的措施。例如,下面的系列onException在Java DSL定义的条款定义不同的死信目的地ValidationExceptionIOException以及Exception

java 复制代码
onException(ValidationException.class).to("activemq:validationFailed");
onException(java.io.IOException.class).to("activemq:ioExceptions");
onException(Exception.class).to("activemq:exceptions");

您可以onException在XML DSL中定义相同的一系列子句,如下所示:

xml 复制代码
<onException>
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>
<onException>
    <exception>java.io.IOException</exception>
    <to uri="activemq:ioExceptions"/>
</onException>
<onException>
    <exception>java.lang.Exception</exception>
    <to uri="activemq:exceptions"/>
</onException>

您还可以将多个异常分组在一起,以被同一onException子句捕获。在Java DSL中,可以将多个异常分组如下:

java 复制代码
onException(ValidationException.class, BuesinessException.class)
  .to("activemq:validationFailed");

在XML DSL中,可以通过在exception元素内定义多个元素来将多个异常组合在一起onException,如下所示:

java 复制代码
<onException>
    <exception>com.mycompany.ValidationException</exception>
    <exception>com.mycompany.BuesinessException</exception>
    <to uri="activemq:validationFailed"/>
</onException>

当捕获多个异常时,onException子句的顺序很重要。Apache Camel最初尝试将抛出的异常与第一个 子句进行匹配。如果第一个子句不匹配,onException则尝试下一个子句,依此类推,直到找到匹配项。每次匹配尝试均由以下算法控制:

  1. 如果抛出的异常是链式异常(也就是说,已捕获异常并将其作为另一个异常重新抛出),则嵌套最丰富的异常类型最初将用作匹配的基础。测试此异常的方法如下:
    1. 如果要测试的异常具有在onException子句中指定的类型(使用进行了测试instanceof),则会触发匹配。
    2. 如果要测试的异常是onException子句中指定的类型的子类型,则会触发匹配。
  2. 如果嵌套最多的异常无法产生匹配项,则将测试链中的下一个异常(包装异常)。测试将一直沿链条进行,直到触发匹配或链条耗尽为止。

注意

throwException EIP使您可以通过简单的语言表达式创建新的异常实例。您可以根据当前交易所的可用信息来使其动态化。例如,

xml 复制代码
<throwException exceptionType="java.lang.IllegalArgumentException" message="${body}"/>
死信通道

onException到目前为止 ,用法的基本示例都利用了死信通道 模式。也就是说,当onException子句捕获异常时,当前交换将路由到特殊的目的地(死信通道)。所述死信通道充当已经失败的消息的保持区域被处理。管理员可以在以后检查消息,并确定需要采取的措施。

使用原始消息

到路由中间出现异常时,交换中的消息可能已经被重大修改(甚至可能无法被人类读取)。通常,如果在死信队列中可见的消息是原始 消息(如在路由开始时收到的消息),则管理员可以更容易地决定采取何种纠正措施。该useOriginalMessage选项是false默认选项,但是如果在错误处理程序上配置了该选项,则会自动启用。

注意
当该useOriginalMessage选项应用于将消息发送到多个端点或将消息拆分为多个部分的骆驼路由时,该选项可能导致意外行为。原始消息可能不会保留在"多播","拆分器"或"收件人列表"路由中,在这些路由中,中间处理步骤会修改原始消息。

在Java DSL中,您可以将交换中的消息替换为原始消息。将设置setAllowUseOriginalMessage()true,然后使用useOriginalMessage()DSL命令,如下所示:

java 复制代码
onException(ValidationException.class)
  .useOriginalMessage()
  .to("activemq:validationFailed");

在XML DSL中,可以通过useOriginalMessageonException元素上设置属性来检索原始消息,如下所示:

xml 复制代码
<onException useOriginalMessage="true">
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>

注意
如果将该setAllowUseOriginalMessage()选项设置为true,Camel会在路由开始时复制原始消息,以确保在致电时原始消息可用useOriginalMessage()。但是,如果在Camel上下文中将该setAllowUseOriginalMessage()选项设置为false(这是默认设置),则将无法 访问原始消息,并且您无法调用useOriginalMessage()

利用默认行为的原因是在处理大型消息时优化性能。

在2.18之前的Camel版本中,默认设置allowUseOriginalMessage为true。

重试策略

Apache Camel可以让您选择尝试在发生异常的时刻重新传递消息,而不用中断消息的处理并在引发异常时立即放弃。在网络系统中,可能会发生超时并出现临时故障,如果失败的消息在引发原始异常后不久重新发送,则通常有可能成功处理失败的消息。

Apache Camel重新交付支持各种发生异常后重新传递消息的策略。配置重新交付的一些最重要的选项如下:

  • maximumRedeliveries()

    指定可以尝试重新传送的最大次数(默认为0)。负值表示始终尝试重新交付(相当于无限值)。

  • retryWhile()

    指定一个谓词(Predicate类型),该谓词确定Apache Camel是否应继续重新传递。如果谓词true在当前交换上评估为,则尝试重新交付;否则,将重新交付。否则,将停止重新交付,并且不会进行进一步的重新交付尝试。此选项优先于该maximumRedeliveries()选项。

在Java DSL中,使用onException子句中的DSL命令指定重新交付策略选项。例如,您最多可以指定六个重新交付,然后将交换发送到validationFailed死信队列,如下所示:

java 复制代码
onException(ValidationException.class)
  .maximumRedeliveries(6)
  .retryAttemptedLogLevel(org.apache.camel.LogginLevel.WARN)
  .to("activemq:validationFailed");

在XML DSL中,通过在redeliveryPolicy元素上设置属性来指定重新交付策略选项。例如,前面的路由可以在XML DSL中表示如下:

java 复制代码
<onException useOriginalMessage="true">
    <exception>com.mycompany.ValidationException</exception>
    <redeliveryPolicy maximumRedeliveries="6"/>
    <to uri="activemq:validationFailed"/>
</onException>

路由的后半部分(设置了重新交付选项之后)直到最后一次重新交付尝试失败后才进行处理。

或者,您可以在redeliveryPolicyProfile实例中指定重新交付策略选项。然后,您可以redeliveryPolicyProfile使用onException元素的redeliverPolicyRef属性来引用实例。例如,前面的路由可以表示为:

xml 复制代码
<redeliveryPolicyProfile id="redelivPolicy" maximumRedeliveries="6" retryAttemptedLogLevel="WARN"/>

<onException useOriginalMessage="true" redeliveryPolicyRef="redelivPolicy">
    <exception>com.mycompany.ValidationException</exception>
    <to uri="activemq:validationFailed"/>
</onException>

注意
redeliveryPolicyProfile如果要在多个onException子句中重复使用相同的重新交付策略,则 使用此方法很有用。

条件捕获

onException通过指定该onWhen选项 ,可以将异常捕获作为条件捕获。如果指定onWhen的选项中onException子句,匹配触发只有当抛出的条款相符onWhen谓词为true在目前的汇率。

例如,在以下Java DSL片段中,onException仅当抛出的异常匹配MyUserException并且user当前交换中的标头为非null时,第一子句才会触发:

java 复制代码
// Java

// Here we define onException() to catch MyUserException when
// there is a header[user] on the exchange that is not null
onException(MyUserException.class)
    .onWhen(header("user").isNotNull())
    .maximumRedeliveries(2)
    .to(ERROR_USER_QUEUE);

// Here we define onException to catch MyUserException as a kind
// of fallback when the above did not match.
// Noitce: The order how we have defined these onException is
// important as Camel will resolve in the same order as they
// have been defined
onException(MyUserException.class)
    .maximumRedeliveries(2)
    .to(ERROR_QUEUE);

前面的onException条款可以在XML DSL中表示如下:

xml 复制代码
<redeliveryPolicyProfile id="twoRedeliveries" maximumRedeliveries="2"/>

<onException redeliveryPolicyRef="twoRedeliveries">
    <exception>com.mycompany.MyUserException</exception>
    <onWhen>
        <simple>${header.user} != null</simple>
    </onWhen>
    <to uri="activemq:error_user_queue"/>
</onException>

<onException redeliveryPolicyRef="twoRedeliveries">
    <exception>com.mycompany.MyUserException</exception>
    <to uri="activemq:error_queue"/>
</onException>
处理异常

默认情况下,当路由中间引发异常时,当前交换的处理将中断,并且所引发的异常将在路由开始时传播回使用者端点。当一个onException子句被触发时,其行为本质上是相同的,除了该onException子句在抛出的异常传播回之前执行一些处理。

但是,这种默认行为不是 处理异常的唯一方法。在onException提供了各种选项来修改异常处理行为,具体如下:

  • 抑制异常重新抛出 -您可以选择在onException子句完成后抑制重新抛出的异常。换句话说,在这种情况下的例外情形并没有在路线的起点重新传播到消费者端点。
  • 继续处理 -您可以选择从最初发生异常的地方恢复交换的正常处理。隐式地,此方法还抑制了重新抛出的异常。
  • 发送响应 -在特殊情况下,路由起点处的使用者终结点需要答复(即具有InOut MEP)时,您可能更喜欢构造自定义的故障答复消息,而不是将异常传播回给消费者端点。

注意

使用自定义处理器,在使用new onExceptionOccurred选项引发异常后不久,就会调用Camel异常子句和错误处理程序。

抑制异常重新抛出

为了防止当前异常被重新引发并传播回使用者端点,可以在Java DSL 中将handled()选项设置为true,如下所示:

java 复制代码
onException(ValidationException.class)
  .handled(true)
  .to("activemq:validationFailed");

在Java DSL中,该handled()选项的参数可以是布尔类型,Predicate类型或Expression类型(其中任何非布尔表达式true如果求值为非null 则解释为)。

可以使用handled元素将相同的路由配置为抑制XML DSL中的重新抛出的异常,如下所示:

xml 复制代码
<onException>
    <exception>com.mycompany.ValidationException</exception>
    <handled>
        <constant>true</constant>
    </handled>
    <to uri="activemq:validationFailed"/>
</onException>
连续处理

要从最初引发异常的路由中继续处理当前消息,可以在Java DSL 中将continued选项设置为true,如下所示:

java 复制代码
onException(ValidationException.class)
  .continued(true);

在Java DSL中,该continued()选项的参数可以是布尔类型,Predicate类型或Expression类型(其中任何非布尔表达式true如果求值为非null 则解释为)。

可以使用continued元素在XML DSL中配置相同的路由,如下所示:

xml 复制代码
<onException>
    <exception>com.mycompany.ValidationException</exception>
    <continued>
        <constant>true</constant>
    </continued>
</onException>
发送响应

当启动路由的使用者端点希望得到答复时,您可能更喜欢构造自定义的故障回复消息,而不是简单地将引发的异常传播回使用者。在这种情况下,您需要执行两个基本步骤:使用handled选项抑制重新抛出的异常;并使用自定义故障消息填充交换机的" **出站"**消息槽。

例如,以下Java DSL片段显示了Sorry每当MyFunctionalException发生异常时如何发送包含文本字符串的回复消息:

java 复制代码
// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body as Sorry.
onException(MyFunctionalException.class)
    .handled(true)
    .transform().constant("Sorry");

如果要向客户端发送故障响应,则通常需要在响应中包含异常消息的文本。您可以使用exceptionMessage()builder方法访问当前异常消息的文本。例如,只要MyFunctionalException发生异常,您就可以发送仅包含异常消息文本的回复,如下所示:

java 复制代码
// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body and return the exception message
onException(MyFunctionalException.class)
    .handled(true)
    .transform(exceptionMessage());

也可以通过exception.message变量从简单语言访问异常消息文本。例如,您可以将当前的异常文本嵌入到回复消息中,如下所示:

java 复制代码
// we catch MyFunctionalException and want to mark it as handled (= no failure returned to client)
// but we want to return a fixed text response, so we transform OUT body and return a nice message
// using the simple language where we want insert the exception message
onException(MyFunctionalException.class)
    .handled(true)
    .transform().simple("Error reported: ${exception.message} - cannot process this message.");

前面的onException子句可以用XML DSL表示如下:

xml 复制代码
<onException>
    <exception>com.mycompany.MyFunctionalException</exception>
    <handled>
        <constant>true</constant>
    </handled>
    <transform>
        <simple>Error reported: ${exception.message} - cannot process this message.</simple>
    </transform>
</onException>
处理异常时引发异常

处理现有异常时抛出的异常(换句话说,是在处理onException子句的过程中抛出的异常)以特殊方式处理。此类异常由特殊的后备异常处理程序处理,该处理程序按如下方式处理异常:

  • 所有现有的异常处理程序都会被忽略,处理会立即失败。
  • 记录新的异常。
  • 在交换对象上设置了新的异常。

简单的策略避免了复杂的故障情况,否则可能导致onException子句被锁定到无限循环中。

范围

这些onException条款在以下任一范围内均有效:

  • RouteBuilder scope - 方法onException内定义为独立语句的子句RouteBuilder.configure()会影响该RouteBuilder实例中定义的所有路由。另一方面,这些onException子句对在任何其他实例内部定义的路由都没有任何影响 RouteBuilder。这些onException子句必须出现在路由定义之前。

    到目前为止,所有示例均使用RouteBuilder范围定义。

  • Route scope - onException子句也可以直接嵌入到路由中。这些onException子句影响定义它们的路由。

路由范围

您可以onException在路由定义内的任何地方嵌入子句,但是必须onException使用end()DSL命令终止嵌入子句。

例如,您可以onException在Java DSL中定义一个嵌入式子句,如下所示:

java 复制代码
// Java
from("direct:start")
  .onException(OrderFailedException.class)
    .maximumRedeliveries(1)
    .handled(true)
    .beanRef("orderService", "orderFailed")
    .to("mock:error")
  .end()
  .beanRef("orderService", "handleOrder")
  .to("mock:result");

您可以onException在XML DSL中定义一个嵌入式子句,如下所示:

xml 复制代码
<route errorHandlerRef="deadLetter">
    <from uri="direct:start"/>
    <onException>
        <exception>com.mycompany.OrderFailedException</exception>
        <redeliveryPolicy maximumRedeliveries="1"/>
        <handled>
            <constant>true</constant>
        </handled>
        <bean ref="orderService" method="orderFailed"/>
        <to uri="mock:error"/>
    </onException>
    <bean ref="orderService" method="handleOrder"/>
    <to uri="mock:result"/>
</route>

错误处理程序

概览

errorHandler()子句提供了与该子句类似的功能onException,不同之处在于该机制无法 区分不同的异常类型。该errorHandler()子句是Apache Camel提供的原始异常处理机制,onException在实现该子句之前可用。

Java DSL示例

errorHandler()子句在一个RouteBuilder类中定义,并应用于该类中的所有路由RouteBuilder。只要其中一条适用路径中发生任何类型 的异常**,**就会触发该事件。例如,要定义将所有失败的交换路由到ActiveMQ deadLetter队列的错误处理程序,可以定义RouteBuilder如下:

java 复制代码
public class MyRouteBuilder extends RouteBuilder {

    public void configure() {
        errorHandler(deadLetterChannel("activemq:deadLetter"));

        // The preceding error handler applies
        // to all of the following routes:
        from("activemq:orderQueue")
          .to("pop3://[email protected]");
        from("file:src/data?noop=true")
          .to("file:target/messages");
        // ...
    }
}

但是,直到用尽所有重新交付的尝试之前,都不会重定向到死信通道。

XML DSL示例

在XML DSL中,您可以camelContext使用errorHandler元素在范围内定义错误处理程序。例如,要定义将所有失败的交换路由到ActiveMQ deadLetter队列的错误处理程序,可以定义一个errorHandler元素,如下所示:

xml 复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <errorHandler type="DeadLetterChannel"
                      deadLetterUri="activemq:deadLetter"/>
        <route>
            <from uri="activemq:orderQueue"/>
            <to uri="pop3://[email protected]"/>
        </route>
        <route>
            <from uri="file:src/data?noop=true"/>
            <to uri="file:target/messages"/>
        </route>
    </camelContext>

</beans>
错误处理程序的类型

错误处理程序类型概述了可以定义的不同类型的错误处理程序。

Java DSL Builder XML DSL类型属性 描述
defaultErrorHandler() DefaultErrorHandler 将异常传播回调用方并支持重新交付策略,但是它不支持死信队列。
deadLetterChannel() DeadLetterChannel 支持与默认错误处理程序相同的功能,此外还支持死信队列。
loggingErrorChannel() LoggingErrorChannel 每当发生异常时记录异常文本。
noErrorHandler() NoErrorHandler 虚拟处理程序实现,可用于禁用错误处理程序。
TransactionErrorHandler 交易路线的错误处理程序。默认事务错误处理程序实例将自动用于标记为已事务处理的路由。

doTry,doCatch和doFinally

概览

要在路线中处理异常,则可以使用的组合doTrydoCatchdoFinally条款,其处理异常以同样的方式到Java的trycatchfinally块。

doCatch和Java catch之间的相似之处

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

  • 多个doCatch子句 -您可以doCatch在一个doTry块中包含多个子句。该doCatch条款在它们出现的顺序进行测试,就像Java的catch()语句。Apache Camel执行doCatch与抛出的异常匹配的第一个子句。

    注意

    该算法与该onException子句使用的异常匹配算法不同--- 有关详细信息

  • 重新抛出异常 -您可以doCatch使用子句从子句中重新抛出当前异常handled

doCatch的特殊功能

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

  • 捕获多个异常 -与仅捕获一个异常doCatch的Javacatch()语句相反,该子句允许您指定要捕获的异常列表。
  • 条件捕获 -通过onWhendoCatch子句中添加一个子句,可以有条件地捕获异常。

下面的示例说明如何doTry在Java DSL中编写一个块doCatch(),如果引发IOException异常或IllegalStateException异常,则子句将在其中执行,而无论是否引发异常,该doFinally()子句始终执行。

java 复制代码
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中:

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()通过调用handled()参数设置为的子句, 可以在子句中抛出异常false,如下所示:

java 复制代码
from("direct:start")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IOException.class)
        // mark this as NOT handled, eg the caller will also get the exception
        .handled(false)
        .to("mock:io")
    .doCatch(Exception.class)
        // and catch all other exceptions
        .to("mock:error")
    .end();

在前面的示例中,如果IOException捕获了doCatch(),则当前交换将发送到mock:io端点,然后将IOException其重新抛出。这为路由起点(在from()命令中)的使用者端点也提供了处理异常的机会。

以下示例显示了如何在Spring XML中定义相同的路由:

xml 复制代码
<route>
    <from uri="direct:start"/>
    <doTry>
        <process ref="processorFail"/>
        <to uri="mock:result"/>
        <doCatch>
            <exception>java.io.IOException</exception>
            <!-- mark this as NOT handled, eg the caller will also get the exception -->
            <handled>
                <constant>false</constant>
            </handled>
            <to uri="mock:io"/>
        </doCatch>
        <doCatch>
            <!-- and catch all other exceptions they are handled by default (ie handled = true) -->
            <exception>java.lang.Exception</exception>
            <to uri="mock:error"/>
        </doCatch>
    </doTry>
</route>
使用onWhen进行条件异常捕获

Apache Camel doCatch()子句的一个特殊功能是,您可以基于在运行时评估的表达式来有条件地捕获异常。换句话说,如果您使用形式为的子句捕获异常,则只有在谓词表达式Expression 在运行时计算为时,才会捕获异常。 doCatch(*ExceptionList*).doWhen(*Expression*)``true

例如,以下doTry块仅在异常消息中包含单词时,才会捕获IOException和: IllegalStateException``Severe

java 复制代码
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中:

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()创建一个try或catch块来处理异常,对于特定于路由的错误处理很有用。

如果您想在中捕获异常ChoiceDefinition,则可以使用以下doTry块:

java 复制代码
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();

2.3.4. 传播SOAP异常

概览

Camel CXF组件提供了与Apache CXF的集成,使您能够从Apache Camel端点发送和接收SOAP消息。您可以轻松地以XML定义Apache Camel端点,然后可以使用端点的Bean ID在路由中对其进行引用

如何传播堆栈跟踪信息

可以配置CXF端点,以便在服务器端引发Java异常时,该异常的堆栈跟踪被整理为故障消息并返回给客户端。要启用此功能,请在元素中将设置dataFormatPAYLOAD,并将faultStackTraceEnabled属性设置为,如下所示: true``cxfEndpoint

xml 复制代码
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
    wsdlURL="ship.wsdl"
    endpointName="s:TestSoapEndpoint"
    serviceName="s:TestService"
    xmlns:s="http://test">
  <cxf:properties>
    <!-- enable sending the stack trace back to client; the default value is false-->
    <entry key="faultStackTraceEnabled" value="true" />
    <entry key="dataFormat" value="PAYLOAD" />
  </cxf:properties>
</cxf:cxfEndpoint>

出于安全原因,堆栈跟踪不包括引起异常(即,紧随其后的堆栈跟踪的一部分Caused by)。如果要在堆栈跟踪中包括引起异常的异常,请在元素中将该exceptionMessageCauseEnabled属性设置为,如下所示: true``cxfEndpoint

xml 复制代码
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
    wsdlURL="ship.wsdl"
    endpointName="s:TestSoapEndpoint"
    serviceName="s:TestService"
    xmlns:s="http://test">
  <cxf:properties>
    <!-- enable to show the cause exception message and the default value is false -->
    <entry key="exceptionMessageCauseEnabled" value="true" />
    <!-- enable to send the stack trace back to client,  the default value is false-->
    <entry key="faultStackTraceEnabled" value="true" />
    <entry key="dataFormat" value="PAYLOAD" />
  </cxf:properties>
</cxf:cxfEndpoint>

警告

您仅应启用该exceptionMessageCauseEnabled标志以进行测试和诊断。服务器通常会掩盖异常的原始原因,以使敌对用户更难探测服务器。

相关推荐
ps酷教程7 小时前
Apache httpclient & okhttp(2)
okhttp·apache
緣起緣落9 小时前
Linux(CentOS 7) 部署 redis 集群
linux·运维·服务器·redis·centos·集成学习
程序猿熊跃晖12 小时前
Excel 数据导入与 SQL 生成:基于 Hutool 和 Apache POI 的优雅实践
sql·apache·excel
碳基学AI2 天前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义免费下载方法
大数据·人工智能·python·gpt·算法·语言模型·集成学习
SeaTunnel3 天前
Apache SeaTunnel 2.3.10 正式发布 —— 全新功能与多项改进,助力数据集成再升级!
apache
路由侠内网穿透3 天前
本地部署开源流处理框架 Apache Flink 并实现外部访问
大数据·网络协议·tcp/ip·flink·服务发现·apache·consul
故事与他6454 天前
TBKDVR硬盘录像机device.rsp命令执行漏洞
服务器·网络·数据库·安全·网络安全·apache
DDDiccc6 天前
项目-苍穹外卖(十七) Apache POI+导出数据
apache
智慧源点6 天前
Apache Doris 高频问题排查指南:从报错到性能优化
apache