Apache Camel指南-第四章:路由径构建之异常处理
摘要
Apache的骆驼提供几种不同的机制,让您在处理不同的粒度级别的例外:您可以通过处理一个路线中的异常doTry
,doCatch
以及doFinally
; 或者您可以指定要采取什么行动每种类型的异常,并应用此规则的所有路由RouteBuilder
使用onException
; 或者,您可以指定对所有异常类型采取何种操作,并将此规则应用于RouteBuilder
using中的所有路由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
子句将捕获该异常并将当前交换重定向到validationFailed
JMS队列(用作死信队列)。
// 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子句,如下所示:
<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.xsdhttp://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定义的条款定义不同的死信目的地ValidationException
,IOException
以及Exception
:
onException(ValidationException.class).to("activemq:validationFailed");
onException(java.io.IOException.class).to("activemq:ioExceptions");
onException(Exception.class).to("activemq:exceptions");
您可以onException
在XML DSL中定义相同的一系列子句,如下所示:
<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中,可以将多个异常分组如下:
onException(ValidationException.class, BuesinessException.class).to("activemq:validationFailed");
在XML DSL中,可以通过在exception
元素内定义多个元素来将多个异常组合在一起onException
,如下所示:
<onException><exception>com.mycompany.ValidationException</exception><exception>com.mycompany.BuesinessException</exception><to uri="activemq:validationFailed"/>
</onException>
当捕获多个异常时,onException
子句的顺序很重要。Apache Camel最初尝试将抛出的异常与第一个子句进行匹配。如果第一个子句不匹配,onException
则尝试下一个子句,依此类推,直到找到匹配项。每次匹配尝试均由以下算法控制:
- 如果抛出的异常是链式异常(也就是说,已捕获异常并将其作为另一个异常重新抛出),则嵌套最丰富的异常类型最初将用作匹配的基础。测试此异常的方法如下:
- 如果要测试的异常具有在
onException
子句中指定的类型(使用进行了测试instanceof
),则会触发匹配。 - 如果要测试的异常是
onException
子句中指定的类型的子类型,则会触发匹配。
- 如果要测试的异常具有在
- 如果嵌套最多的异常无法产生匹配项,则将测试链中的下一个异常(包装异常)。测试将一直沿链条进行,直到触发匹配或链条耗尽为止。
注意
throwException EIP使您可以通过简单的语言表达式创建新的异常实例。您可以根据当前交易所的可用信息来使其动态化。例如,
<throwException exceptionType="java.lang.IllegalArgumentException" message="${body}"/>
死信通道
onException
到目前为止 ,用法的基本示例都利用了死信通道模式。也就是说,当onException
子句捕获异常时,当前交换将路由到特殊的目的地(死信通道)。所述死信通道充当已经失败的消息的保持区域不被处理。管理员可以在以后检查消息,并确定需要采取的措施。
使用原始消息
到路由中间出现异常时,交换中的消息可能已经被重大修改(甚至可能无法被人类读取)。通常,如果在死信队列中可见的消息是原始消息(如在路由开始时收到的消息),则管理员可以更容易地决定采取何种纠正措施。该useOriginalMessage
选项是false
默认选项,但是如果在错误处理程序上配置了该选项,则会自动启用。
注意
当该
useOriginalMessage
选项应用于将消息发送到多个端点或将消息拆分为多个部分的骆驼路由时,该选项可能导致意外行为。原始消息可能不会保留在“多播”,“拆分器”或“收件人列表”路由中,在这些路由中,中间处理步骤会修改原始消息。
在Java DSL中,您可以将交换中的消息替换为原始消息。将设置setAllowUseOriginalMessage()
为true
,然后使用useOriginalMessage()
DSL命令,如下所示:
onException(ValidationException.class).useOriginalMessage().to("activemq:validationFailed");
在XML DSL中,可以通过useOriginalMessage
在onException
元素上设置属性来检索原始消息,如下所示:
<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
死信队列,如下所示:
onException(ValidationException.class).maximumRedeliveries(6).retryAttemptedLogLevel(org.apache.camel.LogginLevel.WARN).to("activemq:validationFailed");
在XML DSL中,通过在redeliveryPolicy
元素上设置属性来指定重新交付策略选项。例如,前面的路由可以在XML DSL中表示如下:
<onException useOriginalMessage="true"><exception>com.mycompany.ValidationException</exception><redeliveryPolicy maximumRedeliveries="6"/><to uri="activemq:validationFailed"/>
</onException>
路由的后半部分(设置了重新交付选项之后)直到最后一次重新交付尝试失败后才进行处理。
或者,您可以在redeliveryPolicyProfile
实例中指定重新交付策略选项。然后,您可以redeliveryPolicyProfile
使用onException
元素的redeliverPolicyRef
属性来引用实例。例如,前面的路由可以表示为:
<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// 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中表示如下:
<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
,如下所示:
onException(ValidationException.class).handled(true).to("activemq:validationFailed");
在Java DSL中,该handled()
选项的参数可以是布尔类型,Predicate
类型或Expression
类型(其中任何非布尔表达式true
如果求值为非null 则解释为)。
可以使用handled
元素将相同的路由配置为抑制XML DSL中的重新抛出的异常,如下所示:
<onException><exception>com.mycompany.ValidationException</exception><handled><constant>true</constant></handled><to uri="activemq:validationFailed"/>
</onException>
连续处理
要从最初引发异常的路由中继续处理当前消息,可以在Java DSL 中将continued
选项设置为true
,如下所示:
onException(ValidationException.class).continued(true);
在Java DSL中,该continued()
选项的参数可以是布尔类型,Predicate
类型或Expression
类型(其中任何非布尔表达式true
如果求值为非null 则解释为)。
可以使用continued
元素在XML DSL中配置相同的路由,如下所示:
<onException><exception>com.mycompany.ValidationException</exception><continued><constant>true</constant></continued>
</onException>
发送响应
当启动路由的使用者端点希望得到答复时,您可能更喜欢构造自定义的故障回复消息,而不是简单地将引发的异常传播回使用者。在这种情况下,您需要执行两个基本步骤:使用handled
选项抑制重新抛出的异常;并使用自定义故障消息填充交换机的“ **出站”**消息槽。
例如,以下Java DSL片段显示了Sorry
每当MyFunctionalException
发生异常时如何发送包含文本字符串的回复消息:
// 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
发生异常,您就可以发送仅包含异常消息文本的回复,如下所示:
// 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
变量从简单语言访问异常消息文本。例如,您可以将当前的异常文本嵌入到回复消息中,如下所示:
// 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表示如下:
<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
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中定义一个嵌入式子句,如下所示:
<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
如下:
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://fulfillment@acme.com");from("file:src/data?noop=true").to("file:target/messages");// ...}
}
但是,直到用尽所有重新交付的尝试之前,都不会重定向到死信通道。
XML DSL示例
在XML DSL中,您可以camelContext
使用errorHandler
元素在范围内定义错误处理程序。例如,要定义将所有失败的交换路由到ActiveMQ deadLetter
队列的错误处理程序,可以定义一个errorHandler
元素,如下所示:
<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.xsdhttp://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://fulfillment@acme.com"/></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
概览
要在路线中处理异常,则可以使用的组合doTry
,doCatch
和doFinally
条款,其处理异常以同样的方式到Java的try
,catch
和finally
块。
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()
语句相反,该子句允许您指定要捕获的异常列表。 - 条件捕获 -通过
onWhen
在doCatch
子句中添加一个子句,可以有条件地捕获异常。
例
下面的示例说明如何doTry
在Java DSL中编写一个块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()
通过调用handled()
参数设置为的子句, 可以在子句中抛出异常false
,如下所示:
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中定义相同的路由:
<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
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>
doTry中的嵌套条件
有多种选项可将Camel异常处理添加到JavaDSL路由。dotry()
创建一个try或catch块来处理异常,对于特定于路由的错误处理很有用。
如果您想在中捕获异常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();
2.3.4. 传播SOAP异常
概览
Camel CXF组件提供了与Apache CXF的集成,使您能够从Apache Camel端点发送和接收SOAP消息。您可以轻松地以XML定义Apache Camel端点,然后可以使用端点的Bean ID在路由中对其进行引用
如何传播堆栈跟踪信息
可以配置CXF端点,以便在服务器端引发Java异常时,该异常的堆栈跟踪被整理为故障消息并返回给客户端。要启用此功能,请在元素中将设置dataFormat
为PAYLOAD
,并将faultStackTraceEnabled
属性设置为,如下所示: true``cxfEndpoint
<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
<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
标志以进行测试和诊断。服务器通常会掩盖异常的原始原因,以使敌对用户更难探测服务器。
相关文章:
Apache Camel指南-第四章:路由径构建之异常处理
摘要 Apache的骆驼提供几种不同的机制,让您在处理不同的粒度级别的例外:您可以通过处理一个路线中的异常doTry,doCatch以及doFinally; 或者您可以指定要采取什么行动每种类型的异常,并应用此规则的所有路由RouteBuilder使用onExc…...
赚钱模拟器--百宝库v0.1.0
#include<bits/stdc.h> #include<windows.h> using namespace std; int n; void welcome(); void zhuye(); int main(){welcome();zhuye();return 0; }void welcome(){cout<<"欢迎您使用更多资源-百宝库v0.1.0"<<endl;system("pause&q…...
SSL证书自动化管理(ACME协议)工作流程介绍
SSL证书自动化管理(ACME协议)是一种用于自动化管理SSL/TLS证书的协议,以下是其详细介绍: 一、ACME协议概述 ACME协议由互联网安全研究小组(ISRG)设计开发,旨在实现SSL证书获取流程的自动化。通…...
推理模型与普通大模型如何选择?
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理、AI应用🔥如果感觉…...
人工智能与计算机技术融合下的高中教育数字化教学模式探索
一、引言 1.1 研究背景与意义 1.1.1 教育数字化转型的国家战略需求 在当今时代,数字化浪潮正席卷全球,深刻改变着人们的生产生活方式。教育领域作为培养未来人才的重要阵地,也不可避免地受到数字化的影响。教育数字化转型已成为世界各国的…...
P2762 太空飞行计划问题 (网络流、最大权闭合子图问题)
P2762 太空飞行计划问题 思路: 今日网络流 这个题思路其实很简单,先说结论:源点连所有实验,容量为收益;实验连接对应仪器,容量为无穷;所有仪器连汇点,容量为费用(注意是…...
对用户登录设计测试用例
一、功能测试 1、正确用户名和密码 输入正确的用户名和密码,点击提交,验证是否成功登录。 2、错误用户名或密码 输入错误的用户名或密码,验证登录失败,并提示“用户名或密码错误”。 3、登录…...
c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第四式】自定义类型详解(结构体、枚举、联合)
c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第四式】自定义类型详解(结构体、枚举、联合) 【心法】 【第零章】c语言概述 【第一章】分支与循环语句 【第二章】函数 【第三章】数组 【第四章】操作符 【第五章】指针 【第六章】结构体 【第七章】con…...
阿里巴巴langengine二次开发大模型平台
阿里巴巴LangEngine开源了!支撑亿级网关规模的高可用Java原生AI应用开发框架 - Leepy - 博客园 阿里国际AI应用搭建平台建设之路(上) - 框架篇 基于java二次开发 目前Spring ai、spring ai alibaba 都是java版本的二次基础能力 重要的是前端工作流 如何与 服务端的…...
获取KUKA机器人诊断文件KRCdiag的方法
有时候在进行售后问题时需要获取KUKA机器人的诊断文件KRCdiag,通过以下方法可以获取KUKA机器人的诊断文件KRCdiag: 1、将U盘插到控制柜内的任意一个USB接口; 2、依次点【主菜单】—【文件】—【存档】—【USB(控制柜)…...
聊聊Spring AI的MilvusVectorStore
序 本文主要研究一下Spring AI的MilvusVectorStore 示例 pom.xml <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-vector-store-milvus</artifactId></dependency>配置 spring:ai:vectorstore:…...
前后端通信指南
HTTP 协议与 RESTful APIWebSocket 与实时通信一、前后端通信概述 前后端通信是现代 Web 开发的核心环节,前端(浏览器或移动端)需要向后端请求数据,并根据返回的数据渲染界面。常见的通信方式包括 HTTP 请求、RESTful API、WebSocket、GraphQL 等。 常见前后端通信方式 通…...
[特殊字符] 驱动开发硬核特训 · Day 2
主题:深入掌握 UART 与 SPI 驱动开发原理、架构与调试技术 本期围绕实际项目中应用最广泛的两类外设通信接口 —— UART(串口)与 SPI(串行外设接口),通过结构化知识点梳理,结合实际驱动开发流程…...
B树和B+树的区别(B Tree B+ Tree)
前言 B树和B树是数据库中常用的索引结构,它们的核心区别主要体现在数据存储方式、节点结构和适用场景上。 关键区别详解 数据存储方式: B树:所有节点均存储键值(key-data)对,数据可能分布在树的任意层级。…...
32--当网络接口变成“夜店门口“:802.1X协议深度解码(理论纯享版本)
当网络接口变成"夜店门口":802.1X协议深度解码 引言:网口的"保安队长"上岗记 如果把企业网络比作高端会所,那么802.1X协议就是门口那个拿着金属探测器的黑超保安。它会对着每个想进场的设备说:“请出示您的会…...
【LLM】使用MySQL MCP Server让大模型轻松操作本地数据库
随着MCP协议(Model Context Protocol)的出现,使得 LLM 应用与外部数据源和工具之间的无缝集成成为可能,本章就介绍如何通过MCP Server让LLM能够直接与本地的MySQL数据库进行交互,例如新增、修改、删除数据,…...
MOM成功实施分享(八)汽车活塞生产制造MOM建设方案(第一部分)
在制造业数字化转型的浪潮中,方案对活塞积极探索,通过实施一系列数字化举措,在生产管理、供应链协同、质量控制等多个方面取得显著成效,为行业提供了优秀范例。 1.转型背景与目标:活塞在数字化转型前面临诸多挑战&…...
程序化广告行业(59/89):广告验证与反作弊实战技巧
程序化广告行业(59/89):广告验证与反作弊实战技巧 大家好!在程序化广告领域,想要做好投放,除了了解基本的架构和原理,还得掌握一些关键的技能,比如广告验证和反作弊。今天就和大家一…...
市场趋势分析与交易策略调整
市场趋势分析与交易策略调整 在市场交易中,趋势的判断与策略的调整至关重要。不同市场环境下,交易者需要灵活运用技术分析和资金管理手段,以提升交易的稳定性。本文将探讨市场趋势的识别方法,以及如何在不同市场环境中调整交易策略…...
安卓离线畅玩的多款棋类单机游戏推荐
软件介绍 在手游盛行的当下,不少玩家在网游激战之余,渴望一份单机游戏带来的宁静与专注。今天要为大家介绍的,便是一款能满足此类需求的安卓软件 —— 棋类大师。 它巧妙地将象棋、围棋、五子棋三种经典棋类游戏集成于一身,且具…...
论文阅读Diffusion Autoencoders: Toward a Meaningful and Decodable Representation
原文框架图: 官方代码: https://github.com/phizaz/diffae/blob/master/interpolate.ipynb 主要想记录一下模型的推理过程 : %load_ext autoreload %autoreload 2 from templates import * device cuda:1 conf ffhq256_autoenc() # pri…...
医疗信息系统的主要痛点分析
医疗信息系统的主要痛点分析 1. 数据治理问题 数据标准不统一 各医院采用不同的数据格式和编码标准诊断术语、药品编码等缺乏统一规范检验检查结果的参考值范围不一致 数据质量参差不齐 数据录入不规范,存在大量错误和缺失历史数据清洗难度大数据更新不及时 数据安…...
Pycharm v2024.3.4 Windows Python开发工具
Pycharm v2024.3.4 Windows Python开发工具 文章目录 Pycharm v2024.3.4 Windows Python开发工具一、介绍二、效果三、下载 一、介绍 JetBrains PyCharm 是一款Python集成开发环境(IDE),被广泛用于Python开发 二、效果 三、下载 百度网盘: …...
YOLOv12 从预训练迈向自主训练,第一步数据准备
视频讲解: YOLOv12 从预训练迈向自主训练,第一步数据准备 前面复现过yolov12,使用pre-trained的模型进行过测试,今天来讲下如何训练自己的模型,第一步先准备数据和训练格式 https://gitcode.com/open-source-toolkit/…...
Java 线程池全面解析
Java 线程池全面解析 一、线程池种类及优缺点 1. 常见线程池类型(通过Executors创建) 线程池类型创建方式特点适用场景缺点FixedThreadPoolExecutors.newFixedThreadPool(n)固定线程数,无界队列负载较重的服务器可能堆积大量任务导致OOMCachedThreadPoolExecutors.newCach…...
第七章 Python基础进阶-异常、模块与包(其五)
目录 一.异常 二.异常的捕获方法 1.捕获常规异常 2.捕获指定异常 3.捕获多个异常 4.异常else 5.异常的finally 三.异常的传递 四.Python模块 1.import导入模块 2.from导入模块 3.from模块名 import* 4.as定义别名 5.自定义模块 (1)测试模块…...
vulkanscenegraph显示倾斜模型(5.6)-vsg::RenderGraph的创建
前言 上一章深入分析了vsg::CommandGraph的创建过程及其通过子场景遍历实现Vulkan命令录制的机制。本章将在该基础上,进一步探讨Vulkan命令录制中的核心封装——vsg::RenderGraph。作为渲染流程的关键组件,RenderGraph封装了vkCmdBeginRenderPass和vkCmd…...
DelayQueue vs ScheduledThreadPool:Java定时任务的双雄争霸
定时任务管理的两种武林绝学 想象你需要管理一个跨时区的视频会议系统: DelayQueue 像一位严格的计时员,把所有会议请求按时间排序,到点才放行ScheduledThreadPool 像一位智能秘书,能主动安排、取消和调整会议时间 它们都能处理…...
Qt添加资源文件
目录 1.创建一个新项目 1.1菜单栏 添加菜单项 1.2工具栏 1.3铆接部件 1.4中心部件 1.5最终界面 2.资源文件 2.1将图片文件拷贝到项目位置下 2.2添加新文件 2.3rec.qrc文件 2.4添加前缀,添加文件 2.5使用 1.创建一个新项目 利用界面文件完成一个有菜单…...
U-Net: Convolutional Networks for BiomedicalImage Segmentation
Abstract 人们普遍认为,深度网络的成功训练需要成千上万的标注训练样本。在本文中,我们提出了一种网络和训练策略,该策略强烈依赖于数据增强,以更有效地利用现有的标注样本。该架构包括一个用于捕获上下文的收缩路径和一个用于实…...
28--当路由器开始“宫斗“:设备控制面安全配置全解
当路由器开始"宫斗":设备控制面安全配置全解 引言:路由器的"大脑保卫战" 如果把网络世界比作一座繁忙的城市,那么路由器就是路口执勤的交通警察。而控制面(Control Plane)就是警察的大脑…...
NHANES指标推荐:DI-GM
文章题目:The relationship between dietary index for gut microbiota and diabetes DOI:10.1038/s41598-025-90854-y 中文标题:肠道菌群膳食指数与糖尿病的关系 发表杂志:Sci Rep 影响因子:1区,IF3.8 发表…...
仓库规划 第32次CCF-CSP计算机软件能力认证
没什么说的暴力枚举 n*n*m 的时间复杂度 题目说选序号小的作为父亲 直接编号前往后输出 遇到合适的就break #include<bits/stdc.h> using namespace std; int n, m; int main() {cin >> n >> m;//n:仓库个数 m:位置编码的维数vector<vector<int>…...
leetcode-代码随想录-哈希表-哈希理论基础
哈希表理论基础 哈希表:或者称为散列表,是根据关键码的值而直接进行访问的数据结构。 哈希法:用于快速判断一个元素是否出现在集合里 哈希函数是⼀种映射关系,根据关键词key,经过⼀定函数关系 f 得到元素的位置。 存…...
《科学》期刊发布新成果:量子计算迎来原子 - 光腔集成新时代
《Error-detected quantum operations with neutral atoms mediated by an optical cavity》 -《Science》 2025.3.21 摘要 光镊(optical tweezers)束缚的可编程原子阵列已成为量子信息处理(quantum information processing)和量…...
Spring Boot 与 TDengine 的深度集成实践(一)
引言 在当今数字化时代,数据处理与存储对于各类应用的重要性不言而喻。Spring Boot 作为一款流行的 Java 开发框架,以其快速开发、约定大于配置、内嵌容器等特性,大大提升了 Java 企业级应用的开发效率,降低了开发门槛࿰…...
SpringBoot + Netty + Vue + WebSocket实现在线聊天
最近想学学WebSocket做一个实时通讯的练手项目 主要用到的技术栈是WebSocket Netty Vue Pinia MySQL SpringBoot,实现一个持久化数据,单一群聊,支持多用户的聊天界面 下面是实现的过程 后端 SpringBoot启动的时候会占用一个端口ÿ…...
数据结构实验2.3:Josephus问题求解
文章目录 一,问题描述二,基本要求三,算法设计(1)存储结构设计(2)算法设计 四,示例代码五,运行效果 一,问题描述 在现实生活以及计算机科学的一些场景中&…...
Ruby语言的代码重构
Ruby语言的代码重构:探索清晰、可维护与高效的代码 引言 在软件开发的过程中,代码的质量直接影响到项目的可维护性、扩展性和整体性能。随着时间的推移,系统的需求变化,代码可能会变得混乱和难以理解,因此࿰…...
CAN/FD CAN总线配置 最新详解 包含理论+实战(附带源码)
看前须知:本篇文章不会说太多理论性的内容(重点在理论结合实践),顾及实操,应用,一切理论内容支撑都是为了后续实际操作进行铺垫,重点在于读者可以看完文章应用。(也为节约读者时间&a…...
杰文字悖论:效率提升的副作用
最近,Deepseek的火爆让我们开始反思一个有趣的现象:杰文斯悖论。这是1856年,经济学家杰文斯提出来的一个有趣的现象:当技术效率提高时,资源的使用量反而会增加,而不是减少。听起来可能有点不可思议。杰文斯…...
AcWing 6118. 蛋糕游戏
贪心 为了方便描述,下面将贝茜和埃尔茜分别称为a、b。 已知蛋糕的数量为偶数个,b每次只能吃左右边界上的蛋糕,a每次操作将两个蛋糕变成一个,发现都会使蛋糕的数量减一,且a先操作将蛋糕数量从偶数变成奇数,…...
【前端】【Nuxt3】Nuxt 3 开发中因生命周期理解不足导致的常见错误分类及其解决方案
以下是 Nuxt 3 开发中因生命周期理解不足导致的常见错误分类及其解决方案,以结构化形式呈现: 一、数据获取与异步处理 错误 1:错误使用客户端钩子获取数据 问题:在 onMounted 中获取数据,导致 SSR 失效。示例&#x…...
【kubernetes】BusyBox
目录 1. 说明2. 在 Kubernetes 中的角色2.1 轻量级调试工具2.2 临时容器2.3 网络测试2.4 文件系统检查 3. 为什么选择 BusyBox?4. 常见用法5. 注意事项 1. 说明 1.BusyBox 是一个轻量级、开源的 Linux 工具集,将多种常见的 Unix 工具(如 ls、…...
Leetcode——239. 滑动窗口最大值
题解一 思路 第一次做困难的题,确实把我既困住了又难住了,确实自己一点都想不出来。 这个思路,差不多就是,自己定义一个单调队列。 添加的时候,判断是否比队列最后的元素大,如果比它大,就把…...
kubernetes configMap 存储
1.模型 首先会在每一个节点上安装一个叫 agent 端 agent 端要做的作用就是监听当前的目标配置中心的配置选项是否发送更新动作 如果有的话 我的agent 端的话要从远程的配置中心 去下载最新的配置文件 替换我当前的 再去触发nginx实现重载 当然对于后期的运维工程师 如果想去发…...
架构思维:查询分离 - 表数据量大查询缓慢的优化方案
文章目录 Pre引言案例何谓查询分离?何种场景下使用查询分离?查询分离实现思路1. 如何触发查询分离?方式一: 修改业务代码:在写入常规数据后,同步建立查询数据。方式二:修改业务代码:…...
A2DP(Advanced Audio Distribution Profile)是蓝牙协议栈中用于音频传输的一个标准化协议
A2DP(Advanced Audio Distribution Profile)是蓝牙协议栈中用于音频传输的一个标准化协议,主要用于高质量音频流的无线传输。以下是A2DP协议的详细信息: 定义 A2DP协议允许音源设备(Source,简称SRC&#…...
Redisson使用详解
一、Redisson 核心特性与适用场景 Redisson 是基于 Redis 的 Java 客户端,提供分布式对象、锁、集合和服务,简化分布式系统开发。 典型应用场景: 分布式锁:防止重复扣款、超卖控制(如秒杀库存)。数据共享…...
GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩
作者:林子熠、饶子昊 2025 年 3 月 18 日 Oracle 双箭齐发,正式发布了 JDK 24 和 GraalVM 24,带来了众多新特性。 JDK 24 在性能和安全性方面均有改进(特性列表链接见下),其中较大的一处改动是在 JDK 中…...