11.11. Service Activator
概述
service activator 模式在 图 11.9 “Service Activator Pattern” 中显示的是,描述在响应传入请求信息时调用该服务的操作的情况。服务激活器标识要调用哪些操作并提取要用作操作参数的数据。最后,服务激活程序利用从消息中提取的数据来调用操作。操作调用可以是单向(请求)或双向(request/reply)。
图 11.9. Service Activator Pattern
在很多方面,服务激活程序类似于传统的远程过程调用(RPC),其中操作调用被编码为消息。主要区别在于,服务激活者需要更灵活。RPC 框架对请求和回复消息编码(例如,Web 服务操作编码为 SOAP 消息),而服务激活器通常需要在消息传递系统和服务操作之间提供映射。
Bean 集成
Apache Camel 为支持服务提供的主要机制是 集成。bean 集成 提供了一个通用框架,用于将传入消息映射到 Java 对象上方法调用。例如,Java fluent DSL 提供了处理器 bean()
和 beanRef()
,您可以插入到路由中以调用已注册 Java Bean 上的方法。消息数据到 Java 方法参数的详细映射由 bean 绑定 决定,可以通过向 bean 类添加注解来实现。
例如,请考虑以下路由,该路由调用 Java 方法 BankBean.getUserAccBalance()
,以服务请求传入 JMS/ActiveMQ 队列:
from("activemq:BalanceQueries") .setProperty("userid", xpath("/Account/BalanceQuery/UserID").stringResult()) .beanRef("bankBean", "getUserAccBalance") .to("velocity:file:src/scripts/acc_balance.vm") .to("activemq:BalanceResults");
从 ActiveMQ 端点 activemq:BalanceQueries
中拉取的消息具有一个简单的 XML 格式,可提供银行账户的用户 ID。例如:
<?xml version='1.0' encoding='UTF-8'?> <Account> <BalanceQuery> <UserID>James.Strachan</UserID> </BalanceQuery> </Account>
路由中的第一个处理器 设置Property()
,从 In 消息中提取用户 ID,并将其存储在 userid
Exchange 属性中。这最好将其存储在标头中,因为调用 bean 后无法使用 In 标头。
服务激活步骤由 beanRef()
处理器执行,它会将传入的消息绑定到由 银行 Bean
识别的 Java 对象上的 getUserAccBalance()
方法。以下代码显示了 BankBean
类实施示例:
package tutorial; import org.apache.camel.language.XPath; public class BankBean { public int getUserAccBalance(@XPath("/Account/BalanceQuery/UserID") String user) { if (user.equals("James.Strachan")) { return 1200; } else { return 0; } } }
如果 @XPath
注释启用消息数据到方法参数的绑定,它会将 UserID
XML 元素的内容注入到 用户
方法参数中。在完成调用时,返回值将插入到 Out 消息的正文中,然后复制到路由中下一步的 In 消息中。要让 bean 可以被 beanRef()
处理器访问,您必须在 Spring XML 中实例化实例。例如,您可以将以下行添加到 META-INF/spring/camel-context.xml
配置文件以实例化 bean:
<?xml version="1.0" encoding="UTF-8"?> <beans ... > ... <bean id="bankBean" class="tutorial.BankBean"/> </beans>
在 registry 中,bean ID、tailBean 标识了此 bean 实例。
bean 调用的输出注入到 Velocity 模板中,以生成正确格式的结果消息。Velocity 端点 velocity:file:src/scripts/acc_balance.vm
用于指定 velocity 脚本的位置:
<?xml version='1.0' encoding='UTF-8'?> <Account> <BalanceResult> <UserID>${exchange.getProperty("userid")}</UserID> <Balance>${body}</Balance> </BalanceResult> </Account>
Exchange 实例作为 Velocity 变量 交换
提供,它可让您使用 ${exchange.getProperty("
获取 userid Exchange 属性。当前 In 消息的正文 userid
")}${body}
中包含 getUserAccBalance()
方法调用的结果。