跳到主要内容

JMS

DeepSeek V3 中英对照 JMS

ConnectionFactory 接口提供了创建 Connection 的标准方法,用于与 JMS 代理进行交互。尽管 Spring 需要一个 ConnectionFactory 来与 JMS 协同工作,但通常您不需要直接使用它,而是可以依赖更高级别的消息抽象。(详情请参阅 Spring 框架参考文档的相关章节。)Spring Boot 还会自动配置发送和接收消息所需的基础设施。

ActiveMQ "经典" 版支持

ActiveMQ "Classic" 在类路径上可用时,Spring Boot 可以配置一个 ConnectionFactory。如果代理存在,则会自动启动并配置一个嵌入式代理(前提是没有通过配置指定代理 URL 并且嵌入式代理在配置中未被禁用)。

备注

如果你使用 spring-boot-starter-activemq,那么连接 ActiveMQ "Classic" 实例所需的依赖项将会被提供,同时也会提供与 JMS 集成的 Spring 基础设施。在你的应用程序中添加 org.apache.activemq:activemq-broker 可以让你使用嵌入式的 broker。

ActiveMQ "Classic" 的配置由 spring.activemq.* 中的外部配置属性控制。

如果 activemq-broker 在类路径上,ActiveMQ "Classic" 会自动配置为使用 VM 传输,这会在同一个 JVM 实例中启动一个嵌入式代理。

你可以通过配置 spring.activemq.embedded.enabled 属性来禁用嵌入式代理,如下例所示:

spring.activemq.embedded.enabled=false
properties

如果配置了代理 URL,嵌入式代理也将被禁用,如下例所示:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret
properties

如果你想完全控制嵌入的代理,请参阅 ActiveMQ "Classic" 文档 了解更多信息。

默认情况下,CachingConnectionFactory 会包装原生的 ConnectionFactory,并提供合理的设置,这些设置可以通过 spring.jms.* 的外部配置属性进行控制:

spring.jms.cache.session-cache-size=5
properties

如果你更倾向于使用原生的连接池,可以通过添加 org.messaginghub:pooled-jms 依赖并相应地配置 JmsPoolConnectionFactory 来实现,如下例所示:

spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
properties
提示

更多支持的选项请参见 ActiveMQProperties。您还可以注册任意数量的实现 ActiveMQConnectionFactoryCustomizer 的 bean 以进行更高级的自定义。

默认情况下,如果目标尚不存在,ActiveMQ "Classic" 会创建一个目标,以便根据提供的名称解析目标。

ActiveMQ Artemis 支持

Spring Boot 能够在检测到类路径中有 ActiveMQ Artemis 时自动配置一个 ConnectionFactory。如果代理存在,Spring Boot 将自动启动并配置一个嵌入式代理(除非明确设置了模式属性)。支持的模式包括 embedded(明确表示需要一个嵌入式代理,如果类路径中不可用则报错)和 native(使用 netty 传输协议连接到代理)。当配置为后者时,Spring Boot 会配置一个 ConnectionFactory,该工厂使用默认设置连接到本地机器上运行的代理。

备注

如果你使用 spring-boot-starter-artemis,那么连接现有 ActiveMQ Artemis 实例所需的依赖项以及用于集成 JMS 的 Spring 基础设施都会提供。将 org.apache.activemq:artemis-jakarta-server 添加到你的应用程序中,可以让你使用嵌入式模式。

ActiveMQ Artemis 的配置由 spring.artemis.* 中的外部配置属性控制。例如,你可以在 application.properties 中声明以下部分:

spring.artemis.mode=native
spring.artemis.broker-url=tcp://192.168.1.210:9876
spring.artemis.user=admin
spring.artemis.password=secret
properties

在嵌入 broker 时,你可以选择是否启用持久化,并列出应该可用的目的地。这些目的地可以指定为逗号分隔的列表,以便使用默认选项创建它们,或者你可以分别定义类型为 JMSQueueConfigurationTopicConfiguration 的 bean,以实现高级的队列和主题配置。

默认情况下,CachingConnectionFactory 会封装原生的 ConnectionFactory,并提供一些合理的设置,这些设置可以通过 spring.jms.* 中的外部配置属性进行控制:

spring.jms.cache.session-cache-size=5
properties

如果您更倾向于使用原生的连接池,可以通过添加 org.messaginghub:pooled-jms 依赖并相应地配置 JmsPoolConnectionFactory 来实现,如下例所示:

spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=50
properties

更多支持的选项请参见 ArtemisProperties

不涉及 JNDI 查找,目的地是通过其名称解析的,使用 ActiveMQ Artemis 配置中的 name 属性或通过配置提供的名称。

使用 JNDI ConnectionFactory

如果你的应用程序运行在应用服务器中,Spring Boot 会尝试通过 JNDI 定位一个 JMS ConnectionFactory。默认情况下,会检查 java:/JmsXAjava:/XAConnectionFactory 这两个位置。如果你需要指定一个不同的位置,可以使用 spring.jms.jndi-name 属性,如下例所示:

spring.jms.jndi-name=java:/MyConnectionFactory
properties

发送消息

Spring 的 JmsTemplate 是自动配置的,你可以直接将其自动注入到你自己的 bean 中,如下例所示:

import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

private final JmsTemplate jmsTemplate;

public MyBean(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}

// ...

public void someMethod() {
this.jmsTemplate.convertAndSend("hello");
}

}
java
备注

JmsMessagingTemplate 可以以类似的方式注入。如果定义了 DestinationResolverMessageConverter bean,它会自动与自动配置的 JmsTemplate 关联。

接收消息

当 JMS 基础设施存在时,任何 Bean 都可以通过 @JmsListener 注解来创建监听器端点。如果未定义 JmsListenerContainerFactory,则会自动配置一个默认的工厂。如果定义了 DestinationResolverMessageConverterExceptionListener Bean,它们会自动与默认工厂关联。

在大多数情况下,消息监听器容器应配置为使用原生的 ConnectionFactory。这样每个监听器容器都有自己的连接,从而在本地恢复方面拥有完全的责任。自动配置会使用 ConnectionFactoryUnwrapper 从自动配置的连接工厂中解包出原生连接工厂。

备注

自动配置仅解包 CachedConnectionFactory

默认情况下,工厂的事务性是默认开启的。如果你在一个包含 JtaTransactionManager 的基础设施中运行,它默认会与监听器容器关联。如果没有,则 sessionTransacted 标志会被启用。在后一种情况下,你可以通过在监听器方法(或其委托方法)上添加 @Transactional 注解,将本地数据存储事务与传入消息的处理关联起来。这确保了在本地事务完成后,传入的消息会被确认。这还包括在同一个 JMS 会话上执行发送响应消息的操作。

以下组件在 someQueue 目标上创建一个监听器端点:

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

@JmsListener(destination = "someQueue")
public void processMessage(String content) {
// ...
}

}
java
提示

有关更多详细信息,请参阅 @EnableJms API 文档。

如果你需要创建更多的 JmsListenerContainerFactory 实例,或者你想覆盖默认配置,Spring Boot 提供了一个 DefaultJmsListenerContainerFactoryConfigurer,你可以使用它来初始化一个 DefaultJmsListenerContainerFactory,并使用与自动配置相同的设置。

例如,以下示例展示了另一个工厂,该工厂使用了特定的 MessageConverter

import jakarta.jms.ConnectionFactory;

import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.boot.jms.ConnectionFactoryUnwrapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

@Configuration(proxyBeanMethods = false)
public class MyJmsConfiguration {

@Bean
public DefaultJmsListenerContainerFactory myFactory(DefaultJmsListenerContainerFactoryConfigurer configurer,
ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, ConnectionFactoryUnwrapper.unwrapCaching(connectionFactory));
factory.setMessageConverter(new MyMessageConverter());
return factory;
}

}
java
备注

在上面的示例中,自定义使用了 ConnectionFactoryUnwrapper 将原生连接工厂与消息监听容器关联起来,这与自动配置的工厂所采用的方式相同。

然后你可以在任何使用 @JmsListener 注解的方法中使用该工厂,如下所示:

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

@JmsListener(destination = "someQueue", containerFactory = "myFactory")
public void processMessage(String content) {
// ...
}

}
java