有些项目的 URI 是 Restful 风格,但是项目本身并不是 RESTful项目,即,返回的仍是 html 格式字符串,而非 json
格式字符串。
在这里,我们只谈论 URL 的风格规范,而不强求是否是『真·RESTful』项目。
1. 以资源为中心的 URL 设计
『资源』是 Restful API 的核心元素,所有的操作都是针对特定资源进行的。
1. 资源分为单个文档和集合,尽量使用『复数』 来表示资源,单个资源通过『嵌入』id 来表示。例如:
/students
/students/9527
2. URL 中『只能』嵌入 id,不能嵌入其它条件。例如:
/students/9527
3. 资源可以『嵌套』,通过类似目录路径的方式来表示,以体现它们之间的关系
/students/9527/teachers
/teachers/10086/courses
4. 一个资源可以有多个不同的 URL,即,多个不同的 URL 可能、可以指向同一个资源,也就是说,一个资源可以
有多种 URL 表现形式。例如:
/students/9527/dormitory
/dormitory/3306
5. 理论上,URL 应该是大小写敏感的。所以为了避免歧义,尽量使用『小写』字母。
6. 命名中出现多个单词的,尽量使用『串型命名法』。例如:
/index-page
/login-page
2. CRUD 操作请求
2.1 严格情况
请求方式 描述 GET 获取资源 POST 创 建资源 PUT 更新资源 DELETE 删除资源 | |
例如:
请求方式 描述
GET 获取资源
POST 创建、更新、删除资源
URL 中不要出现动词。反例:
理论上 URL 中 不应该 出现动词。
2.2 非严格情况
这种情况下,如何在 POST 请求的 URL 中描述当前操作是增删改中的哪一种就是一个问题。见下章。
2.3 特殊情况
有时候 (包括上章的非严格情况) 想要执行的操作、行为,无法完美匹配『增删改』这三个字,需要使用别的动词来描述
所操作的行为。此时,怎么办?
方案有多种,这里我们采用如下这种:
在特殊情况下,允许违背 RESTful 的 URL 严格要求,允许在 URL 中出现动词,但是只允许在 URL 的『最末端』出
现动词。例如:
# 发布一篇文章
POST /articles/9527/publish
# 重新发送邮件
POST /mails/9527/resend
4. 分页查询及返回
分页请求参数
当要进行分页查询时,在请求原有 API 的基础上,可额外附带如下 (或类似参数) 两个参数:
参数 含义
page_number 表示请求第几页
page_size 表示每页最多显示多少条记录
你也可以将普通查询和分页查询统一起来。即,认为所有的查询都认为是分页查询,在客户端没有提供这两个
参数时,认为它俩是默认值,例如 (1, 10) 。
分页返回
返回资源集合时,包含于分页有关的数据。例如:
{
...,
"page_number": 1, # 当前是第几页
"page_size": 10, # 每页多少数据
"pages": 3, # 总共多少页
"has_next": true, # 是否有下一页数据
"has_prev": false, # 是否有前一页数据
"total": 27, # 总共多少数据
"data": [ # 查询结果
{ ... },
{ ... },
{ ... }
]
}
排序参数
如果需要后端排序,那么约定前端请求时,发送类似如下参数
参数 含义
sortby 进行排序的列名、属性名。
order 升序 (asc) ,或降序 (desc)
指定返回结果按照哪个属性排序,以及排序顺序。
# 增
PUT /students/9527
# 删
DELETE /students/9527
# 改
POST /students
# 查
GET /students
GET /teachers/10086/courses
/getAllCars
/createNewCar
/deleteAllRedCars
5. RESTful 请求返回的状态码
RESTful 返回状态吗有两大『流派』:
重用 HTTP 响应状态码
自定义状态码
我们采用第二种 自定义状态码 。
1. 无条件返回 200 。这样前端开发人员就不用纠结应该走哪个返回码的判断逻辑。但这个 200 不代表请求一定就
是成功的,这要接着看第二条。
{
...,
"page_number": 1, # 当前是第几页
"page_size": 10, # 每页多少数据
"pages": 3, # 总共多少页
"has_next": true, # 是否有下一页数据
"has_prev": false, # 是否有前一页数据
"total": 27, # 总共多少数据
"data": [ # 查询结果
{ ... },
{ ... },
{ ... }
]
}
2. 返回的数据中,自带自定义的状态码 (和对应的状态信息) ,例如: { code: 9527, msg: 'xxxx', data: ...
} 。前端开发人员靠这里的 code 的值作为标准,判断请求是否成功,而非 HTTP 请求的那个 200 。