使用 Spring JMS

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

JmsTemplate

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

使用 the 的代码只需要实现提供它们的回调接口 明确定义的高级合同。回调接口会创建一个 消息。自 允许对 JMS API 进行更复杂的使用,提供 JMS 会话,并公开 and 对。JmsTemplateMessageCreatorSessionJmsTemplateSessionCallbackProducerCallbackSessionMessageProducerspring-doc.cn

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

某些 JMS 提供程序允许通过 的配置 .这具有对实例的 method () 的调用 使用的 QOS 默认值与 JMS 规范中指定的值不同。挨次 因此,为了提供对 QOS 值的一致管理,必须 通过将 boolean 属性设置为 .ConnectionFactoryMessageProducersendsend(Destination destination, Message message)JmsTemplateisExplicitQosEnabledtruespring-doc.cn

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

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

从 Spring Framework 4.1 开始,它构建在消息传递抽象之上并提供与消息传递抽象的集成,即 .这样,您就可以将消息创建到 以通用方式发送。JmsMessagingTemplateJmsTemplateorg.springframework.messaging.Messagespring-doc.cn

连接

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

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

缓存消息收发资源

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

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

在和操作之间,三个中间 对象被创建和销毁。优化资源使用并提高 性能,Spring 提供了 .ConnectionFactorySendConnectionFactoryspring-doc.cn

SingleConnectionFactory

Spring 提供了接口的实现,该接口在所有调用中返回相同的值,并忽略对 .这对于测试和 独立环境,以便同一连接可用于可能跨越任意数量的事务的多个调用。 引用通常来自 JNDI 的标准。ConnectionFactorySingleConnectionFactoryConnectioncreateConnection()close()JmsTemplateSingleConnectionFactoryConnectionFactoryspring-doc.cn

CachingConnectionFactory

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

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

目的地管理

作为实例,目标 是可以存储的 JMS 管理对象 并在 JNDI 中检索。在配置 Spring 应用程序上下文时,您可以使用 JNDI 工厂类或执行依赖项 注入对象对 JMS 目标的引用。但是,此策略 如果应用程序中有大量目标,或者存在 是 JMS 提供程序独有的高级目标管理功能。示例 此类高级目标管理包括创建动态目标或 支持目标的分层命名空间。委托 将目标名称解析为实现接口的 JMS 目标对象。 是默认值 implementation used by and accommodate 解析动态目标。还提供了 A 作为 destinations 包含在 JNDI 中,并且可以选择回退到 .ConnectionFactoryJndiObjectFactoryBean<jee:jndi-lookup>JmsTemplateDestinationResolverDynamicDestinationResolverJmsTemplateJndiDestinationResolverDynamicDestinationResolverspring-doc.cn

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

boolean 属性用于配置 了解正在使用的 JMS 域。默认情况下,此属性的值为 false,则表示使用点对点域 。此属性 (使用者 ) 通过以下方式确定动态目标解析的行为 接口的实现。pubSubDomainJmsTemplateQueuesJmsTemplateDestinationResolverspring-doc.cn

您还可以通过 财产。默认目标是发送和接收 不引用特定目标的操作。JmsTemplatedefaultDestinationspring-doc.cn

消息侦听器容器

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

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

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

SimpleMessageListenerContainer

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

虽然不允许外部参与 managed transactions,它确实支持本机 JMS 事务。要启用此功能, 您可以将标志切换到 XML,或者在 XML 命名空间中将属性设置为 。从侦听器引发的异常然后引导 进行回滚,并重新传递消息。或者,考虑使用 mode,它在出现异常时也提供重新传递,但 不使用事务处理实例,因此,在事务协议中不包括任何其他操作(例如发送响应消息)。SimpleMessageListenerContainersessionTransactedtrueacknowledgetransactedCLIENT_ACKNOWLEDGESessionSession
默认模式不提供适当的可靠性保证。 当侦听器执行失败时,消息可能会丢失(因为提供程序会自动 在侦听器调用后确认每条消息,没有要传播到的异常 提供程序)或侦听器容器关闭时(您可以通过设置 标志)。请确保在以下情况下使用事务处理会话 可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。AUTO_ACKNOWLEDGEacceptMessagesWhileStopping

DefaultMessageListenerContainer

此消息侦听器容器在大多数情况下使用。与 相反,此容器变体允许动态适应 满足运行时需求,并能够参与外部管理的事务。 当配置了 .因此,处理可能会利用 XA 事务 语义学。这个侦听器容器在 JMS 提供程序、高级功能(例如参与外部管理的 transactions 的 TRANSACTIONS 以及与 Jakarta EE 环境的兼容性。SimpleMessageListenerContainerJtaTransactionManagerspring-doc.cn

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

当代理出现故障时,此容器还具有可恢复功能。默认情况下, 简单实现每 5 秒重试一次。您可以指定 用于更精细恢复选项的自定义实现。有关示例,请参阅 ExponentialBackOffBackOffBackOffspring-doc.cn

与它的兄弟姐妹(SimpleMessageListenerContainer)一样,支持原生 JMS 事务并允许 自定义 acknowledgment 模式。如果对您的方案可行,则 This is strongly 推荐而不是外部管理的交易 — 也就是说,如果您能忍受 在 JVM 死亡的情况下偶尔出现重复消息。自定义重复消息 业务逻辑中的检测步骤可以涵盖此类情况 — 例如, 以业务实体存在检查或协议表检查的形式。 任何此类安排都比替代方案更有效: 使用 XA 事务包装整个处理(通过使用 配置) 以覆盖 接收 JMS 消息以及在您的 消息侦听器(包括数据库操作等)。DefaultMessageListenerContainerDefaultMessageListenerContainerJtaTransactionManager
默认模式不提供适当的可靠性保证。 当侦听器执行失败时,消息可能会丢失(因为提供程序会自动 在侦听器调用后确认每条消息,没有要传播到的异常 提供程序)或侦听器容器关闭时(您可以通过设置 标志)。请确保在以下情况下使用事务处理会话 可靠性需求(例如,用于可靠的队列处理和持久主题订阅)。AUTO_ACKNOWLEDGEacceptMessagesWhileStopping

事务管理

Spring 提供了一个 Management 单个 JMS 的事务。这允许 JMS 应用程序利用托管事务 Spring 的功能,如 Data Access 一章的 Transaction Management 部分所述。 执行本地资源事务,绑定 JMS 从指定到线程的 Connection/Session 对。 自动检测此类事务性资源并运行 相应地对他们。JmsTransactionManagerConnectionFactoryJmsTransactionManagerConnectionFactoryJmsTemplatespring-doc.cn

在 Jakarta EE 环境中,池 Connection 和 Session 实例 因此,这些资源可以在事务中有效地重用。在独立环境中, 在共享的 JMS 中使用 Spring 的结果,其中 每个事务都有自己独立的 .或者,考虑使用 特定于提供程序的池适配器,例如 ActiveMQ 的类。ConnectionFactorySingleConnectionFactoryConnectionSessionPooledConnectionFactoryspring-doc.cn

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

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