Restfult接口规范
REST,即Representational State Transfer的缩写。RESTful架构,是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,基于这个风格设计的软件可以简洁,更有层次,更易于实现缓存等机制,所以正得到越来越多网站的采用。如果一个架构符合REST原则,就称它为RESTful架构。
本文即将描述的,即是创建RESTful架构的API所要遵循的原则与规范。
一、背景与基础概念
Web应用程序最重要的REST原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。
l 资源(resouce):网络上的一个实体或者是一个具体信息,可以是一段文本、一张图片、一种服务。
l 统一资源定位符(URI,Universal Resource Identifier):一个资源的识别符或者是一个地址,通过URI可以定位到特定的资源。要获取这个资源,需要访问它的URI,因此URI就成了每一个资源的地址或独一无二的识别符。
l 状态轮转换(State Transfer):所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。客户端与服务器互动的过程,通常涉及到服务器端数据和状态的变化过程,比如文件被修改,访问数量增加等。使用标准的HTTP方法,Http标准中主要定义以下几个动词:GET、POST、PUT、PATCH、DELETE。它们分别对应以下基本操作:
GET: 获取资源
POST: 新建资源
PUT: 全量更新资源
PATCH: 选择性更新资源
DELETE: 删除资源
二、RESTful API应遵循的原则
1) 协议
API与用户的通信协议,使用HTTP协议
2) 域名
应该尽量将API部署在专用域名之下
如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下
3) 版本
将API的版本号放入URL:api.example.com/v1/
注:需要注意版本规划,以便之后API的升级和维护。使得API版本变得强制性,不要发布无版本的API,使用简单数据,避免小数点如2.5。
4) 路径
路径表示API的具体网址URL。在RESTful架构中,每个URL代表一种资源(resource),所以网址中不能有动词,只能是名词,且所用的名词与代表的对象名称对应。一般来说,某一同种记录的”集合“(collection),所以API中的名词应该使用复数。
基本操作:
GET /users #获取用户列表
GET /users/{id} #查看某个具体的用户信息
POST /users #新增一个用户
PUT /users/{id} #全量更新某一个用户信息
PATCH /users/{id} #选择性更新某一个用户信息
DELETE /users/{id} #删除某一个用户
批量操作:
POST /users/mget #批量获取多个用户
POST /users/mcreate #批量创建多个用户
POST /users/mupdate #批量更新多个用户
POST /users/mdelete #批量删除多个用户
具体细则:
1. 关于分隔符”/“的使用
”/“分隔符一般用来对资源层级的划分。对于REST API来说,”/“只是一个分隔符,并无其他含义。为了避免混淆,”/“不应该出现在URL的末尾,如下两个地址表示的都是同一个资源:
REST API对URI资源的定义具有唯一性,一个资源对应一个唯一的地址。为了使接口保持清晰干净,如果访问到末尾包含 ”/“的地址,服务端应该转到没有”/“的地址上,此规则仅限REST API接口。
2. URI中尽量使用连字符”-“代替下划线”_“的使用
连字符”-“一般用来分割URI中出现的字符串(单词),来提高URI的可读性,如:
api.example/org/books/m…-my-first-post
3. URI中统一使用小写字母
URI是对大小写敏感的,所以为了避免歧义,应尽量用小写字符。如果是多个单词组合则使用“-”连接式用名规则,如:this-is-my-first-post。
4. 使用名词而不是动词。
举例来说,某个URL是/cards/show/1,其中show是动词,这个URL就设计错了,正确的写法应该是/cards/1,然后用GET方法表示show。如果某些动作是HTTP动词表示不了的,就应该把动作做成一种资源。如网上汇款,从账户1向账户2汇款500元,错误的URI是:POST /accounts/1/transfer/500/to/2。正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:POST /transaction?from=1&to=2&amount=500
5. 使用复数名词。不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
举例:
/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而不是 /setting
6. 使用子资源表达关系。如果一个资源与另外一个资源有关系,使用子资源。
举例:
GET /cars/911/drivers/ 返回car 911下的所有司机
GET /cars/911/drivers/8 返回car 911下的8号司机
GET /cars/911/drivers/8,9,10 返回car 911下的8,9,10号司机
7. 避免层级过深的URI
在URL中表达层级,用于按实体关联关系进行对象导航,一般根据id导航。过深的导航容易导致URL膨胀,不易维护,如:POST /accounts/1/transfer/500/to/2,应尽量使用查询参数代替路径中的实体导航,如:POST /transaction?from=1&to=2&amount=500
8. 状态码(Status Codes)
2xx:成功。200 成功,201 创建。
3xx:重定向。301 永久重定向,304 资源未修改。
4xx:客户端错误。400 错误请求,401 未授权, 403 禁止访问,404 未找到,405 请求方法不对。
5xx:服务器错误。500 服务器错误,502 网关错误,504 网关超时。
5) 参数接收
一次请求传递参数的方式主要有URL路径中、请求头中、请求体中等,下面分别对几种方式进行说明:
l MediaType的选择
MediaType即时Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http 协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。
u 对于POST、PUT、PATCH这种HTTP方法,统一使用application/json,将参数放在请求体中以JSON格式传递至服务器
u 对于GET、DELETE的HTTP方法,使用默认类型
注:特殊情况特殊处理,例如文件上传时,使用multipart/form-data类型
l 路径参数
对应SpringMVC框架中的@PathVariable注解
l 请求头参数
对应SpringMVC框架中的@RequestHeader注解
l 请求体参数
参数传递分为大体两种URL请求查询参数、请求体参数,对于请求体参数我们选择以JSON格式传递,URL请求查询参数、请求体参数分别对应SpringMVC框架中的@RequestParam、@RequestBody两个注解
例:POST MAN截图
成功返回信息
6) 返回值格式
目前主流的返回格式应该只有XML、JSON两种,在此我们使用JSON作为接口的返回格式。Spring boot默认成功/失败响应格式是不一致的,在此我们将成功/失败响应体格式设成一致,如下:
接口正确返回参数
序号 | 参数名 | 字段类型 | 字段描述 |
---|---|---|---|
1 | code | string | 状态码 200成功 |
2 | isOk | boolean | 状态 true成功 false 失败 |
3 | data | int | 成功条数 |
² 示例
接口错误返回参数
序号 | 参数名 | 字段类型 | 字段描述 |
---|---|---|---|
1 | code | string | 状态码 100失败 |
2 | isOk | boolean | 状态 true成功 false 失败 |
3 | msg | String | 错误信息 |
² 示例
为了实现以上这种JSON格式,我们自定义了ResultMsg类用于统一返回格式。返回正确结果时需要调用ResultMsg.SUCCESS("")方法,出现异常时需要调用ResultMsg.ERROR("异常提示");
示例
7) 通用分页
分页请求参数:
序号 | 参数名 | 字段类型 | 字段描述 |
---|---|---|---|
1 | page | string | 当前页数(必传,为空时默认1) |
2 | pageSize | string | 每页显示条数(必传,为空默认10) |
返回结果
序号 | 参数名 | 字段类型 | 字段描述 |
---|---|---|---|
1 | code | Object | 返回编码 |
2 | isOk | string | 返回状态 |
3 | page | boolean | 当前页数 |
4 | pageSize | int | 每页显示条数 |
5 | total | Object | 总数 |
6 | rows | Array | 数据列表,当没有查询到数据时返回[],空数 |
http://localhost:8082/violation/inspectInfo/selectViInfo
响应结果:
{
"code": "200",
"isOk": true,
"page": 1,
"pageSize": 10,
"rows": [
{
"createBy": "孙硕",
"createDate": "2022-11-07 17:47:30",
"delFlag": "0",
"id": "0044cdb81dfb6110b88518be3557433f"
},...
],
"total": 756
}
三、项目开发规范(※)
结合实际项目,现将Rest风格的规范进行重新调整:
1) 类定义
对外提供的接口Controller,必须加上@RestController、@RequestMapping,其中,RequestMapping应设置资源名称,如:@RequestMapping(“/books”)
2) 方法定义
所有的方法返回值设置为:Object,默认全部为POST提交类型,具体规则如下:
@PostMapping(“/add”) #新增
@PostMapping(“/batchAdd”) #批量新增
@PostMapping(“/delete”) #删除
@PostMapping(“/selects”) #根据条件查询
@PostMapping(“/select”) #根据主键查询
@PostMapping(“/update”) #更新
@PostMapping(“/batchUpdate”) #批量更新
3) 参数
除文件上传,所有的请求参数须加上@RequestBody,其后的参数类型只能是具体对象或Map类型,前台提交的参数格式为Json格式,例如: