朱晔的互联网架构实践心得S2E5:浅谈四种API设计风格(RRC、REST、GraphQL、服务端
Web API设计其实是一个挺重要的设计话题,许多公司都会有公司层面的Web API设计规范,几乎所有的项目在详细设计阶段都会进行API设计,项目开发后都会有一份API文档供测试和联调。本文尝试根据自己的理解总结一下目前常见的四种API设计风格以及设计考虑点。
RPC这是最常见的方式,RPC说的是本地调用远程的方法,面向的是过程。
RPC形式的API组织形态是类和方法,或者说领域和行为。
因此API的命名往往是一个动词,比如GetUserInfo,CreateUser。
因为URI会非常多而且往往没有一些约定规范,所以需要有详细的文档。
也是因为无拘无束,HTTP方法基本只用GET和POST,设计起来比较简单。
这里就不贴例子了,估计超过50%的API是这种分格的。
REST是一种架构风格,有四个级别的成熟度:
级别 0:定义一个 URI,所有操作是对此 URI 发出的 POST 请求。
级别 1:为各个资源单独创建 URI。
级别 2:使用 HTTP 方法来定义对资源执行的操作。
级别 3:使用超媒体(HATEOAS)。
级别0其实就是类RPC的风格,级别3是真正的REST,大多数号称REST的API在级别2。REST实现一些要点包括:
REST形式的API组织形态是资源和实体,一切围绕资源(级别1的要点)。设计流程包括:
确定API提供的资源
确定资源之间的关系
根据资源类型和关系确定资源URI结构
确定资源的结构体
会定义一些标准方法(级别2的要点),然后把标准方法映射到实现(比如HTTP Method):
GET:获取资源详情或资源列表。对于collection类型的URI(比如/customers)就是获取资源列表,对于item类型的URI(比如/customers/1)就是获取一个资源。
POST:创建资源,请求体是新资源的内容。往往POST是用于为集合新增资源。
PUT:创建或修改资源,请求体是新资源的内容。往往PUT用于单个资源的新增或修改。实现上必须幂等。
PATCH:部分修改资源,请求体是修改的那部分内容。PUT一般要求提交整个资源进行修改,而PATCH用于修改部分内容(比如某个属性)。
DELETE:移除资源。和GET一样,对于collection类型的URI(比如/customers)就是删除所有资源,对于item类型的URI(比如/customers/1)就是删除一个资源。
需要考虑资源之间的导航(级别3的要点,比如使用HATEOAS,HATEOAS是Hypertext as the Engine of Application State的缩写)。有了资源导航,客户端甚至可能不需要参阅文档就可以找到更多对自己有用的资源,不过HATEOAS没有固定的标准,比如:
{ "content": [ { "price": 499.00, "description": "Apple tablet device", "name": "iPad", "links": [ { "rel": "self", "href": ":8080/product/1" } ], "attributes": { "connector": "socket" } }, { "price": 49.00, "description": "Dock for iPhone/iPad", "name": "Dock", "links": [ { "rel": "self", "href": ":8080/product/3" } ], "attributes": { "connector": "plug" } } ], "links": [ { "rel": "product.search", "href": ":8080/product/search" } ] }Spring框架也提供了相应的支持:https://spring.io/projects/spring-hateoas,比如如下的代码:
@RestController public class GreetingController { private static final String TEMPLATE = "Hello, %s!"; @RequestMapping("/greeting") public HttpEntity<Greeting> greeting( @RequestParam(value = "name", required = false, defaultValue = "World") String name) { Greeting greeting = new Greeting(String.format(TEMPLATE, name)); greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel()); return new ResponseEntity<>(greeting, HttpStatus.OK); } }产生如下的结果:
除了之前提到的几个要点,REST API的设计还有一些小点:
必须无状态的,相互独立的,不区分顺序的
API需要有一致的接口来解耦客户端和服务实现,如果基于HTTP那么务必使用HTTP的Method来操作资源,而且尽量使用HTTP响应码来处理错误
需要尽量考虑缓存、版本控制、内容协商、部分响应等实现
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/47814.html