使用 Spring JMS
本节介绍如何使用 Spring 的 JMS 组件。
用JmsTemplate
这JmsTemplateclass 是 JMS 核心包中的中心类。它简化了
使用 JMS,因为它在发送或
同步接收消息。
使用JmsTemplate只需要实现回调接口,为它们提供
明确定义的高级合同。这MessageCreatorcallback 接口会创建一个
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实例的sendmethod (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.您可以使用sessionCacheSizeproperty 设置为
增加缓存会话的数量。请注意,实际缓存的会话数
大于该数字,因为会话是根据其确认模式缓存的,
因此,最多可以有四个缓存的 Session 实例(每个确认模式一个)
什么时候sessionCacheSize设置为 1。MessageProducer和MessageConsumer实例
缓存在其拥有的会话中,并且还考虑了唯一属性
的创建者和使用者。MessageProducers 根据其
目的地。MessageConsumers 基于由目标、选择器、
noLocal delivery 标志和持久订阅名称(如果创建持久使用者)。
|
临时队列和主题的 MessageProducers 和 MessageConsumers
(TemporaryQueue/TemporaryTopic) 永远不会被缓存。不幸的是,WebLogic JMS 发生了
要在其常规目标实现上实现临时 queue/topic 接口,
错误地表示无法缓存其任何目标。请使用其他连接
pool/cache 的 webLogic,或自定义 |
目的地管理
Destinations 的ConnectionFactoryinstances)是您可以存储的 JMS 受管理对象
并在 JNDI 中检索。在配置 Spring 应用程序上下文时,您可以使用
JNDIJndiObjectFactoryBeanfactory 类或<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 容器。(参见异步接收:消息驱动的 POJOs,以详细了解 Spring 的 MDP 支持。端点方法可以用@JmsListener— 有关更多详细信息,请参阅 Annotation-driven Listener Endpoints 。
消息侦听器容器用于从 JMS 消息队列接收消息,并且
驱动MessageListener被注入其中。侦听器容器是
负责将消息接收和分派的所有线程线程化到侦听器中
加工。消息侦听器容器是 MDP 和
消息传递提供商,并负责注册以接收消息、参与
事务、资源获取和释放、异常转换等。这
允许您编写(可能很复杂的)业务逻辑
与接收消息(并可能响应消息)相关联,并委托
框架的样板 JMS 基础设施问题。
有两个与 Spring 打包在一起的标准 JMS 消息侦听器容器,每个容器都带有 它的专业功能集。
用SimpleMessageListenerContainer
此消息侦听器容器是两种标准风格中较简单的一种。它创建
启动时固定数量的 JMS 会话和使用者,使用
标准 JMSMessageConsumer.setMessageListener()方法,并将其留给 JMS
provider 执行侦听器回调。此变体不允许动态适应
运行时需求或参与外部管理的事务。
在兼容性方面,它非常接近独立 JMS 的精神
规范,但通常与 Jakarta EE 的 JMS 限制不兼容。
而SimpleMessageListenerContainer不允许外部参与
managed transactions,它确实支持本机 JMS 事务。要启用此功能,
您可以将sessionTransactedflag 设置为true或者,在 XML 命名空间中,将acknowledge属性设置为transacted.从侦听器引发的异常然后引导
进行回滚,并重新传递消息。或者,考虑使用CLIENT_ACKNOWLEDGE模式,该模式在出现异常时也提供重新传递,但
不使用 transactedSession实例,因此不包括任何其他Session作(例如发送响应消息)。 |
默认的AUTO_ACKNOWLEDGEmode 不提供适当的可靠性保证。
当侦听器执行失败时,消息可能会丢失(因为提供程序会自动
在侦听器调用后确认每条消息,没有要传播到的异常
提供程序)或侦听器容器关闭时(您可以通过设置
这acceptMessagesWhileStopping标志)。请确保在以下情况下使用事务处理会话
可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。 |
用DefaultMessageListenerContainer
此消息侦听器容器在大多数情况下使用。与SimpleMessageListenerContainer,此容器变体允许动态适应
满足运行时需求,并能够参与外部管理的事务。
当配置了JtaTransactionManager.因此,处理可能会利用 XA 事务
语义学。这个侦听器容器在
JMS 提供程序、高级功能(例如参与外部管理的
transactions 的 TRANSACTIONS 以及与 Jakarta EE 环境的兼容性。
您可以自定义容器的缓存级别。请注意,当未启用缓存时, 将为每个消息回执创建一个新连接和一个新会话。结合这个 对于具有高负载的非持久订阅,可能会导致消息丢失。请确保 在这种情况下,请使用适当的缓存级别。
当代理宕机时,此容器还具有可恢复功能。默认情况下,
一个简单的BackOffimplementation 每 5 秒重试一次。您可以指定
自定义BackOffimplementation 以获取更精细的恢复选项。看ExponentialBackOff例如。
就像它的兄弟姐妹 (SimpleMessageListenerContainer),DefaultMessageListenerContainer支持本机 JMS 事务,并允许
自定义 acknowledgment 模式。如果对您的方案可行,则 This is strongly
推荐而不是外部管理的交易 — 也就是说,如果您能忍受
在 JVM 死亡的情况下偶尔出现重复消息。自定义重复消息
业务逻辑中的检测步骤可以涵盖此类情况 — 例如,
以业务实体存在检查或协议表检查的形式。
任何此类安排都比替代方案更有效:
使用 XA 事务包装整个处理(通过配置DefaultMessageListenerContainer替换为JtaTransactionManager) 覆盖
收到 JMS 消息,并在
消息侦听器(包括数据库作等)。 |
默认的AUTO_ACKNOWLEDGEmode 不提供适当的可靠性保证。
当侦听器执行失败时,消息可能会丢失(因为提供程序会自动
在侦听器调用后确认每条消息,没有要传播到的异常
提供程序)或侦听器容器关闭时(您可以通过设置
这acceptMessagesWhileStopping标志)。请确保在以下情况下使用事务处理会话
可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。 |
事务管理
Spring 提供了一个JmsTransactionManager管理单个 JMS 的事务ConnectionFactory.这允许 JMS 应用程序利用托管事务
Spring 的功能,如 Data Access 一章的 Transaction Management 部分所述。
这JmsTransactionManager执行本地资源事务,绑定 JMS
来自指定ConnectionFactory到线程。JmsTemplate自动检测此类事务性资源并运行
相应地对他们。
在 Jakarta EE 环境中,ConnectionFactorypools 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.