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