映射dto /域以在微服务之间传输的最佳方法

时间:2017-07-09 12:16:30

标签: java domain-driven-design microservices dto

我有DTO和DOMAIN模型:

@Data
public class CarDomain {
    private String name;
    private int year;
    private String color;
}

@Data
public class CarDto {
    private String name;
    private int year;
    private String color;
}

我有3个微服务(MS)通过RabbitMq相互通信。 我有models module所有DTO课程。每个MS都包含models module 在maven。

1 MS发送carDto 2 MS接收CarDto并转换为域。为此我可以使用几种变体:

  1. 使用库例如mapstruct
  2. @Mapper
    public interface CarMapper {
        CarMapper INSTANCE = Mappers.getMapper(CarMapper.class );
        CarDto carToCarDto(CarDomain car);
    }
    

    并使用:

    CarDto carDto = CarMapper.INSTANCE.carToCarDto(carDomain);
    
    1. 创建手动映射器:
    2. class CarMapper {
              public static CarDto toDto(CarDomain car) {
                  CarDto carDto = new CarDto();
                  carDto.setName(car.getName());
                  carDto.setYear(car.getYear());
                  carDto.setColor(car.getColor());
              }
          }
      

      现在我们使用2个变体。当我们构建微服务时,并且在models module DTO模型更改的某个字段中,我们在编译时遇到错误。例如,有人在models module

      中更改此dto模型的名称
      private String name; 
      

      private String name1;
      

      当我们构建项目时,我们会在这一行上收到错误:

      carDto.setName(car.getName());// getName not found becose now getName1
      

      但这种方式很难。对于每个dto / domain模型,我们需要创建映射器并编写每个字段。在1个变体中它更容易但如果改变我们在运行时会得到错误。

      告诉我如何匹配/映射模型dto / domain的最佳方法?

2 个答案:

答案 0 :(得分:4)

  

当我们构建微服务时,在模型模块中,DTO模型的某些字段会发生变化,我们会在编译时遇到错误。

您遇到的问题通常被视为邮件版本控制。

微服务中的一个关键想法是它们可以彼此独立地重新部署;你应该能够随时改变它们,而不会破坏其他一切。为此,我们将微服务之间的耦合限制为它们共有的消息。

因此;因此,使消息模式“正确”是非常重要的

在这种情况下,

正确并不意味着你想出了第一次发送的正确消息,而是在投资前期设计资本来理解消息如何变化,以及消息结构支持那些变化。

关于我所知道的主题的最佳单一参考是Greg Young的书Versioning in an Event Sourced System

Greg提出了使用“弱模式”来支持前向和后向兼容性的案例;基本的想法是

  • 字段的含义永远不会改变
  • 消费者必须忽略并且必须转发它不理解的字段
  • 大多数(所有?)字段应该是可选的;消费者必须为消息中缺少某些数据元素的事件做好准备。这可能意味着准备了可接受的默认值,或者替代处理。

记住基础知识;您可以查看AvroThriftProtocol Buffers的详细信息,以了解标准化格式如何发展。 Martin Kleppmann对Schema Evolution in Avro, Protocol Buffers, and Thrift的讨论可能是一个很好的中间步骤。

消息规则非常重要 - 架构是微服务API的一部分。向API引入向后不兼容的更改会带来很多风险,不应轻易进行。

  

我有所有DTO类的模型模块。

这可能是一个错误;很难说。拥有一个通常以不向后兼容的方式发展的共同核心肯定是错误的。这种习惯应该改变。

答案 1 :(得分:0)

考虑使用Java bean映射器。看到 any tool for java object to object mapping?

此类映射器非常灵活,可以在不需要样板代码的情况下弥合模型之间的细微差别。