所以我正在开展一个项目,许多团队正在使用公共服务并遵循通用架构。正在使用的服务之一是消息传递,目前是带有ActiveMQ的JMS。几乎所有团队都必须遵循一套严格的规则来创建和发送消息,即一切都是pub-subscribe,发送的消息有点像下面这样:
public class WorkDTO {
private String type;
private String subtype;
private String category;
private String jsonPayload; // converted custom Java object
}
'jsonPayload'来自所有团队扩展的基类,因此它具有共同的属性。
所以基本上在JMS中,每个人总是发送相同类型的消息,但是发送到不同的ActiveMQ主题。当通过JMS发送消息(WorkDTO)时,首先将其转换为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;
}
}