此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
注释驱动的侦听器端点
异步接收消息的最简单方法是使用带注释的侦听器 端点基础设施。简而言之,它允许您公开托管 bean 作为 JMS 侦听器端点。以下示例演示如何使用它:
@Component
public class MyService {
@JmsListener(destination = "myDestination")
public void processOrder(String data) { ... }
}
前面示例的思想是,每当消息在jakarta.jms.Destination
myDestination
这processOrder
方法被调用
相应地(在本例中,与 JMS 消息的内容,类似于
什么MessageListenerAdapter
提供)。
带注释的端点基础结构创建消息侦听器容器
在后台,通过使用JmsListenerContainerFactory
.
这样的容器不会针对应用程序上下文注册,但可以轻松
通过使用JmsListenerEndpointRegistry
豆。
@JmsListener 是 Java 8 上的可重复注释,因此您可以关联
通过添加额外的@JmsListener 声明给它。 |
启用侦听器端点注释
启用对@JmsListener
注释,您可以添加@EnableJms
到其中一个
你@Configuration
类,如以下示例所示:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableJms
public class JmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory,
DestinationResolver destinationResolver) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setDestinationResolver(destinationResolver);
factory.setSessionTransacted(true);
factory.setConcurrency("3-10");
return factory;
}
}
@Configuration
@EnableJms
class JmsConfiguration {
@Bean
fun jmsListenerContainerFactory(connectionFactory: ConnectionFactory, destinationResolver: DestinationResolver) =
DefaultJmsListenerContainerFactory().apply {
setConnectionFactory(connectionFactory)
setDestinationResolver(destinationResolver)
setSessionTransacted(true)
setConcurrency("3-10")
}
}
<jms:annotation-driven/>
<bean id="jmsListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationResolver" ref="destinationResolver"/>
<property name="sessionTransacted" value="true"/>
<property name="concurrency" value="3-10"/>
</bean>
默认情况下,基础架构会查找名为jmsListenerContainerFactory
作为工厂用于创建消息侦听器容器的源。在这个
case(并忽略 JMS 基础设施设置),您可以调用processOrder
核心池大小为三个线程,最大池大小为十个线程的方法。
您可以自定义侦听器容器工厂以用于每个注释,也可以
通过实现JmsListenerConfigurer
接口。
仅当至少注册了一个端点而没有特定的
集装箱工厂。请参阅实现JmsListenerConfigurer
了解详细信息和示例。
编程端点注册
JmsListenerEndpoint
提供 JMS 端点的模型,并负责配置
该模型的容器。基础结构允许您以编程方式配置终结点
除了JmsListener
注解。
以下示例显示了如何执行此作:
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myJmsEndpoint");
endpoint.setDestination("anotherQueue");
endpoint.setMessageListener(message -> {
// processing
});
registrar.registerEndpoint(endpoint);
}
}
在前面的示例中,我们使用SimpleJmsListenerEndpoint
,它提供了实际的MessageListener
调用。但是,您也可以构建自己的端点变体
来描述自定义调用机制。
请注意,您可以跳过使用@JmsListener
完全
并通过JmsListenerConfigurer
.
带注释的端点方法签名
到目前为止,我们一直在注入一个简单的String
在我们的端点中,但它实际上可以
具有非常灵活的方法签名。在下面的示例中,我们重写它以注入Order
跟
自定义标头:
@Component
public class MyService {
@JmsListener(destination = "myDestination")
public void processOrder(Order order, @Header("order_type") String orderType) {
...
}
}
您可以在 JMS 侦听器端点中注入的主要元素如下:
-
原始的
jakarta.jms.Message
或其任何子类(前提是 与传入邮件类型匹配)。 -
这
jakarta.jms.Session
用于选择访问本机 JMS API(例如,用于发送 自定义回复)。 -
这
org.springframework.messaging.Message
表示传入的 JMS 消息。请注意,此消息同时包含自定义标头和标准标头(如定义所示) 由JmsHeaders
). -
@Header
-带注释的方法参数来提取特定的标头值,包括标准 JMS 标头。 -
一个
@Headers
-带注释的参数,也必须可以分配给java.util.Map
为 访问所有标头。 -
非受支持类型之一的非注释元素 (
Message
或Session
) 被视为有效负载。您可以通过注释参数@Payload
. 您还可以通过添加额外的@Valid
.
注入 Spring 的能力Message
抽象对于受益特别有用来自存储在传输特定消息中的所有信息,而不依赖传输特定 API。以下示例显示了如何执行此作:
@JmsListener(destination = "myDestination")
public void processOrder(Message<Order> order) { ... }
方法参数的处理由DefaultMessageHandlerMethodFactory
,您可以进一步自定义以支持其他方法参数。您可以自定义转换和验证也支持那里。
例如,如果我们想确保我们的Order
在处理之前有效,我们可以用@Valid
并配置必要的验证器,如以下示例所示:
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(myJmsHandlerMethodFactory());
}
@Bean
public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setValidator(myValidator());
return factory;
}
}
响应管理
现有支持MessageListenerAdapter
已经让你的方法具有非void
返回类型。在这种情况下,调用的结果调用被封装在jakarta.jms.Message
,在指定的目标中发送 在JMSReplyTo
标头或在侦听器上配置的默认目标中。您现在可以使用@SendTo
注释消息传递抽象。
假设我们的processOrder
方法现在应该返回一个OrderStatus
,我们可以编写自动发送响应,如下例所示:
@JmsListener(destination = "myDestination")
@SendTo("status")
public OrderStatus processOrder(Order order) {
// order processing
return status;
}
如果您有多个@JmsListener -annotated 方法,也可以将@SendTo 类级别的注释以共享默认回复目的地。 |
如果需要以与传输无关的方式设置其他标头,可以返回Message
相反,使用类似于以下的方法:
@JmsListener(destination = "myDestination")
@SendTo("status")
public Message<OrderStatus> processOrder(Order order) {
// order processing
return MessageBuilder
.withPayload(status)
.setHeader("code", 1234)
.build();
}
如果您需要在运行时计算响应目标,则可以将响应封装在JmsResponse
实例,该实例还提供了在运行时使用的目的地。我们可以重写前面的示例,如下所示:
@JmsListener(destination = "myDestination")
public JmsResponse<Message<OrderStatus>> processOrder(Order order) {
// order processing
Message<OrderStatus> response = MessageBuilder
.withPayload(status)
.setHeader("code", 1234)
.build();
return JmsResponse.forQueue(response, "status");
}
最后,如果您需要为响应指定一些 QoS 值,例如优先级或生存时间,您可以配置JmsListenerContainerFactory
因此 如以下示例所示:
@Configuration
@EnableJms
public class AppConfig {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
QosSettings replyQosSettings = new QosSettings();
replyQosSettings.setPriority(2);
replyQosSettings.setTimeToLive(10000);
factory.setReplyQosSettings(replyQosSettings);
return factory;
}
}