领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多信息Spring Framework 4.0 引入了一个新的 spring-messaging
模块,添加了一系列 Spring Integration 类型,例如核心 Message
抽象。Spring 4.1 使其 JMS 支持与之保持一致,以便您可以从中受益。但在深入研究之前,我想详细向您展示我们如何进一步改进侦听器端点的基础架构。
您可能习惯于 <xyz:annotation-driven>
元素或 @Enable*
的对应项,也许您正在寻找类似于 JMS 的东西。不用再寻找了:Spring 框架的下一个主要版本将允许您使用简单的注解定义 JMS 侦听器。
@Component
public class MyService {
@JmsListener(containerFactory = "myContainerFactory", destination = "myQueue")
public void processOrder(String data) { ... }
}
以下配置(忽略 JMS 基础设施设置)在幕后创建了一个 JMS 消息侦听器容器,该容器位于 myQueue
目标上,并在消息可用时调用 processOrder
@Configuration
@EnableJms
public class AppConfig {
@Bean
public DefaultJmsListenerContainerFactory myContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setConcurrency("3-10");
return factory;
}
}
这是使用 XML 命名空间的等效方法
<jms:annotation-driven/>
<bean id="myContainerFactory"
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationResolver" ref="destinationResolver"/>
<property name="concurrency" value="3-10"/>
</bean>
像往常一样,@JmsListener
可以直接放在方法上,也可以使用元注解间接放置。该注解具有 jms:listener
XML 元素在相当长一段时间内提供的常用选项。但是,containerFactory
是新的,它指的是 JmsListenerContainerFactory
的名称,这相当于您习惯在 <jms:listener-container>
元素中配置的内容。
如果您想从现有配置平滑过渡,我们已向该元素添加了一个 factory-id
属性。当它存在时,配置将自动公开为具有该名称的 JmsListenerContainerFactory
bean。此 XML 配置等效于上面的 myJmsContainerFactory
bean
<jms:listener-container factory-id="myContainerFactory"
connection-factory="connectionFactory"
destination-resolver="destinationResolver"
concurrency="3-10"/>
由于单个容器工厂设置可能相当常见,因此如果已设置或发现了默认工厂,则可以省略 containerFactory
属性。默认情况下,我们查找名为 jmsListenerContainerFactory
的 bean。
可以通过实现 JmsListenerConfigurer
接口以多种方式自定义此基础设施的配置。就像我们刚才提到的,可以使用显式方式指定要使用的默认容器工厂,但此回调接口还允许您以编程方式注册 JMS 端点!
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setDefaultContainerFactory(defaultContainerFactory());
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("anotherQueue");
endpoint.setMessageListener(message -> {
// processing
});
registrar.registerEndpoint(endpoint);
}
@Bean
public DefaultJmsListenerContainerFactory defaultContainerFactory() {
...
}
上面的示例设置了默认的 JmsListenerContainerFactory
,并在 anotherQueue
上配置了一个额外的端点。JmsListenerEndpoint
对您的端点进行建模,并负责为此模型配置容器。在上面的示例中,我们使用了 SimpleJmsListenerEndpoint
,它提供了要调用的实际 MessageListener
,但您也可以构建自己的端点变体来描述自定义调用机制。MethodJmsListenerEndpoint
是另一个示例,它由所有使用 @JmsListener
注解的端点使用。
到目前为止,我们一直在端点中注入一个简单的 String
,但它实际上可以具有非常灵活的方法签名。让我们将其重写为使用自定义标头注入 Order
@Component
public class MyService {
@JmsListener(destination = "myQueue")
public void processOrder(Order order, @Header("order_type") String orderType) {
...
}
}
这些是您可以在 JMS 侦听器端点中注入的主要元素
javax.jms.Message
或其任何子类(当然,前提是它与传入的消息类型匹配)。javax.jms.Session
,例如发送自定义回复。org.springframework.messaging.Message
。请注意,此消息包含自定义标头和标准标头(如 JmsHeaders
定义的那样)。@Header
注解的方法参数,用于提取特定标头值,包括标准 JMS 标头。@Headers
注解的参数,也必须可分配给 java.util.Map
以访问所有标头。Message
和 Session
),则被视为有效负载。您可以通过使用 @Payload
注解参数来明确表示这一点。您还可以通过添加额外的 @Validated
来打开验证。能够注入 Spring 的 Message
抽象对于利用存储在特定于传输的消息中的所有信息而无需依赖于特定于传输的 API 尤其有用。
@JmsListener(destination = "myQueue")
public void processOrder(Message<Order> order) { ... }
这些功能在所有带注解的元素下都提供了。可以自定义验证和转换服务,甚至为您的自定义用例添加其他方法参数解析器。以下示例设置了一个自定义 Validator
,以便在调用侦听器方法之前,先使用它验证 @Validated
注解的有效负载
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setJmsHandlerMethodFactory(myJmsHandlerMethodFactory());
}
@Bean
public DefaultJmsHandlerMethodFactory myJmsHandlerMethodFactory() {
DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
factory.setValidator(myValidator());
return factory;
}
}
MessageListenerAdapter
中现有的支持已允许您的方法具有非 void
返回类型。在这种情况下,调用的结果将封装在一个 javax.jms.Message
中,该消息发送到原始消息的 JMSReplyTo
标头中指定的目的地或侦听器上配置的默认目的地。现在可以使用消息传递抽象的 @SendTo
注解设置该默认目的地。
假设我们的 processOrder
方法现在应该返回一个 OrderStatus
,则可以按如下方式编写它以自动发送回复
@JmsListener(destination = "myQueue")
@SendTo("queueOut")
public OrderStatus processOrder(Order order) {
// order processing
return status;
}
如果您需要以独立于传输的方式设置其他标头,则可以返回一个 Message
,例如
@JmsListener(destination = "myQueue")
@SendTo("queueOut")
public Message<OrderStatus> processOrder(Order order) {
// order processing
return MessageBuilder
.withPayload(status)
.setHeader("code", 1234)
.build();
}
Spring Framework 4.1 预计将于今年 7 月发布,其中包含 JMS 领域的若干改进:JMS 侦听器方法可以简单地进行注解,并且可以使用非常灵活的方法签名。Spring 4.0 中引入的消息传递抽象现在也支持 JMS 侦听器。