Spring DefaultMessageListenerContainer/SimpleMessageListenerContainer (JMS/AMQP) 注解配置
因此,我正在开发一个项目,其中许多团队都使用通用服务并遵循通用架构。正在使用的服务之一是消息传递,目前是带有 ActiveMQ 的 JMS。几乎所有团队都需要遵循一组严格的规则来创建和发送消息,即一切都是发布订阅,发送的消息有点类似于以下内容:
public class WorkDTO {
private String type;
private String subtype;
private String category;
private String jsonPayload; // converted custom Java object
}
“jsonPayload”来自所有团队的基类扩展自,因此它具有共同的属性。
所以基本上在 JMS 中,每个人总是发送相同类型的消息,但是发送到不同的 ActiveMQ 主题。当消息 (WorkDTO) 通过 JMS 发送时,首先将其转换为 JSON 对象,然后在 TextMessage 中发送。
每当团队希望为某个主题创建订阅者时,他们都会创建一个 DefaultMessageListenerContainer 并对其进行适当配置以接收消息(我们使用基于 Java 的 Spring 配置)。基本上,团队定义的每个 DefaultMessageListenerContainer 几乎都是相同的,除了接收消息的目的地和消息处理程序之外。
我想知道在这种情况下,有人会如何通过注释进一步抽象消息配置?这意味着,由于几乎每个人都需要遵循相同的要求,因此类似以下内容是否有用:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Listener {
String destination();
boolean durable() default false;
long receiveTimeout() default -1; // -1 use JMS default
String defaultListenerMethod() default "handleMessage";
// more config details here
}
@Listener(destination="PX.Foo", durable=true)
public class FooListener {
private ObjectMapper mapper = new ObjectMapper(); // converts JSON Strings to Java Classes
public void handleMessage(TextMessage message){
String text = message.getText();
WorkDTO dto = mapper.readValue(text, WorkDto.class);
String payload = dto.getPayload();
String type = dto.getType();
String subType = dto.getSubType();
String category = dto.getCategory();
}
}
当然,我省略了有关如何使用 @Listener 注释配置 DefaultMessageListenerContainer 的部分。我开始研究 BeanFactoryPostProcessor 来创建必要的类并将它们添加到应用程序上下文中,但我不知道如何执行所有这些操作。
我问这个问题的原因是我们正在从 JMS/ActiveMQ 切换到 AMQP/RabbitMQ,并且希望通过使用注释进一步抽象消息配置。我知道 AMQP 与 JMS 不同,因此配置细节会略有不同。我不相信我们会从 AMQP 切换到其他东西。
在这里,团队只需要知道目的地的名称以及他们是否想让他们的订阅持久。
这只是最近突然出现在我脑海中的事情。对此有什么想法吗?
我不想做一些过于复杂的事情,所以另一种选择是创建一个方便的方法,该方法返回给定目标和消息处理程序的预配置的 DefaultMessageListenerContainer:
@Configuration
public class MyConfig{
@Autowired
private MessageConfigFactory configFactory;
@Bean
public DefaultMessageListenerContainer fooListenerContainer(){
return configFactory.getListenerContainer("PX.Foo", new FooListener(), true);
}
}
class MessageConfigFactory {
public DefaultMessageListenerContainer getListener(String destination, Object listener, boolean durable) {
DefaultMessageListenerContainer l = new DefaultMessageListenerContainer();
// configuration details here
return l;
}
}
So I'm working on a project where many teams are using common services and following a common architecture. One of the services in use is messaging, currently JMS with ActiveMQ. Pretty much all teams are required to follow a strict set of rules for creating and sending messages, namely, everything is pub-subscribe and the messages that are sent are somewhat like the following:
public class WorkDTO {
private String type;
private String subtype;
private String category;
private String jsonPayload; // converted custom Java object
}
The 'jsonPayload' comes from a base class that all teams extend from so it has common attributes.
So basically in JMS, everyone is always sending the same kind of message, but to different ActiveMQ Topics. When the message (WorkDTO) is sent via JMS, first it is converted into a JSON object then it is sent in a TextMessage.
Whenever a team wishes to create a subscriber for a topic, they create a DefaultMessageListenerContainer and configure it appropriately to receive messages (We are using Java-based Spring configuration). Basically every DefaultMessageListenerContainer that a team defines is pretty much the same except for maybe the destination from which to receive messages and the message handler.
I was wondering how anyone would approach further abstracting the messaging configuration via annotations in such a case? Meaning, since everyone is pretty much required to follow the same requirements, could something like the following be useful:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Listener {
String destination();
boolean durable() default false;
long receiveTimeout() default -1; // -1 use JMS default
String defaultListenerMethod() default "handleMessage";
// more config details here
}
@Listener(destination="PX.Foo", durable=true)
public class FooListener {
private ObjectMapper mapper = new ObjectMapper(); // converts JSON Strings to Java Classes
public void handleMessage(TextMessage message){
String text = message.getText();
WorkDTO dto = mapper.readValue(text, WorkDto.class);
String payload = dto.getPayload();
String type = dto.getType();
String subType = dto.getSubType();
String category = dto.getCategory();
}
}
Of course I left out the part on how to configure the DefaultMessageListenerContainer by use of the @Listener annotation. I started looking into a BeanFactoryPostProcessor to create the necessary classes and add them to the application context, but I don't know how to do all that.
The reason I ask the question is that we are switching to AMQP/RabbitMQ from JMS/ActiveMQ and would like to abstract the messaging configuration even further by use of annotations. I know AMQP is not like JMS so the configuration details would be slightly different. I don't believe we will be switching from AMQP to something else.
Here teams only need to know the name of the destination and whether they want to make their subscription durable.
This is just something that popped into my head just recently. Any thoughts on this?
I don't want to do something overly complicated though so the other alternative is to create a convenience method that returns a pre-configured DefaultMessageListenerContainer given a destination and a message handler:
@Configuration
public class MyConfig{
@Autowired
private MessageConfigFactory configFactory;
@Bean
public DefaultMessageListenerContainer fooListenerContainer(){
return configFactory.getListenerContainer("PX.Foo", new FooListener(), true);
}
}
class MessageConfigFactory {
public DefaultMessageListenerContainer getListener(String destination, Object listener, boolean durable) {
DefaultMessageListenerContainer l = new DefaultMessageListenerContainer();
// configuration details here
return l;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论