我正在构建 HTTP REST API 并为 API 实现 CQRS、DDD、ES 和微服务概念。
例如,我想为订购系统构建 API。订单包含订单状态、客户数据、员工数据、购物车项目、运输数据。订单命令服务和订单查询服务使用不同的代码,不同的数据库。和不同的IP/端口。
客户数据包括客户 ID、名字、姓氏、联系电话等。销售和员工等员工数据包括员工 ID、电子邮件、姓名和角色。送货数据包括送货地址、城市、邮政编码、送货单、送货方式和送货费用。购物车项目包含产品 ID 和数量。客户数据、产品数据、员工数据和运输方式数据来自其他服务。
当我想开发它时,我有两个问题。
我应该怎么做才能以正确的方式开发 HTTP REST API?
谢谢你。
我正在构建 HTTP REST API 并为 API 实现 CQRS、DDD、ES 和微服务概念。
凉爽的。牢记 REST API 部分是集成组件的一部分;其目的是确保老客户可以继续利用您的服务,即使这些服务的实施不断发展。
Jim Webber,RESTful 系统的领域驱动设计
Web 不是您的域,它是一个文档管理系统。所有 HTTP 动词都适用于文档管理域。URI 不映射到域对象 - 这违反了封装。工作(例如:向域模型发出命令)是管理资源的副作用。换句话说,资源是反腐败层的一部分。您应该期望在您的集成域中拥有比在您的业务域中拥有的业务对象更多的资源。
当我构建 POST 方法以从销售/员工创建新订单时,请求有效负载中应该包含什么?
请注意上面关于“更多资源”的观点——您可以提供尽可能多的不同方式(协议)来创建您愿意支持的新订单。
从微服务的角度来看,下单可能涉及到许多不同的业务能力。参见 Udi Dahan 关于UI Composition Techniques的著作,同样的问题也出现在机器对机器的界面中。
因此,从最终与服务通信订单的 Web 端点的角度来看,您需要的信息将取决于公开的端点需要什么。
从客户端的角度来看:提供REST API的部分意义在于集成资源可以引导客户端构建最终提交。想想在线购物体验 - 亚马逊不会要求您输入一堆 SKU 或客户 ID。您只需提交一系列表单,直到出现一个允许您对数据进行最后一次检查的屏幕,然后如果看起来正确,您就提交它。
因此,沿途的屏幕之一可以帮助客户确定员工 ID 应该是什么(这是一个搜索表单,这是一个可供选择的列表等)。
当我构建 POST / PUT 方法时,我应该返回响应代码 200 吗?
一般来说,200就可以了。除非您预计客户会对不同形式的成功做出巧妙的反应,否则这将涵盖您的大多数情况。
202 Accepted是一种更细粒度的状态,通常在处理不会立即完成时使用。“嗨,我们收到了您的订单。这是一个链接,您可以使用它来查看进度。”
例如,如果您使用的架构中 REST api 将简单地将订单请求写入队列以供微服务消费者接收,那么 202 在概念上是准确的“我们写下来,服务将自行决定怎么办”。
用户希望立即获取订单数据。
Instantly不是您可能遇到的延迟,因此您需要一个更宽容的 SLA。
我没想到会出现这种问题;毕竟,如果您的设计是 CQRS,您可以对热缓存中的大量可用数据进行非规范化表示。如果该表示是可独立寻址和可缓存的,则您可以重用存储在客户端上的副本。
但是,后端 API 如何知道用户想要按订单购买该产品?我们收到 SKU 作为有效载荷,不是吗?
不一定——我们会收到 REST API 可以用来计算 SKU 的东西。它可能是别的东西。但是 SKU 很好:从客户端的角度来看,主要的一点是消息格式没有改变;从购物者的角度来看,主要的一点是,她不必关心有效载荷中的内容,因为她有稳定的语义线索可以工作(即:她正在查看产品名称,但在封面是 SKU)。
映射 HTTP 动词、URI 和域对象的理想方法是什么?
反过来说:让您的后端服务看起来像一个网站的正确方法是什么?
曾经使用您的网络浏览器配置无线路由器吗?它是如何工作的——路由器内部与网站完全不同。您用来询问堆栈溢出问题的应用程序没有理由应该用作路由器配置工具。然而它确实如此,因为路由器上的 API 知道如何像网站一样躲避,同时向后端发送正确的指令。
REST 客户端只查看它收到的消息;它不知道任何有关域对象; 它只知道资源的表示(想想描述事物的文档)。
映射 HTTP 动词等的理想方式,它伪装成一个愚蠢的文档存储。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句