REST API一对多,多对多调用设计

最近一直在思考Rest API的设计,普通的CRUD应用REST是比较简单并且明确的,大多数搜索结果都有REST API的设计理念,概括来说就是URL代表资源,HTTP Method代表要做什么事情,HTTP response status code代表做事情的结果,如:
Get /users/2
Response 404

代表了请求ID为2的User,返回了404代表资源没有找到。

https://www.zhihu.com/question/28570307 最高票回答也解决了一些在设计rest API涉及的问题,例如某些动词很难去名词化,这要涉及到业务的抽象,词性的转换。另外比如像search这种有两种词性的,其实设计的时候已经可以作为URL的一部分了。这点在github API中已经有体现:
https://api.github.com/
"repository_search_url": "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}",


类似login这种,虽然有提到是在操作session,但是在实际应用中,一般就非rest的处理了,用/login作为endpoint,大家看起来也不会认为有很大的问题。

在业务系统中会遇到更加复杂的问题,其中包括
  • 1. 一对多,多对多的rest API设计,包括创建,更新
  • 2. 双向绑定的循环序列化问题。


这里先记录一下我看到的针对1这个问题的处理。

一般来说,这种关联分两种情况:
[list]
  • 一种情况是多方的实体不能脱离单方的实体存在,或者多方的实体不会直接被获取,举例:
  • 每个人都有多条教育记录,而教育记录一般不需要直接使用,都是从个人为起点获取的。URL如下:
    GET /persons/{PERSON_ID}/edu-histories

  • 另外一种情况是多方实体和单方实体都是独立存在的,然而他们之间是有关联的。比如订单和商品,这时候就需要多个API了。
  • 获取单个订单 GET /orders/{order_id}
    获取单个商品 GET /products/{product_id}
    获取某个订单的所有商品  GET /orders/{order_id}/products
    获取某个商品关联的所有订单  GET /products/{product_id}/orders

    创建这种关联可以用POST/PUT/PATCH去实现,在body中加入被关联实体即可。具体实现在stackoverflow也有讨论应该用哪个method更符合规范,大家都比较提PATCH,实际应用中可以针对自己的web server支持不支持PATCH来做调整。

    在这种情况下,实体尽量单独返回,不要返回关联实体,例如获取order,不会直接把关联的product返回来。这样造成的一个缺陷就是,需要client端调用多次才能返回所有的结果。
    [/list]


    这种缺陷其实是RestAPI原本设计理念的第三层 -- hateoas 所提及的,即,每个restAPI发回的结果可能不仅仅是当前的一个结果,它还应当包含对其他相关对象引用的link,就像我们去访问一个网址,网址上不仅仅会返回给我们内容,还会给我们提供其他相关的超级链接一样。 只有完成了Hateoas才能算是真正的Restful。

    另外一种实现是把这种关联认为是一类资源,URL直接用relationship表示:
    GET /order-product-relationship
    [{"orderId":1,"productId":2},{"orderId":1,"productId":3}]



    待续

    猜你喜欢

    转载自wwwcomy.iteye.com/blog/2422101