1

前言

  最近依旧在忙公司 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 操作资源这种设计思路,的确是让人眼前一亮。


Seven_Nee
614 声望53 粉丝