spring jms 消息_使用JMS和Spring.NET进行消息互操作

spring jms 消息

介绍

.NET和Java之间存在多种实现互操作性的方法。 最受欢迎的方法之一是使用Web服务,并设计可在两种环境中均可使用的WSDL和XML Schema。 如您所料,Web服务最适合基于Internet的应用程序。 如果要编写在单个部门或组织内的LAN上运行的Intranet应用程序,则其他中间件技术将变得有吸引力。 具体地说,面向消息的中间件(MOM)长期以来一直是在公司内集成各种平台的流行选择。 本文将MOM用作.NET和Java之间通信的基础,以在本地LAN上运行的简单股票应用程序为背景,演示.NET客户端和Java中间层之间的互操作性。 该实现使用Spring框架中的JMS支持(可用于.NET和Java)来提供跨应用程序两层的通用编程模型。

为什么要发送消息?

在许多方面,面向消息的中间件可以被视为互操作性的老手。 诸如IBM和TIBCO之类的供应商已经提供了超过20年的消息中间件,它们可以在异构操作系统上工作并具有多种语言绑定。 在1999年,Java消息服务(JMS)规范通过定义一组通用的API和消息传递供应商要实现的行为,为消息传递领域注入了新的活力。 鉴于传统,JMS实现可在多个操作系统上运行并且大多数(但不是全部)提供.NET API 1并不奇怪。 本文中的示例使用TIBCO的JMS实现,该实现提供Java,.NET,.NET Compact Framework和C ++客户端API。 附带说明一下,即使您的首选供应商不提供.NET客户端,也有一些选项可用于从.NET访问JMS。 其中之一是使用互操作性产品,例如JNBridge 2或Codemesh 3

尽管互操作性是使用消息传递的一个令人信服的理由,但还有许多其他方面使它成为在应用程序体系结构中使用的非常有吸引力的选择(即使不是事实)。 简而言之,MOM擅长提供进程之间的异步通信,发布-订阅(一对多)消息传递语义以及高度的可靠性。 如果您的应用程序可以从这些功能中受益,那么您会经常找到一种适合的消息传递解决方案。 如果您的公司出于某些原因已经在使用消息传递,但是仅在基于Java或C ++的应用程序中使用了消息传递,请将其角色扩展为包括.NET客户端在内的现有体系结构的逻辑扩展。 无论是什么激励因素,创建基于JMS的解决方案都有其自己的学习曲线和最佳实践的集合。 本文使用.NET和Java上的Spring框架来演示如何快速开始创建JMS应用程序。 它还提供有关使用消息传递在.NET和Java之间进行通信时自然出现的一些问题的指南。

介绍Spring.NET

尽管大多数人都熟悉用于构建Java应用程序的Spring框架,但许多人并不知道其.NET对应版本Spring.NET 4 。 Spring.NET是Spring框架的.NET版本,它是用C#“从头开始”构建的,可以将Spring的设计和方法移植到.NET。 它包含与Java对应的一组相同的核心功能,即控制反转,面向方面的编程,Web框架,RPC导出器,声明式事务管理和ADO.NET框架。 简而言之,如果您已经是“ Spring.Java”用户,那么使用Spring.NET会让您感到宾至如归。

与Spring.Java在其基础上捆绑了许多第三方库不同,Spring.NET将对第三方库的支持分为可单独下载的模块。 这些模块之一提供了基于TIBCO的JMS实现的JMS支持。 如果您想运行本文的示例,则应从TIBCO的网站5下载评估版的TIBCO EMS(企业消息服务)。

一个自然的问题是:“为什么Spring.NET只支持TIBCO的JMS而不支持<在此处插入提供者名称>?” 没有根本原因不支持其他供应商。 由于这实际上是一个实际的原因,因为.NET中没有事实上的JMS API,每个供应商都需要实现。 这样,每个供应商最终都会创建自己的Java JMS API的.NET启发式副本。 开源项目.Net消息服务API(NMS)的目标是提供这样的通用API,并且很有可能将其用于Spring.NET 6中将来的JMS工作。 由于我对TIBCO的JMS产品非常熟悉,因此出于方便考虑,选择它作为第一个在Spring.NET中提供支持的提供者。

使用Spring框架进行消息传递

Spring的JMS支持的目标是提高使用JMS时的抽象水平并支持消息传递最佳实践。 Spring通过提供易于使用的消息传递类(使通用操作变得简单)并通过使用MessageConverters创建用于消息传递的“普通旧对象”(POJO / POCO)编程模型来实现这些目标。 MessageConverters负责JMS消息和“普通旧对象”之间的转换,其实质与XML / Object映射器相同,但带有JMS扭曲。 使用消息转换器可为您带来好处,即可以将JMS工件限制在应用程序的最外层,从而使大部分应用程序与技术无关。 如果您决定切换中间件,则所需的重构将大大少于JMS MapMessage进入您的业务处理的重构。

与JDBC一样,JMS是一个低级API,甚至对于最基本的JMS任务,它都要求您创建和管理多个中间对象。 为了发送消息,Spring的JmsTemplate代表您管理这些中间对象,并使常见的JMS操作成为“单线”。 在接收方,Spring的MessageListenerContainer实现使您可以轻松创建基础结构以支持并发异步消息消费。 JmsTemplate和MessageListenerContainer都可以与MessageConverter关联,以在JMS和POJO / POCO世界之间进行转换。

JmsTemplateMessageListenerContainersMessageConverters是Spring的JMS支持中的中心构件。 本文对它们进行了广泛的使用,并对其进行了详细说明,但不是最终的参考。 有关更多详细信息,请参考Spring参考文档或其他Spring资源。

Spring JMS中的Hello World

在深入探讨互操作性和Spring JMS的细节之前,这是.NET中的一个简单示例,该示例使用JmsTemplate将“ Hello World” TextMessage发送到名为“ test.queue”的JMS队列。

ConnectionFactory factory = new ConnectionFactory("tcp://localhost:7222");
JmsTemplate template = new JmsTemplate(factory);
template.ConvertAndSend("test.queue", "Hello world!");

如果您都熟悉JMS API,则可以立即看到使用JmsTemplate与直接使用JMS API相比有多么简单。 这主要是因为JmsTemplate提供了JMS Connections,Session和MessageProducers的所有样板资源管理,否则您将需要对其进行编码。 它还增加了其他便利,例如在Java中将已检查的异常转换为未检查的异常,将基于字符串的JMS目标解析为JMS目标对象,以及委托给MessageConverter将对象转换为JMS消息。 如果要不进行转换就发送消息,则JmsTemplate具有一个简单的Send方法。

调用ConvertAndSend方法时, JmsTemplate使用默认的MessageConverter实现SimpleMessageConverter来转换字符串“ Hello World!”。 到JMS TextMessage。 SimpleMessageConverter还支持字节阵列和ByteMessage和哈希表和为JMS MapMessage之间的转换。 提供您自己的自定义MessageConverter实现是创建复杂的Spring JMS应用程序的核心。 通用方法是为您已在应用程序代码中使用的对象创建一个转换器,而只是想将它们编组/解组到JMS上。

简而言之,JMS的互操作性

将Spring作为.NET和Java上的通用框架,围绕互操作性的问题归结为实现兼容的MessageConverters以及在.NET和Java之间交换的“普通旧对象”的实现。 为了方便起见,我们将这些简单的旧对象称为“业务对象”。 实际上,它们可能是完整的域对象,数据传输对象或适合呈现的域对象的UI优化版本。 通过这种方法,业务对象本身本质上成为了两层之间的数据契约。 该数据协定中包含的字段和属性取决于转换器的实现。 请注意,没有明确共享特定的数据类型。 围栏每一侧的数据类型仅在它们关联的消息转换器可以成功执行其工作的范围内才需要彼此兼容。

尽管此方法肯定比Web服务中的使用前期合同少规定性,但可以使用多种技术来显着地约束交换的数据并减少琐碎的不匹配。 在这方面有帮助的一个非技术性问题是,在Intranet或部门应用程序中,开发.NET客户端和Java中间层的人员通常是同一个人(甚至是个人)。 因此,交流和频繁的集成测试可以在很大程度上替代旨在供不同开发小组使用的预先联系方式。 如果您喜欢使用预先的正式合同来定义各层之间的交互,那么建议的JMS方法可能不适合您。 话虽如此,据我所知,在一些项目中已经成功地使用了这种更为宽松且标准化程度较低的互操作性方法。

以下各节采用一种日益复杂的方法来使用MessageConverters并使业务对象在.NET和Java之间保持同步。 示例应用程序通过使用Spring附带的SimpleMessageConverter交换哈希表开始。 然后,我们创建一个简单业务对象以及相应的一对自定义MessageConverters的.NET和Java实现。 最后,我们将展示一些技术,这些技术可以通过使用源代码转换器和通用的“通用” MessageConverter来减少在每个平台上手动创建转换器和业务对象所涉及的重复工作,而不是转换任意对象类型。 在此过程中,将讨论每种方法的优缺点。

股票交易示例

该示例的上下文是简化的股票交易应用程序。 我们的应用程序将具有三个主要功能-实时市场数据信息的分发,新交易的创建以及交易组合的检索。

从分发市场数据开始,我们创建了JMS基础结构,以将消息从Java中间层发送到.NET客户端。 在Java中间层上,将创建JmsTemplate来发送消息,并在客户端上创建SimpleMessageListenerContainer来接收消息。 这两个类默认情况下都使用SimpleMessageConverter的实例。 由于市场数据本质上是键值对的集合,即PRICE = 28.5,TICKER =“ CSCO”,因此使用默认转换器并在.NET / Java之间交换简单的哈希表是合理的。

JmsTemplate和SimpleMessageListenerContainer的配置都需要JMS连接工厂以及JMS目标名称和类型。 SimpleMessageListenerContainer还需要引用JMS MessageListener回调的实现来处理消息。 Spring提供了一个MessageListenerAdapter类,该类实现JMS MessageListener接口,并使用MessageConverter将接收到的JMS Message转换为对象。 然后,MessageListenerAdapter使用此对象在用户提供的具有匹配方法签名的处理程序类上调用方法。

上面的流程将通过一个示例得到最好的解释。 如果将MessageListenerAdapter配置为使用SimpleMessageConverter,则传入的JMS MapMessage将转换为.NET IDictionary,并且将调用处理程序类上带有签名“ void handle(IDictionary data)”的方法。 如果转换器生成了Trade类型的对象,则处理程序类必须包含一个名为handle(Trade trade)的方法。 下面的序列图显示了事件流。

此委托方案在Java世界中通常称为“消息驱动的POJO”或“消息驱动的对象”,因为它是“普通旧对象”而不是充当消息传递回调的JMS MessageListener。 这种方法的优点之一是,您可以通过直接调用处理程序方法来轻松创建用于测试应用程序流程的集成样式测试用例。 另一个优点是MessageListenerAdapter可以替代消息传递应用程序中常见的if / else或switch / case块。 SimpleMessageListenerContainer包含许多其他功能,例如根据处理程序方法的返回值自动发送回复消息,并且打算将其子类化以定制处理流程。 有关更多详细信息,请参考Spring参考文档。

这些对象的Spring配置如下所示。

中间层发布者:

<bean id = "jmsTemplate" class = "org.springframework.jms.core.JmsTemplate" >
<property name = "connectionFactory" ><ref bean = "connectionFactory" /></property>
<property name = "pubSubDomain" value = "true" />
<property name = "defaultDestinationName" value = "APP.STOCK" />
</bean>

和客户消费者

<object id= "jmsContainer" 
type= "Spring.Messaging.Tibco.Ems.Listener.SimpleMessageListenerContainer, Spring.Messaging.Tibco.Ems">
<property name= "ConnectionFactory" ref= "connectionFactory" />
<property name= "PubSubDomain" value= "true" />
<property name= "DestinationName" value= "APP.STOCK" />
<property name= "ConcurrentConsumers" value= "1" />
<property name= "MessageListener" ref= "messageListenerAdapter" />
</object>

<object
id= "messageListenerAdapter"
type= "Spring.Messaging.Tibco.Ems.Listener.Adapter.MessageListenerAdapter, Spring.Messaging.Tibco.Ems" >
<property name= "DelegateObject" >
<object type= "Spring.JmsInterop.Handlers.SimpleHandler, Spring.JmsInterop" />
</property>
<property name= "DefaultListenerMethod" value= "HandleObject" />
</object>

请注意,Spring.NET使用XML元素“对象”而不是“ bean”来定义对象定义。 从.NET角度来看,处理程序对象的名称很不幸,为“ DelegateObject”。 此属性与.NET委托无关。

发送到客户端的所有数据都在JMS主题APP.STOCK上,并且从客户端发送到中间层的所有数据都在JMS队列APP.STOCK.REQUEST上。

发送JMS消息非常简单,如下所示,其中包含一些人为的市场数据

Map marketData = new HashMap();
marketData.Add("TICKER","CSCO");
marketData.Add("PRICE", new Float(23.54));
... jmsTemplate.send(marketData);

在接收方,处理在StockAppHandler的handle方法内完成。

public class SimpleHandler 
{
public void HandleObject( IDictionary data)
{
log.InfoFormat( "Received market data. Ticker = {0}, Price = {1}" , data[ "TICKER" ], data[ "PRICE" ]);
// forward to controller to update view
. . .

}
}

入门仅需最少的基础结构代码。 但是,虽然交换哈希表很容易并且开箱即用,但仅适用于最简单的互操作性方案。 我简单地表示少于〜5个数据交换,每个数据交换具有少于〜10个键值对。 无法扩展到更复杂的场景的原因很明显,数据协定过于松散,很难确保两层之间的键值对不存在不匹配。 一种更自然的方法是使用类来封装数据。 类本身可以在很大程度上确保数据内容的正确性,例如,通过提供参数化的构造函数,或通过使用第三方验证库。 除了验证问题,与引入散列表以满足MessageConverter的要求相比,直接处理中间层中用于业务处理的对象更加简单。 这样,为了直接使用对象,需要创建自定义消息转换器并将其插入Spring JMS基础架构。

使用自定义转换器

Spring的MessageConverter接口非常简单。 它仅包含下面显示的两种方法,

public interface IMessageConverter 
{
Message ToMessage( object objectToConvert, . Session session);
object FromMessage( Message message);
}

如果无法转换消息,则抛出MessageConversionException

我们将创建一个自定义消息转换器,以将交易创建请求消息从客户端发送到中间层。 TradeRequest类从填写交易时收集用户输入的信息,并且还包含一种验证方法。 TradeRequest类包含以下属性,符号,#份额,价格,OrderType,AccountName,操作(买/卖),requestid和用户名。 转换器实现很容易编写代码,因为它只是将这些属性添加到JMS MapMessage的相应字段中。 客户端上“ ToMessage”的实现如下所示。

public class TradeRequestConverter : IMessageConverter 
{
public Message ToMessage( object objectToConvert, Session session)
{
TradeRequest tradeRequest = objectToConvert as TradeRequest;
if (tradeRequest == null )
{
throw new MessageConversionException ( "TradeRequestConverter can not convert object of type " +
objectToConvert.GetType());
}
try
{
MapMessage mm = session.CreateMapMessage();
mm.SetString( "accountName" , tradeRequest.AccountName);
mm.SetBoolean( "buyRequest" , tradeRequest.BuyRequest);
mm.SetString( "orderType" , tradeRequest.OrderType);
mm.SetDouble( "price" , tradeRequest.Price);
mm.SetLong( "quantity" , tradeRequest.Quantity);
mm.SetString( "requestId" , tradeRequest.RequestId);
mm.SetString( "ticker" , tradeRequest.Ticker);
mm.SetString( "username" , tradeRequest.UserName);

return mm;

} catch ( Exception e)
{
throw new MessageConversionException ( "Could not convert TradeRequest to message" , e);
}
}

... (FromMessage not shown)
}

“ FromMessage”实现仅创建一个TradeRequest对象,并使用从消息中获取的值来设置其属性。 有关详细信息,请参见代码。 请注意,如果您使用属性来编组/解组数据,请确保在编组上下文中调用这些属性没有副作用。

要将数据从客户端发送到中间层,我们需要创建以前的JMS基础结构的镜像,客户端中的JmsTemplate和中间层中的SimpleMessageListenerContainer。 中间层的消息容器配置为使用Java版本的TradeRequestConverter和消息处理程序类StockAppHandler,该类具有方法“ void handle(TradeRequest)”。客户端配置如下所示。

<object name=" jmsTemplate " type=" Spring...JmsTemplate, Spring.Messaging.Tibco.Ems ">
<property name=" ConnectionFactory " ref=" connectionFactory "/>
<property name=" DefaultDestinationName " value="APP.STOCK.REQUEST"/>
<property name=" MessageConverter ">
<object type=" Spring.JmsInterop.Converters.TradeRequestConverter, Spring.JmsInterop "/>
</property>
</object>

模板对客户端的硬编码使用如下所示。

public void SendTradeRequest()
{
TradeRequest tradeRequest = new TradeRequest ();
tradeRequest.AccountName = " ACCT-123 ";
tradeRequest.BuyRequest = true ;
tradeRequest.OrderType = " MARKET ";
tradeRequest.Quantity = 314000000;
tradeRequest.RequestId = " REQ-1 ";
tradeRequest.Ticker = " CSCO ";
tradeRequest.UserName = " Joe Trader ";

jmsTemplate.ConvertAndSend(tradeRequest);
}

下面显示了在客户端上发送消息的顺序图:

下面显示了中间层配置以及POJO消息处理程序的简单实现。

<bean id=" jmsContainer " class=" org.springframework.jms.listener.SimpleMessageListenerContainer ">
<property name=" connectionFactory " ref=" connectionFactory "/>
<property name=" destinationName " value=" APP.STOCK.REQUEST "/>
<property name=" concurrentConsumers " value=" 10 "/>
<property name=" messageListener " ref=" messageListenerAdapter "/>
</bean>

<bean id=" messageListenerAdapter " class=" org.springframework.jms.listener.adapter.MessageListenerAdapter ">
<property name=" delegate ">
<bean class=" org.spring.jmsinterop.handlers.StockAppHandler "/>
</property>
<property name=" defaultListenerMethod " value=" handleObject "/>
<property name=" messageConverter ">
<bean class=" org.spring.jmsinterop.converters.TradeRequestConverter "/>
</property>
</bean>

public class StockAppHandler {
protected final Log logger = LogFactory.getLog(getClass());
public void handleObject(TradeRequest tradeRequest)
{
logger .info( "Recieved TradeRequest object" );
}
}

这种方法的优势在于,客户端和中间层开发人员可以实质上“共享”一个类,在本例中为TradeRequest,其中包含数据和功能。 共享类的一个缺点(尤其是在大型项目中)是创建一对业务对象和转换器时的重复工作。 如果层之间交换的数据相对稳定,则此重复可以被视为一次性成本。 但是,如果交换的数据每周(或每天)更改一次(如在主动开发过程中通常发生这种情况),那么它将成为一项繁琐的任务。

解决这些问题的有效方法是创建一个通用的MessageConverter,它可以处理多种消息类型,并使用Java编写一次业务对象,并使用源代码转换工具来获得等效的C#。 下一节将更详细地讨论这种方法。

通用消息转换器

正如您在TradeRequestConverter的上一个清单中看到的那样,该实现正在调用* not *进行手动编码。 可以改用使用代码生成或反射的解决方案。 该示例代码包括一个受“ XStream”启发的基于反射的转换器ReflectionMessageConverter,它可以转换各种对象。 该转换器具有以下功能和局限性。

  • 通过反射所有字段成员,所有对象均按值编组。 采取这种选择是为了避免由于附加代码可能驻留在属性设置器中而引起的任何副作用。 (添加支持以控制通过外部配置或类似于WCF的DataContract / DataMember属性的属性/注释来包括/排除哪些字段是一个不错的增强。)
  • 支持的字段类型包括:基元(int,字符串等),日期,时间戳以及由基元,哈希图和对象集合(非泛型)组成的对象。 检测到循环引用。
  • 线路表示形式是具有易于理解的格式的JMS MapMessage。 这允许其他不使用此转换器的进程轻松地参与JMS消息交换。
  • JMS提供程序必须支持嵌套的映射消息才能转换集合类。
  • 提供为任意对象类型注册其他转换器的功能。
  • .NET / Java之间的耦合减少,因为转换器不需要知道它们的alter-ego类型。 在消息中放置一个类型标识符,指示要创建的类型。 在每一侧,类型标识符都独立地映射到特定的数据类型。 为方便起见,所有业务对象均以类似的方式命名,但仅在名称空间/程序包方面有所不同的情况,使用最少的配置即可处理

转换器应被视为正在开发中,其更新将在Spring.NET网站上提供。

单个通用MessageConverter的其他替代方法是将艰苦的工作委托给现有的编组技术。 例如,您可以委派XML / Object转换器并发送XML字符串作为JMS消息的有效负载。 最近,Tangosol引入了一种平台和与语言无关的可移植对象格式(POF)作为Coherence的一部分,也可以用于相同的目的。

示例应用程序使用ReflectionMessageConverter将Trade对象发送到客户端以响应TradeRequest。 作为发送更复杂对象的示例,客户端发送一个PortfolioRequest,并将收到一个Portfolio对象,该对象包含一个User和作为响应的Trade对象列表。 转换器的配置如下所示。

<object name=" reflectionMessageConverter "
type=" Spring.JmsInterop.Converters.ReflectionMessageConverter, Spring.JmsInterop ">
property name=" ConversionContext " ref=" conversionContext "/>
</object>

<object name=" conversionContext " type=" Spring.JmsInterop.Converters.ConversionContext, Spring.JmsInterop ">
<property name=" TypeMapper " ref=" typeMapper "/>
</object>

<object name=" typeMapper " type=" Spring.JmsInterop.Converters.SimpleTypeMapper, Spring.JmsInterop ">

<!-- use simple configuation style -->
<property name=" DefaultNamespace " value=" Spring.JmsInterop.Bo "/>
<property name=" DefaultAssemblyName " value=" Spring.JmsInterop "/>

<!--
<property name="IdTypeMapping">
<dictionary>
<entry key="1" value="Spring.JmsInterop.Bo.Trade, Spring.JmsInterop"/>
</dictionary>
</property>

-->
</object>

上面使用的TypeMapper的简单配置样式使用完全限定类型名称的最后一部分作为类型标识符,该标识符在编组时放在网络上的消息中。 解组时,DefaultNamespace和DefaultAssemblyName属性用于构造完全限定的类型名称。 Java端对应的映射器定义如下所示。

<bean id="classMapper" class="org.spring.jmsinterop.converters.SimpleClassMapper">
<property name="defaultPackage" value="org.spring.jmsinterop.bo"/>

<!--
<property name="idClassMapping">
<map>
<entry key="1" value="org.spring.jmsinterop.bo.Trade"/>
</map>
</property>
-->


</bean>

IdTypeMapping / IdClassMapping属性(注释掉)显示了如何完全避免使用类名,以及如何使用任意标识符指定类型。

共享业务对象

一种可以减少使业务对象保持同步的工作的技术是使用Java语言转换器(JLCA)将Java类自动转换为C# 7 。 虽然此工具旨在用作Java代码库的“一次性”翻译,但可以将其合并到自动构建过程中,并用于在Java和.NET之间同步业务对象。 业务对象实际上是此转换器的一个很好的候选对象,因为它们不包含特定于技术的API,例如用于数据访问或Web编程的API,如果不进行后续手动调整,这些API很难正确转换。

但是,JLCA并非没有缺陷。 有很多限制和怪癖,但是您仍然可以创建复杂的C#类,而无需人工干预就可以成功地将它们转换为Java。 最引人注意的怪癖之一是方法名称保留为小写,但从正面来看,JavaBean get / set方法转换为.NET属性。 其他限制是注释不能转换为属性,并且不支持泛型。 命名空间保留为Java包名称,但是简单的正则表达式后处理可以轻松解决该问题。 如果需要,转换器还会创建一些支持类的C#实现,例如,等效于java.util.Set的C#。 通过一些试验,您将看到可以在自己的项目中使用该技术的程度。 Gaurav Seth的博客8上提供了概述转换器功能的“备忘单”。 关于JLCA信息的最后一个提示是,在JLCA背后的公司ArtinSoft还出售产品JLCA Companion,该产品可让您更改或添加转换规则9

在此示例中,在Java类上运行JLCA效果很好。 您可以通过在.NET解决方案中包含/排除“ Bo”和“ Jlca”目录来切换手工编码的C#业务对象和JLCA生成的对象的使用。 特别是在TradeRequest类中查找/修改验证方法,该方法使用简单的条件逻辑和集合类操作。 提供了一个ant脚本来在Java业务对象上运行JLCA并将包名称更改为正确的.NET名称空间。

接收到一些市场数据事件并发送TradeRequest和PortfolioRequest之后的客户的屏幕截图如下所示。

结论

如果您已经处于消息传递环境中,或者被异步通信和发布/订阅交付等消息传递功能所吸引,那么在Java和.NET中使用Spring的JMS支持将为您提供一个强大的起点来创建互操作解决方案。 Spring在确保JMS生产者和消费者之间的兼容性所用的合同方面不是很规范,但是它确实提供了一个简单的扩展点MessageConverter,供您介绍自己设计的合同。 转换器和关联对象的复杂程度应与应用程序的复杂性相匹配。 股票交易应用程序和ReflectionMessageConverter为您轻松进行实验奠定了基础。

重申对Spring框架的普遍描述-“它使简单的事情变得容易,而硬的事情变得可能”。 我希望您会同意,这也适用于混合.NET / Java环境中Spring的JMS支持。 归根结底,无论您选择哪种方式实现互操作性,都将发现在.NET和Java上同时使用Spring是有益的,因为可以轻松地在两个世界之间共享相同的编程模型和最佳实践。

可以在此处下载本文随附的源代码。


翻译自: https://www.infoq.com/articles/jms-spring-messaging-interop/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

spring jms 消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值