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