此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
异步接收消息的最简单方法是使用带 Comments 的侦听器 端点基础设施。简而言之,它允许您公开托管 bean 作为 JMS 侦听器端点。以下示例演示如何使用它:
@Component
public class MyService {
@JmsListener(destination = "myDestination")
public void processOrder(String data) { ... }
}
前面示例的思路是,只要 上有消息可用,就会调用该方法
因此(在本例中,使用 JMS 消息的内容,类似于
MessageListenerAdapter
提供的内容)。jakarta.jms.Destination
myDestination
processOrder
带注释的终端节点基础设施会创建一个消息侦听器容器
每个带注释的方法的幕后,通过使用 .
这样的容器不是针对应用程序上下文注册的,但可以很容易地
使用 Bean 进行管理。JmsListenerContainerFactory
JmsListenerEndpointRegistry
@JmsListener 是 Java 8 上的可重复注释,因此您可以将
多个 JMS 目标。@JmsListener |
@JmsListener 是 Java 8 上的可重复注释,因此您可以将
多个 JMS 目标。@JmsListener |
启用 Listener Endpoint Annotations
要启用对注释的支持,您可以添加到以下
您的类,如下例所示:@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>
默认情况下,基础结构会查找名为 Bean 的 Bean,作为工厂的源,以用于创建消息侦听器容器。在这个
case(并忽略 JMS 基础结构设置),您可以调用核心池大小为 3 个线程且最大池大小为 10 个线程的方法。jmsListenerContainerFactory
processOrder
您可以自定义侦听器容器工厂以用于每个注释,也可以
通过实现接口来配置显式默认值。
仅当至少注册了一个端点而没有特定的
集装箱工厂。有关详细信息和示例,请参阅实现JmsListenerConfigurer
的类的 javadoc。JmsListenerConfigurer
编程终端节点注册
JmsListenerEndpoint
提供 JMS 终端节点的模型,并负责配置
该模型的容器。基础设施允许您以编程方式配置终端节点
除了 Annotation 检测到的 None 之外。
以下示例显示了如何执行此操作: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
带注释的端点方法签名
到目前为止,我们一直在端点中注入一个 simple,但它实际上可以
具有非常灵活的方法签名。在下面的示例中,我们重写它以将
自定义标头:String
Order
@Component
public class MyService {
@JmsListener(destination = "myDestination")
public void processOrder(Order order, @Header("order_type") String orderType) {
...
}
}
您可以在 JMS 侦听器终端节点中注入的主要元素如下:
-
raw 或其任何子类(前提是它 匹配传入消息类型)。
jakarta.jms.Message
-
用于对本机 JMS API 的可选访问(例如,用于发送 自定义回复)。
jakarta.jms.Session
-
表示传入 JMS 消息的 that。 请注意,此消息同时包含自定义和标准标头(如定义 由 )。
org.springframework.messaging.Message
JmsHeaders
-
@Header
-annotated 方法参数来提取特定的标头值,包括 标准 JMS 标头。 -
一个带 -注释的参数,也必须分配给 for 获取对所有标头的访问权限。
@Headers
java.util.Map
-
不是受支持类型( 或 )之一的未注释元素被视为有效负载。您可以通过注释 带有 .您还可以通过添加额外的 .
Message
Session
@Payload
@Valid
注入 Spring 抽象的能力特别有用
从特定于传输的消息中存储的所有信息中,而无需依赖
特定于传输的 API。以下示例显示了如何执行此操作:Message
@JmsListener(destination = "myDestination")
public void processOrder(Message<Order> order) { ... }
方法参数的处理由 提供,你可以
进一步自定义以支持其他方法参数。您可以自定义转换和验证
那里也有支持。DefaultMessageHandlerMethodFactory
例如,如果我们想在处理之前确保 our 是有效的,我们可以
使用必要的 Validator 注释有效负载并配置必要的 Validator,如下例所示: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
中的现有支持已经允许你的方法具有非 return 类型。在这种情况下,将
调用封装在 ,在指定的目标中发送
在原始消息的报头中或在
侦听器。现在,您可以使用
消息传递抽象。void
jakarta.jms.Message
JMSReplyTo
@SendTo
假设我们的方法现在应该返回一个 ,我们可以编写它
自动发送响应,如下例所示:processOrder
OrderStatus
@JmsListener(destination = "myDestination")
@SendTo("status")
public OrderStatus processOrder(Order order) {
// order processing
return status;
}
如果有多个 -annotated 方法,则还可以将 annotation 放在类级别以共享默认回复目标。@JmsListener @SendTo |
如果需要以与传输无关的方式设置其他标头,则可以使用类似于以下的方法返回 a: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;
}
}
如果有多个 -annotated 方法,则还可以将 annotation 放在类级别以共享默认回复目标。@JmsListener @SendTo |