使用 Spring JMS

本节介绍如何使用 Spring 的 JMS 组件。spring-doc.cadn.net.cn

JmsTemplate

JmsTemplateclass 是 JMS 核心包中的中心类。它简化了 使用 JMS,因为它在发送或 同步接收消息。spring-doc.cadn.net.cn

使用JmsTemplate只需要实现回调接口,为它们提供 明确定义的高级合同。这MessageCreatorcallback 接口会创建一个 message 时Session由 中的调用代码提供JmsTemplate.自 允许对 JMS API 进行更复杂的使用,SessionCallback提供 JMS 会话和ProducerCallback暴露一个SessionMessageProducer双。spring-doc.cadn.net.cn

JMS API 公开了两种类型的 send 方法,一种采用 delivery mode、priority 和 和 time to live 作为服务质量 (QOS) 参数,并且不采用 QOS 参数并使用默认值。因为JmsTemplate具有许多 send 方法, 设置 QOS 参数已作为 Bean 属性公开给 避免 send 方法的数量重复。同样,的 同步接收调用是使用setReceiveTimeout财产。spring-doc.cadn.net.cn

某些 JMS 提供程序允许通过 的配置ConnectionFactory.这具有对MessageProducer实例的sendmethod (send(Destination destination, Message message)) 使用的 QOS 默认值与 JMS 规范中指定的值不同。挨次 为了提供对 QOS 值的一致管理,JmsTemplate因此,必须是 通过设置 boolean 属性,专门启用以使用自己的 QOS 值isExplicitQosEnabledtrue.spring-doc.cadn.net.cn

为方便起见,JmsTemplate还公开了一个基本的 request-reply作,该作允许 发送消息并等待临时队列的回复,该队列是作为 的一部分创建的 作。spring-doc.cadn.net.cn

的实例JmsTemplate类是线程安全的,一旦配置。这是 重要,因为这意味着您可以配置JmsTemplate然后安全地将此共享引用注入多个协作者。成为 clear 的JmsTemplate是有状态的,因为它维护了对ConnectionFactory,但此状态不是会话状态。

从 Spring Framework 4.1 开始,JmsMessagingTemplate建立在JmsTemplate并提供与消息传递抽象的集成 — 即org.springframework.messaging.Message.这样,您就可以将消息创建到 以通用方式发送。spring-doc.cadn.net.cn

连接

JmsTemplate需要引用ConnectionFactory.这ConnectionFactory是 JMS 规范的一部分,用作使用 JMS 的入口点。它 被客户端应用程序用作工厂来创建与 JMS 的连接 provider 并封装各种配置参数,其中许多是 特定于供应商的,例如 SSL 配置选项。spring-doc.cadn.net.cn

在 EJB 中使用 JMS 时,供应商提供 JMS 接口的实现 以便它们可以参与声明式事务管理并执行池化 连接和会话。为了使用此实现,Jakarta EE 容器 通常要求您将 JMS 连接工厂声明为resource-ref里面 EJB 或 Servlet 部署描述符。要确保将这些功能与JmsTemplate在 EJB 中,客户端应用程序应确保它引用了 managed 实现ConnectionFactory.spring-doc.cadn.net.cn

缓存消息收发资源

标准 API 涉及创建许多中间对象。要发送消息, 执行以下 'API' 遍历:spring-doc.cadn.net.cn

ConnectionFactory->Connection->Session->MessageProducer->send

ConnectionFactorySend作,三个中间 对象被创建和销毁。优化资源使用并提高 性能,Spring 提供了ConnectionFactory.spring-doc.cadn.net.cn

SingleConnectionFactory

Spring 提供了ConnectionFactory接口SingleConnectionFactory,这将返回相同的Connection在所有createConnection()调用并忽略对close().这对于测试和 独立环境,以便同一连接可用于多个JmsTemplate可以跨越任意数量的事务的调用。SingleConnectionFactory引用标准ConnectionFactory这通常来自 JNDI。spring-doc.cadn.net.cn

CachingConnectionFactory

CachingConnectionFactory扩展了SingleConnectionFactory并添加Session,MessageProducerMessageConsumer实例。 初始缓存大小设置为1.您可以使用sessionCacheSizeproperty 设置为 增加缓存会话的数量。请注意,实际缓存的会话数 大于该数字,因为会话是根据其确认模式缓存的, 因此,最多可以有四个缓存的 Session 实例(每个确认模式一个) 什么时候sessionCacheSize设置为 1。MessageProducerMessageConsumer实例 缓存在其拥有的会话中,并且还考虑了唯一属性 的创建者和使用者。MessageProducers 根据其 目的地。MessageConsumers 基于由目标、选择器、 noLocal delivery 标志和持久订阅名称(如果创建持久使用者)。spring-doc.cadn.net.cn

临时队列和主题的 MessageProducers 和 MessageConsumers (TemporaryQueue/TemporaryTopic) 永远不会被缓存。不幸的是,WebLogic JMS 发生了 要在其常规目标实现上实现临时 queue/topic 接口, 错误地表示无法缓存其任何目标。请使用其他连接 pool/cache 的 webLogic,或自定义CachingConnectionFactory用于 WebLogic 目的。spring-doc.cadn.net.cn

目的地管理

Destinations 的ConnectionFactoryinstances)是您可以存储的 JMS 受管理对象 并在 JNDI 中检索。在配置 Spring 应用程序上下文时,您可以使用 JNDIJndiObjectFactoryBeanfactory 类或<jee:jndi-lookup>执行依赖关系 注入对象对 JMS 目标的引用。但是,此策略 如果应用程序中有大量目标,或者存在 是 JMS 提供程序独有的高级目标管理功能。示例 此类高级目标管理包括创建动态目标或 支持目标的分层命名空间。这JmsTemplate委托 将目标名称解析为实现DestinationResolver接口。DynamicDestinationResolver是默认值 使用JmsTemplate并容纳解析动态目标。一个JndiDestinationResolver还提供了作为 目标,并且可以选择回退到 JNDI 中包含的行为DynamicDestinationResolver.spring-doc.cadn.net.cn

通常,JMS 应用程序中使用的目的地仅在运行时才知道,并且 因此,在部署应用程序时无法以管理方式创建。这是 通常是因为交互的系统组件之间存在共享的应用程序逻辑 ,它们根据众所周知的命名约定在运行时创建目标。甚至 尽管创建动态目标不是 JMS 规范的一部分,但大多数 供应商已提供此功能。动态目标是使用用户定义的名称创建的。 这使它们与临时目的地区分开来,并且通常是 未在 JNDI 中注册。用于创建动态目标的 API 因提供商而异 to provider,因为与目标关联的属性是特定于供应商的。 但是,供应商有时会做出一个简单的实现选择,即 忽略 JMS 规范中的警告,并使用TopicSession createTopic(String topicName)QueueSession createQueue(String queueName)方法创建具有默认目标属性的新目标。取决于 在 vendor 实现上,DynamicDestinationResolver然后还可以创建一个 physical destination 而不是仅解析一个。spring-doc.cadn.net.cn

布尔属性pubSubDomain用于配置JmsTemplate跟 了解正在使用的 JMS 域。默认情况下,此属性的值为 false,则表示点对点域Queues,将被使用。此属性 (使用者JmsTemplate) 通过以下方式确定动态目标解析的行为 的DestinationResolver接口。spring-doc.cadn.net.cn

您还可以配置JmsTemplate替换为默认目标。 财产defaultDestination.默认目标是发送和接收 不引用特定目标的作。spring-doc.cadn.net.cn

消息侦听器容器

在 EJB 世界中,JMS 消息最常见的用途之一是驱动消息驱动的 Beans (MDB)。Spring 提供了一种解决方案,以某种方式创建消息驱动的 POJO (MDP) 不会将用户绑定到 EJB 容器。(有关详细信息,请参阅 异步接收:消息驱动的 POJO Spring 的 MDP 支持覆盖率。从 Spring Framework 4.1 开始,端点方法可以 注解@JmsListener— 有关更多详细信息,请参阅 Annotation-driven Listener Endpointsspring-doc.cadn.net.cn

消息侦听器容器用于从 JMS 消息队列接收消息,并且 驱动MessageListener被注入其中。侦听器容器是 负责将消息接收和 dispatch 的所有线程处理到侦听器中 加工。消息侦听器容器是 MDP 和 消息传递提供商,并负责注册以接收消息、参与 事务、资源获取和释放、异常转换等。这 允许您编写(可能很复杂的)业务逻辑 与接收消息(并可能响应消息)相关联,并委托 框架的样板 JMS 基础设施问题。spring-doc.cadn.net.cn

有两个与 Spring 打包在一起的标准 JMS 消息侦听器容器,每个容器都带有 它的专业功能集。spring-doc.cadn.net.cn

SimpleMessageListenerContainer

此消息侦听器容器是两种标准风格中较简单的一种。它创建 启动时固定数量的 JMS 会话和使用者,使用 标准 JMSMessageConsumer.setMessageListener()方法,并将其留给 JMS provider 执行侦听器回调。此变体不允许动态适应 运行时需求或参与外部管理的事务。 在兼容性方面,它非常接近独立 JMS 的精神 规范,但通常与 Jakarta EE 的 JMS 限制不兼容。spring-doc.cadn.net.cn

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 环境的兼容性。spring-doc.cadn.net.cn

您可以自定义容器的缓存级别。请注意,当未启用缓存时, 将为每个消息接收创建一个新连接和一个新会话。结合这个 对于具有高负载的非持久订阅,可能会导致消息丢失。请确保 在这种情况下,请使用适当的缓存级别。spring-doc.cadn.net.cn

当代理出现故障时,此容器还具有可恢复功能。默认情况下, 一个简单的BackOffimplementation 每 5 秒重试一次。您可以指定 自定义BackOffimplementation 以获取更精细的恢复选项。看ExponentialBackOff例如。spring-doc.cadn.net.cn

就像它的兄弟姐妹 (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自动检测此类事务性资源并运行 相应地对他们。spring-doc.cadn.net.cn

在 Jakarta EE 环境中,ConnectionFactorypools Connection 和 Session 实例, 因此,这些资源可以在事务中有效地重用。在独立环境中, 使用 Spring 的SingleConnectionFactory在共享 JMS 中生成Connection跟 每笔交易都有自己独立的Session.或者,考虑使用 特定于提供程序的池适配器(例如 ActiveMQ 的PooledConnectionFactory类。spring-doc.cadn.net.cn

您还可以使用JmsTemplate使用JtaTransactionManager以及支持 XA 的 JMSConnectionFactory执行分布式事务。请注意,这需要 使用 JTA 事务管理器以及正确配置的 XA ConnectionFactory。 (请查看 Jakarta EE 服务器或 JMS 提供商的文档。spring-doc.cadn.net.cn

在托管和非托管事务环境中重用代码可能会令人困惑 使用 JMS API 创建SessionConnection.这是因为 JMS API 只有一个工厂方法来创建一个Session,并且它需要 transaction 和 acknowledgment 模式。在托管环境中,设置这些值为 环境的事务性基础设施的责任,因此这些值 被供应商的 JMS Connection 包装器忽略。当您使用JmsTemplate在非托管环境中,您可以通过使用 性能sessionTransactedsessionAcknowledgeMode.当您使用PlatformTransactionManagerJmsTemplate,模板始终会得到一个 事务性 JMSSession.spring-doc.cadn.net.cn


APP信息