Rest API 设计
【问题】
在以前的项目经验中,接口请求都是GET或者POST方式;接口定义都是以动词开头,比如,按名称查询某用户信息,都是写成queryByUserName;接口不管对内还是对外,都是一套,也没有所谓的版本,等等。这一系列问题,都是Restful风格中不允许出现的,所以在提供对外接口前,先学习了下,如何设计Restful风格API,从而让第三方使用我们的接口第一感觉就是专业和规范。
【安全与幂等】
每一种HTTP请求方法都可以从安全性和幂等性两方面考虑,要定义严谨的REST统一接口,就需要真正理解HTTP方法的安全性和幂等性。
安全性是指对外系统对该接口的访问,不会使服务器端资源的状态发生变化;幂等性是指外系统对同一REST接口的多次访问,得到的资源状态是相同的。
【HTTP请求】
- GET
只读操作的请求,用于读取资源,它既是安全的,也是幂等的。但可能因为不良的API设计,使得违背其特性。
标准的命名方式是单数的操作以资源名称命名,批量的操作以资源名称的复数名称命名。比如同步订单可用order和orders。
- PUT
是一种写操作的HTTP请求,用于更新或添加资源。PUT方法是幂等的,即多次插入或更新同一份数据,在服务器端对资源状态所产生的改变是相同的。但PUT方法是不安全的,有写动作的HTTP方法都是不安全的。
- POST
用于写数据,其特性是既不幂等也不安全。由于请求会改变服务器端资源状态,因此是不安全的;由于每次请求对服务器端的资源状态的改变并不是相同的,所以它不是幂等的。
- DELETE
该方法是幂等的,即多次删除同一份数据(通常请求中传递的参数是数据的主键值),在服务器端产生的改变是相同的。
执行删除的资源方法,其返回值可以定义为void,即没有任何返回值。因为删除的前提是对该资源信息已经充分了解,没有必要再将其从服务器上传递回来。
【请求比较】
在创建某个和更新某个资源的时候,可能我们比较迷茫的是何时使用PUT方法,何时使用POST方法。
- 更新资源
由于使用同一份数据向服务器请求更新某一资源,得到的结果应该总是相同的,因此,对于更新操作,使用PUT方法是没有问题的。
- 创建资源
创建操作每次得到的结果是不同的,因为服务器端的业务逻辑通常要求数据的主键字段是不同的,要么是业务上自增的一个逻辑值,要么是数据库的主键自增,因此,相同的数据每一次提交到服务器端,都会为数据添加一个新的主键值,也就是创建一个主键值不同的新资源。所以创建操作通常应该设计为POST方法的API。
【使用示例】
请求方法 | 请求示例 | 请求说明 |
---|---|---|
GET | /orders | 查询所有订单 |
POST | /orders | 创建一个订单 |
GET | /orders/ID | 获取某个订单的信息 |
PUT | /orders/ID | 更新某个指定订单的信息 |
DELETE | /orders/ID | 删除某个订单 |
【设计指导】
(一)使用名词而不是动词
资源(Resource) | 读(GET) | 创建(POST) | 修改(PUT) | 删除(DELETE) |
---|---|---|---|---|
/orders | 返回orders集合 | 创建新的资源 | 批量更新orders | 删除所有的orders |
/orders/100 | 返回特定的order | 该方法不允许(405) | 更新一个指定的资源 | 删除指定的资源 |
而不要使用:
/getAllOrders
/createNewOrder
/deleteAllOrders
(二)使用复数名词
不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
/orders 而不是 /order
/users 而不是 /user
/cars 而不是 /car
(三)Get方法和查询参数不应该涉及状态改变
使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态
(四)为集合提供过滤 排序 选择和分页等功能
- Filtering过滤:
使用唯一的查询参数进行过滤:
GET /orders?compID=15 返回某个供应商的订单
GET /orders?orderMoney>1000 返回订单金额大于1000的orders集合
- Sorting排序:
允许针对多个字段排序
GET /orders?sort=-createTime,+orderMoney
这是返回根据创建时间降序和金额升序排列的order集合
- Field selection
移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。
GET /orders?fields=createTime,orderMoney,id,buyerAddress
- Paging分页
使用 limit 和offset.实现分页,缺省limit=20 和offset=0;
(五)版本化API
使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.
一般在Url后面使用?v
/orders/api/v1
(六) 使用Http状态码处理错误
如果你的API没有错误处理是很难的,只是返回500和出错堆栈不一定有用
Http状态码提供70个出错,我们只要使用10个左右:
- 200 – OK – 一切正常
- 201 – OK – 新的资源已经成功创建
- 204 – OK – 资源已经成功擅长
- 304 – Not Modified – 客户端使用缓存数据
- 400 – Bad Request – 请求无效,需要附加细节解释如 “JSON无效”
- 401 – Unauthorized – 请求需要用户验证
- 403 – Forbidden – 服务器已经理解了请求,但是拒绝服务或这种请求的访问是不允许的。
- 404 – Not found – 没有发现该资源
- 422 – Unprocessable Entity – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。
- 500 – Internal Server Error – API开发者应该避免这种错误。
还没有评论,来说两句吧...