JMS

jakarta.jms.ConnectionFactory 介面提供建立 jakarta.jms.Connection 以與 JMS 訊息代理互動的標準方法。雖然 Spring 需要 ConnectionFactory 才能與 JMS 協同運作,但您通常不需要直接使用它,而是可以依賴更高層級的訊息抽象化。(詳情請參閱 Spring Framework 參考文件中的相關章節。)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://localhost: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 以取得更多支援的選項。您也可以註冊任意數量的 bean 來實作 ActiveMQConnectionFactoryCustomizer 以進行更進階的自訂。

預設情況下,ActiveMQ "Classic" 會在目的地尚不存在時建立目的地,以便根據其提供的名稱解析目的地。

ActiveMQ Artemis 支援

當 Spring Boot 偵測到 ActiveMQ Artemis 在類別路徑上可用時,它可以自動組態 ConnectionFactory。如果訊息代理存在,則會自動啟動並組態嵌入式訊息代理(除非已明確設定模式屬性)。支援的模式為 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 中宣告以下章節

  • 屬性

  • 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.JMSQueueConfigurationorg.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:/JmsXAjava:/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 可以以類似的方式注入。如果定義了 DestinationResolverMessageConverter bean,它會自動與自動組態的 JmsTemplate 相關聯。

接收訊息

當 JMS 基礎架構存在時,任何 bean 都可以使用 @JmsListener 註解來建立監聽器端點。如果未定義 JmsListenerContainerFactory,則會自動組態預設的工廠。如果定義了 DestinationResolverMessageConverterjakarta.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 API 文件以取得更多詳細資訊。

如果您需要建立更多 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?) {
		// ...
	}

}