JMS
jakarta.jms.ConnectionFactory
接口提供了一种标准方法来创建 jakarta.jms.Connection
,用于与 JMS 代理进行交互。虽然 Spring 需要 ConnectionFactory
来使用 JMS,但您通常不需要直接使用它,而是可以依赖于更高级别的消息传递抽象。(有关详细信息,请参阅 Spring 框架参考文档的 相关部分。)Spring Boot 还自动配置了发送和接收消息所需的必要基础设施。
ActiveMQ "Classic" 支持
当 ActiveMQ "Classic" 在类路径上可用时,Spring Boot 可以配置 ConnectionFactory
。
如果您使用 spring-boot-starter-activemq ,则会提供连接到 ActiveMQ "Classic" 实例所需的依赖项,以及与 JMS 集成的 Spring 基础设施。
|
ActiveMQ "Classic" 配置由 spring.activemq.*
中的外部配置属性控制。默认情况下,ActiveMQ "Classic" 自动配置为使用 TCP 传输,默认连接到 tcp://127.0.0.1:61616
。以下示例展示了如何更改默认代理 URL
-
属性
-
YAML
spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret
spring:
activemq:
broker-url: "tcp://192.168.1.210:9876"
user: "admin"
password: "secret"
默认情况下,CachingConnectionFactory
会使用合理的设置包装本机 ConnectionFactory
,您可以通过 spring.jms.*
中的外部配置属性来控制这些设置。
-
属性
-
YAML
spring.jms.cache.session-cache-size=5
spring:
jms:
cache:
session-cache-size: 5
如果您希望使用本机池,则可以通过添加对 org.messaginghub:pooled-jms
的依赖项并相应地配置 JmsPoolConnectionFactory
来实现,如以下示例所示
-
属性
-
YAML
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
spring:
activemq:
pool:
enabled: true
max-connections: 50
有关更多支持的选项,请参阅 ActiveMQProperties 。您还可以注册任意数量的实现 ActiveMQConnectionFactoryCustomizer 的 bean,以进行更高级的自定义。
|
默认情况下,ActiveMQ "Classic" 会在目的地不存在时创建它,以便目的地根据其提供的名称进行解析。
ActiveMQ Artemis 支持
当 Spring Boot 检测到类路径中存在 ActiveMQ Artemis 时,它可以自动配置一个 ConnectionFactory
。如果代理存在,则会自动启动并配置一个嵌入式代理(除非显式设置了 mode 属性)。支持的模式有 embedded
(明确表示需要嵌入式代理,如果类路径中不存在代理,则应发生错误)和 native
(使用 netty
传输协议连接到代理)。当配置后者时,Spring Boot 会配置一个 ConnectionFactory
,该 ConnectionFactory
连接到本地机器上运行的代理,并使用默认设置。
如果您使用 spring-boot-starter-artemis ,则会提供连接到现有 ActiveMQ Artemis 实例所需的依赖项,以及与 JMS 集成的 Spring 基础设施。将 org.apache.activemq:artemis-jakarta-server 添加到您的应用程序中,可以让您使用嵌入式模式。
|
ActiveMQ Artemis 配置由 spring.artemis.*
中的外部配置属性控制。例如,您可以在 application.properties
中声明以下部分
-
属性
-
YAML
spring.artemis.mode=native
spring.artemis.broker-url=tcp://192.168.1.210:9876
spring.artemis.user=admin
spring.artemis.password=secret
spring:
artemis:
mode: native
broker-url: "tcp://192.168.1.210:9876"
user: "admin"
password: "secret"
当嵌入代理时,您可以选择是否启用持久性并列出要提供的目标。这些可以作为逗号分隔列表指定,以使用默认选项创建它们,或者您可以定义类型为 org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration
或 org.apache.activemq.artemis.jms.server.config.TopicConfiguration
的 bean,分别用于高级队列和主题配置。
默认情况下,CachingConnectionFactory
会使用合理的设置包装本机 ConnectionFactory
,您可以通过 spring.jms.*
中的外部配置属性来控制这些设置。
-
属性
-
YAML
spring.jms.cache.session-cache-size=5
spring:
jms:
cache:
session-cache-size: 5
如果您希望使用本机池,则可以通过添加对 org.messaginghub:pooled-jms
的依赖项并相应地配置 JmsPoolConnectionFactory
来实现,如下例所示
-
属性
-
YAML
spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=50
spring:
artemis:
pool:
enabled: true
max-connections: 50
有关更多支持的选项,请参阅 ArtemisProperties
。
不涉及 JNDI 查找,目标是根据其名称解析的,使用 ActiveMQ Artemis 配置中的 name
属性或通过配置提供的名称。
使用 JNDI ConnectionFactory
如果您在应用程序服务器中运行应用程序,Spring Boot 会尝试使用 JNDI 查找 JMS ConnectionFactory
。默认情况下,会检查 java:/JmsXA
和 java:/XAConnectionFactory
位置。如果您需要指定备用位置,可以使用 spring.jms.jndi-name
属性,如下例所示
-
属性
-
YAML
spring.jms.jndi-name=java:/MyConnectionFactory
spring:
jms:
jndi-name: "java:/MyConnectionFactory"
发送消息
Spring 的 JmsTemplate
是自动配置的,您可以将其直接自动装配到您自己的 bean 中,如下例所示
-
Java
-
Kotlin
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");
}
}
import org.springframework.jms.core.JmsTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val jmsTemplate: JmsTemplate) {
// ...
fun someMethod() {
jmsTemplate.convertAndSend("hello")
}
}
JmsMessagingTemplate 可以以类似的方式注入。如果定义了 DestinationResolver 或 MessageConverter bean,它将自动与自动配置的 JmsTemplate 关联。
|
接收消息
当 JMS 基础设施存在时,任何 Bean 都可以通过 @JmsListener
注解来创建监听器端点。如果没有定义 JmsListenerContainerFactory
,则会自动配置一个默认的工厂。如果定义了 DestinationResolver
、MessageConverter
或 jakarta.jms.ExceptionListener
Bean,它们会自动与默认工厂关联。
默认情况下,默认工厂是事务性的。如果您在存在 JtaTransactionManager
的基础设施中运行,它会默认与监听器容器关联。如果没有,则会启用 sessionTransacted
标志。在这种情况下,您可以通过在监听器方法(或其委托)上添加 @Transactional
来将本地数据存储事务与传入消息的处理关联起来。这确保了在本地事务完成后,传入消息将被确认。这也包括在同一个 JMS 会话中执行的发送响应消息。
以下组件在 someQueue
目标上创建监听器端点
-
Java
-
Kotlin
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@JmsListener(destination = "someQueue")
public void processMessage(String content) {
// ...
}
}
import org.springframework.jms.annotation.JmsListener
import org.springframework.stereotype.Component
@Component
class MyBean {
@JmsListener(destination = "someQueue")
fun processMessage(content: String?) {
// ...
}
}
有关更多详细信息,请参阅 @EnableJms 的 Javadoc。
|
如果您需要创建更多 JmsListenerContainerFactory
实例,或者想要覆盖默认实例,Spring Boot 提供了一个 DefaultJmsListenerContainerFactoryConfigurer
,您可以使用它来使用与自动配置的实例相同的设置初始化 DefaultJmsListenerContainerFactory
。
例如,以下示例公开另一个使用特定 MessageConverter
的工厂
-
Java
-
Kotlin
import jakarta.jms.ConnectionFactory;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
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) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
ConnectionFactory connectionFactory = getCustomConnectionFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(new MyMessageConverter());
return factory;
}
private ConnectionFactory getCustomConnectionFactory() {
return ...
}
}
import jakarta.jms.ConnectionFactory
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.jms.config.DefaultJmsListenerContainerFactory
@Configuration(proxyBeanMethods = false)
class MyJmsConfiguration {
@Bean
fun myFactory(configurer: DefaultJmsListenerContainerFactoryConfigurer): DefaultJmsListenerContainerFactory {
val factory = DefaultJmsListenerContainerFactory()
val connectionFactory = getCustomConnectionFactory()
configurer.configure(factory, connectionFactory)
factory.setMessageConverter(MyMessageConverter())
return factory
}
fun getCustomConnectionFactory() : ConnectionFactory? {
return ...
}
}
然后,您可以在任何 @JmsListener
注解的方法中使用该工厂,如下所示
-
Java
-
Kotlin
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) {
// ...
}
}
import org.springframework.jms.annotation.JmsListener
import org.springframework.stereotype.Component
@Component
class MyBean {
@JmsListener(destination = "someQueue", containerFactory = "myFactory")
fun processMessage(content: String?) {
// ...
}
}