1. 概述

近些年来,微服务变得越来越流行。微服务基本特征是模块化、独立、易于扩展的。它们之间需要协同工作并交换数据。为了实现这一点,我们创建了名为 DTO 的共享数据传输对象。在本文中,我们将介绍在微服务之间共享DTO的方法。

2. 将域对象发布为DTO

使用微服务管理表示应用程序域的模型。域模型的关注点与 DTO 不同,我们将它们与DAO层中的数据模型分开。

这样做的主要原因是我们不想通过服务向客户暴露我们领域的复杂性。

恰恰相反,我们通过 REST API 暴露 DTO 为客户端提供服务。当DTO在这些服务之间传递时,我们将它们转换为域对象。

上面的 面向服务架构 示意性地显示了DTO到域对象的组件和流程。

3. 微服务间共享DTO

以客户订购产品的过程为例。此过程基于 Customer-Order 模型,从服务体系结构的角度来看看这个过程。

假设客户服务将请求数据发送到订单服务:

"order": {
"customerId": 1,
"itemId": "A152"
}

CustomerOrder 服务使用 contracts (契约) 进行通信。contract(或者是服务请求)以JSON格式显示。作为 Java 模型,OrderDTO 类表示客户服务和订单服务之间的契约:

public class OrderDTO {
private int customerId;
private String itemId; // constructor, getters, setters
}

3.1. 使用客户端模块共享DTO

微服务需要来自其他服务的某些信息来处理任何请求。假设有第三个微服务接收订单付款请求。与订单服务不同,此服务需要不同的客户信息:

public class CustomerDTO {
private String firstName;
private String lastName;
private String cardNumber; // constructor, getters, setters
}

如果我们还添加了送货服务,客户信息将具有:

public class CustomerDTO {
private String firstName;
private String lastName;
private String homeAddress;
private String contactNumber; // constructor, getters, setters
}

因此,将 CustomerDTO 类放在共享模块中起不到预期的作用。为了解决这个问题,我们采用了一种不同的方法。

在每个微服务模块中,创建一个客户端模块(依赖包),并在其旁边创建一个服务端模块:

order-service
|__ order-client
|__ order-server

order-client 模块包含一个与客户服务共享的DTO。因此,order-client模块具有以下结构:

order-service
└──order-client
OrderClient.java
OrderClientImpl.java
OrderDTO.java

OrderClient 是一个接口,它定义了处理订单请求的order方法:

public interface OrderClient {
OrderResponse order(OrderDTO orderDTO);
}

为了实现 order 方法,我们使用 RestTemplate 对象向 order 服务发送POST请求:

String serviceUrl = "http://localhost:8002/order-service";
OrderResponse orderResponse = restTemplate.postForObject(serviceUrl + "/create",
request, OrderResponse.class);

此外,order-client模块已经可以使用了。它现在成为 customer-service 模块的依赖库:

[INFO] --- maven-dependency-plugin:3.1.2:list (default-cli) @ customer-service ---
[INFO] The following files have been resolved:
[INFO] com.baeldung.orderservice:order-client:jar:1.0-SNAPSHOT:compile

当然,如果 order-server 模块没有向 order-client 暴露 /create 服务端点,那也是不行滴!

@PostMapping("/create")
public OrderResponse createOrder(@RequestBody OrderDTO request)

由于这个服务端点,Customer Service 可以通过其order客户端发送订单请求。通过使用客户端模块,微服务以更加独立的方式相互通信。DTO中的属性在客户端模块中更新。因此,违背契约仅限于使用相同客户端模块的服务。

4. 结论

本文解释了一种在微服务之间共享DTO对象的方法。充其量,我们通过签订特殊契约作为微服务客户端模块(库)的一部分来实现这一点。通过这种方式,我们将服务客户端与包含API资源的服务端部分分开。这样做的好处是:

  • 服务之间没有冗余
  • 违反契约仅限于使用同一客户端的服务

    如果你觉得文章还不错,记得关注公众号: 锅外的大佬

    锅外的大佬博客

微服务之间如何共享DTO?的更多相关文章

  1. Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7867340 在前面一篇文章中,我们分析了And ...

  2. JHipster技术栈定制 - 基于UAA的微服务之间安全调用

    本文通过代码实例演示如何通过UAA实现微服务之间的安全调用. uaa: 身份认证服务,同时也作为被调用的资源服务.服务端口9999. microservice1: 调用uaa的消费者服务,服务端口80 ...

  3. spring cloud实战与思考(二) 微服务之间通过fiegn上传一组文件(上)

    需求场景: 微服务之间调用接口一次性上传多个文件. 上传文件的同时附带其他参数. 多个文件能有效的区分开,以便进行不同处理. Spring cloud的微服务之间接口调用使用Feign.原装的Feig ...

  4. spring cloud实战与思考(三) 微服务之间通过fiegn上传一组文件(下)

    需求场景: 用户调用微服务1的接口上传一组图片和对应的描述信息.微服务1处理后,再将这组图片上传给微服务2进行处理.各个微服务能区分开不同的图片进行不同处理. 上一篇博客已经讨论了在微服务之间传递一组 ...

  5. SOA和微服务之间的区别

    近几年,我们有很多文章对SOA和微服务之间的不同点和相似点进行了分析.有些人认为SOA有很多地方是值得微服务学习的,而有些人则认为区别对待微服务和SOA会更好.而Neal Ford认为,将单体迁移到面 ...

  6. SpringCloud实战 | 第五篇:SpringCloud整合OpenFeign实现微服务之间的调用

    一. 前言 微服务实战系列是基于开源微服务项目 有来商城youlai-mall 版本升级为背景来开展的,本篇则是讲述SpringCloud整合OpenFeign实现微服务之间的相互调用,有兴趣的朋友可 ...

  7. SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递

    实现思路: 1:准备一个ThreadLocal变量,供线程之间共享. 2:每个微服务对所有过来的Feign调用进行过滤,然后从请求头中获取User用户信息,并存在ThreadLocal变量中. 3:每 ...

  8. 【转】SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递

    实现思路: 1:准备一个ThreadLocal变量,供线程之间共享. 2:每个微服务对所有过来的Feign调用进行过滤,然后从请求头中获取User用户信息,并存在ThreadLocal变量中. 3:每 ...

  9. Restful、SOAP、RPC、SOA、微服务之间的区别

    什么是Restful Restful是一种架构设计风格,提供了设计原则和约束条件,而不是架构,而满足这些约束条件和原则的应用程序或设计就是 Restful架构或服务. 主要的设计原则: 资源与URI ...

随机推荐

  1. CSP2020 游记

    Day -28 后天就初赛了,考了一套模拟题,自闭,心态爆炸,感觉退役不远了 Day -26(初赛) 香农是谁??? 手写随机nth_element与O(n)的哈希表??? 阅读程序T2时间复杂度分析 ...

  2. php数组学习记录01

    array_change_key_case array_change_key_case - 将数组中的所有键名修改为全大写或小写 <?php $input_array = array(" ...

  3. jmeter压测mysql数据库

    jmeter连接并压测mysql数据库,之前一直想用jmeter一下测试mysql数据库的性能,今天偶然看到一篇博客,于是乎开始自己动手实践. 一.准备工作 1.安装好mysql数据库,可以安装在本地 ...

  4. Java基础教程——注释

    Java注释 三种注释: public class 注释 { // (1)单行注释 /* * (2)多行注释 */ /**+回车 * (3)文档注释:可以通过javadoc工具生成HTML文档 * & ...

  5. 学习关注:学习C++的前景

    许多朋友都有这样的疑问,学习C/++能做什么?有什么好处?薪资怎么样,下面就为大家来解答! 像前面的文章有提到过,计算机专业位列热门专业第一门,可想前景如何.C语言C++属于高级语言,适合人类编写,现 ...

  6. 浅谈JAVA servlet

    1.servlet是什么? servlet的本质是接口,接口就是一种规范.我们来看一下servlet接口中都有哪些函数: 图片来源:https://www.cnblogs.com/whgk/p/639 ...

  7. oracle sql%notfound

    SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回fal ...

  8. Centos7安装Kubernetes k8s v1.16.0 国内环境

    一. 为什么是k8s v1.16.0? 最新版的v1.16.2试过了,一直无法安装完成,安装到kubeadm init那一步执行后,报了很多错,如:node xxx not found等.centos ...

  9. 在之前的EventHandler中的参数类型必须继承EventArgs,现在已经去掉这个约束了。

    分别是vs2008和vs2012的对比,可以看到2012已经去掉了约束条件.

  10. django 不使用序列化器时进行查询结果序列化

    在app01views中添加 class User1(View): def post(self,request): user=User.objects.all() list=[] for i in u ...