我在一个使用Java和Spring Boot的项目中,该项目处理来自同一队列的几种不同的消息类型。使用每种消息类型的MessageProcessingService
抽象类的实现,根据消息类型有条件地处理每个消息。
截至目前,我们有5种不同的消息类型进入同一使用者。我们使用相同的队列是因为我们利用JMS中的组策略,并且每种消息类型都具有与组策略相同的业务密钥。
因此,最终我们得出的结果是,每当需求需要接收新的消息类型时,我们都会为消费者对象添加MessageProcessingService
的新实现和另一个依赖项。我想找到一个更好的策略来有选择地选择消息处理
这是一个类似于我们正在做的例子。我不保证语法是可编译的或在语法上是完美的,仅用于说明问题。注意所有消息围绕一个人解决
消费者:
@Component
public class PersonMessageConsumer {
private MessageProcessingService<HeightUpdate> heightUpdateMessageProcessingService;
private MessageProcessingService<WeightUpdate> weightUpdateMessageProcessingService;
private MessageProcessingService<NameUpdate> nameUpdateMessageProcessingService;
private MessageProcessingService<ShowSizeUpdate> shoeSizeUpdateMessageProcessingService;
public PersonMessageConsumer(
MessageProcessingService<HeightUpdate> heightUpdateMessageProcessingService,
MessageProcessingService<WeightUpdate> weightUpdateMessageProcessingService,
MessageProcessingService<NameUpdate> nameUpdateMessageProcessingService,
MessageProcessingService<ShowSizeUpdate> shoeSizeUpdateMessageProcessingService) {
this.heightUpdateMessageProcessingService = heightUpdateMessageProcessingService;
this.weightUpdateMessageProcessingService = weightUpdateMessageProcessingService;
this.nameUpdateMessageProcessingService = nameUpdateMessageProcessingService;
this.shoeSizeUpdateMessageProcessingService = shoeSizeUpdateMessageProcessingService;
}
@JmsListener(destination = "${queueName}")
public void receiveMessage(TextMessage message) {
String messageType = message.getHeader("MessageType");
switch (messageType) {
case "HeightUpdate":
heightUpdateMessageProcessingService.processMessage(message.getText());
return;
case "WeightUpdate":
weightUpdateMessageProcessingServivce.processMessage(message.getText());
return;
// And other message types
default:
throw new UnknownMessageTypeException(messageType);
}
}
消息POJO示例
public class HeightUpdate implements PersonMessage {
@Getter
@Setter
private int height;
}
PersonMessage介面
public interface PersonMessage {
int getPersonId();
}
MessageProcessingService
public abstract class MessageProcessingService<T extends PersonMessage> {
public void processMessage(String messageText) {
//Common message processing, we do some more involved work here but just as a simple example
T message = new ObjectMapper.readValue(messageText, getClassType());
Person person = personRepository.load(message.getPersonId());
Person originalPerson = person.deepCopy();
processMessageLogic(person, message);
if (originalPerson.isDifferentFrom(person)) {
personRespository.update(person);
}
}
protected abstract void processMessageLogic(Person person, T message);
protected abstract Class getClassType();
}
抽象类实现示例
@Service("heightUpdateMessageProcessingService")
public class HeightUpdateMessageProcessingService extends MessageProcessingService<HeightUpdate> {
@Override
protected void processMessageLogic(Person person, HeightUpdate update) {
person.setHeight(update.getHeight());
}
@Override
protected Class getMessageType() {
return HeightUpdate.getClass();
}
}
所以我的问题是,是否有更好的设计模式或在Java和spring中对此进行编码的方式,使其更易于清洁和维护,并牢记SOLID原则
最佳答案
在MessageProcessingService
中添加抽象方法以返回每个具体实现可以处理的messageType
。
而不是将每个单独的服务连接到PersonMessageConsumer
,而是连接一个List<MessageProcessingService>
,以便您一次获得所有这些服务。
使用List
作为键,将该Map<String, MessageProcessingService>
转换为messageType
。
通过在switch
中查找适当的服务,然后调用其Map
方法来替换processMessage
语句。
将来您可以添加MessageProcessingService
的新实例而不必编辑PersonMessageConsumer
,因为Spring会自动将这些新实例添加到您连接的List<MessageProcessingService>
中。