前言
最近依旧在忙公司 KM 的项目,我负责的是部分核心模块的开发,已经实现了Servcie - DAO 层的开发,紧接开始着手实现 Controller 层,因为是基于 RESTful,所以必须定义好 RESTful API 的接口,才能进行功能的实现。
因为对 RESTful 理解的比较少,所以参考了GitHub的设计开发原则,以下的内容是我根据对 RESTful 的理解,针对公司项目设计接口。
项目-部分核心模块-部分功能
-
Disk : 网盘
网盘列表
-
Folder : 目录 (即网盘下的文件夹)
目录列表
目录重命名
目录移动
目录批量移动
目录下载
目录批量下载
-
File :文件(只能存在于目录下,不能存在网盘下)
文件列表(展示该目录下的子目录和文件)
文件收藏
文件分享
文件批量下载
跟着 Github 学习 Restful
-
RESTful 的关键
RESTful 定义可表示流程元素/资源的对象。在 REST 中,每一个对象都是通过URL来表示的,对象用户负责将状态信息打包进每一条消息内,以便对象的处理总是无状态的
资源分为单个文档和集合,尽量使用复数来表示资源,单个资源通过添加 id 或者 name 等来表示
一个资源可以有多个不同的 URL
资源可以嵌套,通过类似目录路径的方式来表示,以体现它们之间的关系
注意:根据RFC3986定义,URL是大小写敏感的。所以为了避免歧义,尽量使用小写字母
-
Method
-
举例:GitHub上对仓库的增删查改
GET /repos/:owner/:repo/issues GET /repos/:owner/:repo/issues/:number POST /repos/:owner/:repo/issues PATCH /repos/:owner/:repo/issues/:number DELETE /repos/:owner/:repo
-
Method | 描述 |
---|---|
GET | 获取资源 |
POST | 创建资源,会返回创建的资源 |
PATCH | 更新资源的部分属性。因为 PATCH 比较新,而且规范比较复杂,所以真正实现的比较少,一般都是用 POST 替代,会返回更新的资源 |
PUT | 替换资源,客户端需要提供新建资源的所有属性。如果新内容为空,要设置 Content-Length 为 0,以区别错误信息,会返回更新的资源 |
DELETE | 删除资源 |
-
把动作转换为资源
在设计的过程中,会发现,除了 CRUD 这四种操作,我们还会遇到其他的操作,这样就给我们在 API 的设计带来很大的麻烦,然而,RESTful 是一种设计风格而不是标准,只是提供了一组设计原则和约束条件,所以我们可以对接口进行灵活的设计,从而满足我们的业务需求。最常规的做法是为需要的动作增加一个 endpoint,选择一个 Method 来执行动作,比如 POST /email/:emailId/resend 重新发送邮件举例:GitHub上对仓库的加星操作
PUT /gists/:id/star DELETE /gists/:id/star
-
Query 实现更自由的查询
在对接口进行操作的时候,除了一些必要的参数,有时候需要一些非必要的参数进行条件控制,是用 query 参数进行控制,避免了在接口设计的硬性规定,实现更大的自由度。
举例: 查询某个 repo 下面 issues 的时候,可以通过以下参数来控制返回哪些结果:
state:issue 的状态,可以是 open,closed,all
since:在指定时间点之后更新过的才会返回
assignee:被 assign 给某个 user 的 issues
sort:选择排序的值,可以是 created、updated、comments
direction:排序的方向,升序(asc)还是降序(desc)
per_page:每页返回多少资源,如果没提供会使用预设的默认值
page:要获取哪一页的资源,默认是第一页
-
批量操作实现
设计方法有很多种,借用Backbone.js 的说法:There's More Than One Way To Do It,不要太纠结
-
举例:多种设计方案
//简约的设计 GET /ec2/instance/batch?id=aa,bb,cc: //健壮的设计 GET /ec2/instance?batch={"ids":["aa","bb","cc"]}: // GET /ec2/instance?batch=[{"method":"DELETE","id":"aa"},{"method":"DELETE","id":"bb"},{"method":"DELETE","id":"cc"}]:
功能的RESTful API 设计
-
Disk : 网盘
网盘列表 :/disks
-
Folder : 目录 (即网盘下的文件夹)
目录列表 :GET: /disks/:diskId/folders
目录重命名 :PATCH:/disks/:diskId/folders/:folderId/rename/:name
目录移动 :PATCH:disks/:diskId/folders/:folderId/moveto/folderId/:folderId
目录下载 :GET:disks/:diskId/folders/:foderId/download
-
File :文件(只能存在于目录下,不能存在网盘下)
文件列表 :GET:disks/:diskId/folders/:folders/files
文件收藏 :PATCH:disks/:diskId/folders/:folderId/files/:fileId/collect
文件分享 :PATCH:disks/:diskId/folders/:folderId/files/:fileId/share
-
批量操作:
多个fileObj移动:PATCH:disks/:diskId/fileobjs/moveto/folderId/:folderId?请求包体
多个fileObj删除:DELETE:disks/:diskId/fileobjs?请求包体
-
多个fileObj下载:GET:disks/:diskId/fileobjs/download?请求包体
请求包体:
请求包体:"fileObjects": [ { "fileObjectId": fileId, "isFolder": true / false } ]
以上的设计其实还没得到上级的通过,其实还需要继续改进,不过这一轮的设计让我对 RESTful 的使用有了一定的了解,虽然还没深入研究 RESTful 核心的部分,但是,通过 URL 操作资源这种设计思路,的确是让人眼前一亮。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。