MessageProcessingService

MessageProcessingService

我在一个使用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>中。

10-05 18:33