此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
使用 Spring JMS
本节介绍如何使用 Spring 的 JMS 组件。
JmsTemplate
和JmsClient
这JmsTemplate
class 是 JMS 核心包中的中心类。它简化了JMS 的使用,因为它在发送或同步接收消息时处理资源的创建和释放。
JmsClient
是 Spring Framework 7.0 中的一个新 API 变体,遵循JdbcClient
和公司。JmsClient
建立在JmsTemplate
用于直接发送并接收每个作的自定义选项。
用JmsTemplate
使用JmsTemplate
只需要实现回调接口,为它们提供一个明确定义的高级合约。 这MessageCreator
callback 接口会创建一个message 当给定Session
由调用代码提供JmsTemplate
. 自 允许更复杂的 JMS API 使用,SessionCallback
提供JMS 会话,以及ProducerCallback
公开一个Session
和MessageProducer
双。
JMS API 公开了两种类型的发送方法,一种采用交付模式、优先级、和生存时间作为服务质量 (QOS) 参数,另一种不采用 QOS参数并使用默认值。 因为JmsTemplate
有许多发送方法,设置 QOS 参数已作为 bean 属性公开为避免发送方法数量重复。同样,的超时值同步接收调用是通过使用setReceiveTimeout
财产。
一些 JMS 提供程序允许通过配置的ConnectionFactory
. 这具有调用MessageProducer
实例的send
方法 (send(Destination destination, Message message)
) 使用与 JMS 规范中指定的 QOS 默认值不同的 QOS 默认值。 挨次 为了提供对 QOS 值的一致管理,请JmsTemplate
因此,必须是通过设置布尔属性专门启用以使用自己的 QOS 值isExplicitQosEnabled
自true
.
为方便起见,JmsTemplate
还公开了一个基本的请求-回复作,该作允许发送消息并在临时队列上等待回复,该队列是作为作的一部分创建的。
的实例JmsTemplate 一旦配置,类是线程安全的。 这是 重要,因为这意味着您可以配置JmsTemplate 然后将此共享引用安全地注入多个协作者。要成为clear,则JmsTemplate 是有状态的,因为它维护对ConnectionFactory ,但这种状态不是对话状态。 |
用JmsClient
从 Spring Framework 4.1 开始,JmsMessagingTemplate
建立在JmsTemplate
并提供与 Spring 的通用消息抽象的集成——即 处理org.springframework.messaging.Message
用于发送和接收, 扔org.springframework.messaging.MessagingException
并带有有效载荷转换通过org.springframework.messaging.converter.MessageConverter
(有许多可用的常见转换器实现)。
从 Spring Framework 7.0 开始,一个名为JmsClient
可用。这提供了可自定义的作org.springframework.messaging.Message
和投掷org.springframework.messaging.MessagingException
似JmsMessagingTemplate
, 以及与org.springframework.messaging.converter.MessageConverter
. 一个JmsClient can either be created for a given `ConnectionFactory
或给定JmsTemplate
,在后一种情况下,默认情况下重用其设置。 看JmsClient
有关用法示例。
连接
这JmsTemplate
需要引用ConnectionFactory
. 这ConnectionFactory
是 JMS 规范的一部分,用作使用 JMS 的入口点。 它 被客户端应用程序用作工厂来创建与 JMSprovider 的连接,并封装各种配置参数,其中许多是特定于提供商的,例如 SSL 配置选项。
在 EJB 中使用 JMS 时,提供商提供了 JMS 接口的实现以便它们可以参与声明性事务管理并执行池化连接和会话。为了使用此实现,Jakarta EE 容器通常要求您将 JMS 连接工厂声明为resource-ref
里面
EJB 或 Servlet 部署描述符。为确保将这些功能与JmsTemplate
在 EJB 中,客户端应用程序应确保它引用
托管实现ConnectionFactory
.
缓存消息传递资源
标准 API 涉及创建许多中间对象。要发送消息,请 执行以下“API”遍历:
ConnectionFactory->Connection->Session->MessageProducer->send
在ConnectionFactory
和Send
作,三中级
对象被创建和销毁。优化资源使用并增加
performance,Spring 提供了两个ConnectionFactory
.
用SingleConnectionFactory
Spring 提供了ConnectionFactory
接口SingleConnectionFactory
,返回相同的Connection
在所有createConnection()
调用并忽略对close()
.这对于测试和
独立环境,以便同一连接可用于多个JmsTemplate
可以跨越任意数量事务的调用。SingleConnectionFactory
引用标准ConnectionFactory
这通常来自 JNDI。
用CachingConnectionFactory
这CachingConnectionFactory
扩展了SingleConnectionFactory
并添加Session
,MessageProducer
和MessageConsumer
实例。
初始缓存大小设置为1
.您可以使用sessionCacheSize
属性设置为
增加缓存的会话数。请注意,实际缓存的会话数
大于该数字,因为会话是根据其确认模式缓存的,
因此,最多可以有四个缓存的会话实例(每种确认模式一个)
什么时候sessionCacheSize
设置为 1。MessageProducer
和MessageConsumer
实例
缓存在它们拥有的会话中,并且还考虑了唯一的属性
缓存时生产者和消费者。MessageProducer 根据其
目的地。MessageConsumers 基于由目标、选择器、
noLocal 传递标志和持久订阅名称(如果创建持久使用者)。
用于临时队列和主题的 MessageProducers 和 MessageConsumers
(TemporaryQueue/TemporaryTopic) 永远不会被缓存。不幸的是,WebLogic JMS 发生了
要在其常规目标实现上实现临时队列/主题接口,
错误地指示其任何目标都无法缓存。请使用其他连接
pool/cache 在 WebLogic 上,或自定义 |
目的地管理
目的地,如ConnectionFactory
instances 是可以存储的 JMS 管理对象
并在 JNDI 中检索。配置 Spring 应用程序上下文时,您可以使用
JNDI公司JndiObjectFactoryBean
工厂类或<jee:jndi-lookup>
执行依赖关系
注入到对象对 JMS 目标的引用上。然而,这种策略
如果应用程序中有大量目的地,或者如果
是 JMS 提供程序独有的高级目标管理功能。示例
此类高级目标管理包括创建动态目标或
支持目标的分层命名空间。这JmsTemplate
委托
将目标名称解析为 JMS 目标对象,该对象实现了DestinationResolver
接口。DynamicDestinationResolver
是默认值
实现JmsTemplate
并适应解析动态目的地。一个JndiDestinationResolver
还提供作为服务定位器
destinations 包含在 JNDI 中,并可选择回退到DynamicDestinationResolver
.
很多时候,JMS 应用程序中使用的目的地仅在运行时为人所知,并且,
因此,在部署应用程序时无法以管理方式创建。这是
通常是因为交互的系统组件之间存在共享的应用程序逻辑
根据众所周知的命名约定在运行时创建目标。甚至
尽管动态目标的创建不是 JMS 规范的一部分,但大多数
提供商已提供此功能。动态目标使用用户定义的名称
这使他们与临时目的地区分开来,并且通常是
未在 JNDI 中注册。用于创建动态目标的API因提供程序而异
to provider,因为与目标关联的属性是特定于提供商的。
但是,提供商有时会做出一个简单的实现选择是
忽略 JMS 规范中的警告,并使用TopicSession
createTopic(String topicName)
或QueueSession
createQueue(String
queueName)
方法,以创建具有默认目标属性的新目标。取决于
在提供商实施方面,DynamicDestinationResolver
然后还可以创建一个
物理目标,而不是仅解析一个目标。
布尔属性pubSubDomain
用于配置JmsTemplate
跟
了解正在使用的 JMS 域。默认情况下,此属性的值为
false,表示点对点域Queues
,将被使用。此属性
(使用JmsTemplate
) 通过
的实现DestinationResolver
接口。
您还可以配置JmsTemplate
通过
财产defaultDestination
.默认目标为发送和接收
不引用特定目标的作。
消息侦听器容器
JMS 消息在 EJB 世界中最常见的用途之一是驱动消息驱动
Beans(MDB)。Spring 提供了一种解决方案,以某种方式创建消息驱动的 POJO (MDP)
这不会将用户绑定到 EJB 容器。(有关 Spring 的 MDP 支持的详细介绍,请参阅异步接收:消息驱动的 POJO。端点方法可以使用@JmsListener
— 有关更多详细信息,请参阅注释驱动的侦听器端点。
消息侦听器容器用于从 JMS 消息队列接收消息,并且
驱动MessageListener
被注入其中。侦听器容器是
负责消息接收和调度到侦听器中的所有线程,以便
加工。消息侦听器容器是 MDP 和
消息传递提供商,并负责注册以接收消息,参与
事务、资源获取和释放、异常转换等。这
允许您编写(可能复杂的)业务逻辑
与接收消息(并可能响应消息)相关联,以及委托
样板 JMS 基础设施对框架的关注。
有两个标准的 JMS 消息监听器容器与 Spring 打包在一起,每个容器都带有 其专业功能集。
用SimpleMessageListenerContainer
此消息侦听器容器是两种标准风格中较简单的一种。它创造了
启动时固定数量的 JMS 会话和使用者,使用
标准 JMSMessageConsumer.setMessageListener()
方法,并将其留在 JMS 中
provider 来执行侦听器回调。此变体不允许动态适应
到运行时需求或参与外部管理的交易。
在兼容性方面,它非常接近独立 JMS 的精神
规范,但通常与 Jakarta EE 的 JMS 限制不兼容。
而SimpleMessageListenerContainer 不允许参与外部托管事务,它确实支持原生 JMS 事务。要启用此功能,您可以将sessionTransacted flag 到true 或者,在 XML 命名空间中,将acknowledge 属性设置为transacted . 然后,从侦听器抛出的异常会导致回滚,并重新传递消息。或者,考虑使用CLIENT_ACKNOWLEDGE 模式,它在异常情况下也提供重新交付,但不使用 transactedSession 实例,因此不包括任何其他Session 交易协议中的作(例如发送响应消息)。 |
默认值AUTO_ACKNOWLEDGE 模式不提供适当的可靠性保证。当侦听器执行失败时,消息可能会丢失(因为提供者自动在侦听器调用后确认每条消息,没有例外要传播到提供者)或当侦听器容器关闭时(您可以通过设置 这acceptMessagesWhileStopping 标志)。确保在出现以下情况时使用事务会话可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。 |
用DefaultMessageListenerContainer
在大多数情况下,都会使用此消息侦听器容器。与SimpleMessageListenerContainer
,这种容器变体允许动态适应
满足运行时需求,并能够参与外部管理的交易。
当配置JtaTransactionManager
.因此,处理可能会利用 XA 事务
语义学。这个监听器容器在低要求之间取得了很好的平衡
JMS 提供程序,高级功能(例如参与外部管理
事务),以及与雅加达 EE 环境的兼容性。
您可以自定义容器的缓存级别。请注意,当未启用缓存时, 为每个消息接收创建一个新连接和一个新会话。结合这些 使用高负载的非持久订阅可能会导致消息丢失。确保 在这种情况下,请使用适当的缓存级别。
当代理出现故障时,此容器还具有可恢复的功能。默认情况下,
一个简单的BackOff
实现每五秒重试一次。您可以指定
一个习惯BackOff
实现更细粒度的恢复选项。看ExponentialBackOff
举个例子。
与它的兄弟姐妹一样 (SimpleMessageListenerContainer ),DefaultMessageListenerContainer 支持本机 JMS 事务并允许
自定义确认模式。如果对你的方案可行,这是非常
推荐而不是外部管理的交易——也就是说,如果您能忍受
偶尔出现重复消息,以防 JVM 死亡。自定义重复消息
业务逻辑中的检测步骤可以涵盖此类情况,例如,
以业务实体存在检查或协议表检查的形式。
任何此类安排都比替代方案效率高得多:
使用 XA 事务包装整个处理(通过配置DefaultMessageListenerContainer 使用JtaTransactionManager ) 来涵盖JMS 消息的接收以及消息侦听器中业务逻辑的执行(包括数据库作等)。 |
默认值AUTO_ACKNOWLEDGE 模式不提供适当的可靠性保证。当侦听器执行失败时,消息可能会丢失(因为提供者自动在侦听器调用后确认每条消息,没有例外要传播到提供者)或当侦听器容器关闭时(您可以通过设置 这acceptMessagesWhileStopping 标志)。确保在出现以下情况时使用事务会话可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。 |
事务管理
Spring 提供了一个JmsTransactionManager
管理单个 JMS 的事务ConnectionFactory
. 这允许 JMS 应用程序利用托管事务Spring 的功能,如数据访问一章的事务管理部分所述。 这JmsTransactionManager
执行本地资源事务,绑定 JMS连接/会话对ConnectionFactory
到线程。JmsTemplate
自动检测此类事务资源并相应地作在他们身上。
在 Jakarta EE 环境中,ConnectionFactory
pools Connection 和 Session 实例,因此这些资源可以在事务之间有效地重用。在独立环境中,使用 Spring 的SingleConnectionFactory
导致共享 JMSConnection
跟 每个事务都有自己的独立Session
. 或者,考虑使用特定于提供商的池适配器,例如 ActiveMQ 的PooledConnectionFactory
类。
您还可以使用JmsTemplate
使用JtaTransactionManager
以及支持 XA 的 JMSConnectionFactory
来执行分布式事务。请注意,这需要使用 JTA 事务管理器以及正确配置的 XA ConnectionFactory。(查看您的 Jakarta EE 服务器或 JMS 提供商的文档。
在托管和非托管事务环境中重用代码可能会造成混淆
使用 JMS API 创建Session
从Connection
.这是因为
JMS API 只有一个工厂方法来创建Session
,并且它需要
事务和确认模式。在托管环境中,设置这些值是
环境事务基础设施的责任,因此这些价值观
被提供商的 JMS 连接包装器忽略。当您使用JmsTemplate
在非托管环境中,您可以通过使用
性能sessionTransacted
和sessionAcknowledgeMode
.当您使用PlatformTransactionManager
跟JmsTemplate
,则模板始终被赋予一个
事务性 JMSSession
.