一:RESTful是什么
- 1:RESTful是一种架构风格,是一种描述语言,不是一个标准
- 2:RESTful核心就是rest,rest是几个单词的缩写(REpresentational State Transfer),各种国人写的文档都是直译为:表现层状态转移。这对一些刚接触的人来说都是一脸懵,和我们刚接触Spring的IOC(控制反转)一样,理解了好长时间才明白其中意思。很多软件的一些专业词汇都缺乏主语和宾语,增加了理解的难度。rest的主语就是各种Resource(文档,音乐,视频)。具体真正完整的描述应该是:资源在网络请求中以某种的表现形式把状态进行了改变
- 3:资源在网络上有特定的实体,互联网有一个统一资源定位符(URI)来指向它
- 4:REST使用的是HTTP,URI,XML等已有的协议和标准
二:为什么要使用RESTful架构风格的接口
- 统一请求风格,用于各种前端的访问
- Restful的API是面向资源的,非常清晰,根据url就知道内容
- 轻量,直接基于http
三:设计RESTful接口的规范
概念 |
含义 |
幂等性 |
一个操作或者多个操作导致资源的结果是一样的 |
RFC |
Internet服务的标准,通常标准文件由数字标识,数字越大,代表标准越新 |
URI |
表示资源,资源对应的是服务器端领域模型的实体类 |
Endpoint |
路径,表示api的具体网址 |
- 我们在设计符合restful规则API时候要知道我们一个api是对资源的操作,这是个前提。所以我们重要考虑的点在URI的Endpoint,请求方式,入参,返回结果和异常这几个方面来考虑
1:URI规范
@GetMapping("/api/app/Order") //Order大写字母开头,错误
@GetMapping("/api/app/orders") //正确
@GetMapping("/api/app/order") //order不是复数,错误
@GetMapping("/api/app/orders") //正确
@GetMapping("/api/app/order_type/1") //错误
@GetMapping("/api/app/order-type/1") //正确
- (4)避免层级过深的URI,过深导航会导致URI膨胀,不易维护
@GetMapping("/api/app/orders/1/good-type/1") //错误
@RequestMapping("/api/app/orders"){
@RequestParam(value = "goodType") Integer goodsType} //正确
2:Request规范
- HTTP有五种方法对URI进行CURD操作,每个的幂等性都不一样,可以按照下面规范定义不同的操作
方法 |
含义 |
幂等性 |
DEMO |
GET |
查询 |
是 |
/api/orders |
POST |
新增 |
否 |
/api/orders |
PUT |
修改完整资源 |
是 |
/api/orders/1 |
PATCH |
修改部分属性 |
否 |
/api/orders/1 |
DELETE |
删除资源 |
是 |
/api/orders/1 |
3:response规范
- (1)只返回数据,不包装,我们的一个具体的测试工程项目返回的接口,只有返回数据
{
"id": "1246021398806081538",
"projectName": "沈磊的项目",
"companyId": "1246020467318276097",
"companyName": "沈磊的企业",
"address": "北京第二小学",
"type": 3,
"firstPartName": "我不太清楚甲方是谁",
"secondPartName": null,
"contractAmount": 222558,
"deviceCategory": 5,
"deviceBrand": "北京",
"deviceAmount": 333586,
"upstreamSupplierType": 3,
"upstreamSupplierName": "上游供应商的东西",
"createBy": "艾新建",
"updateTime": "2020-04-03 18:27:20",
"updateBy": "艾新建"
}
方法 |
返回格式 |
GET |
查询的对象 |
POST |
新增成功的对象 |
PUT |
更新成功的对象 |
PATCH |
更新成功的对象 |
DELETE |
空 |
4:错误码规范
- 业务类异常controller层做统一拦截,统一错误码500
- 使用http自带的状态码,不许自定义
5:完整的demo
根据我们已有的项目,包含完整的CURD的操作,展示出来供参考
@ApiOperation(value = "查询工程项目详情",notes = "查询工程项目详情",httpMethod = "GET")
@GetMapping("/{id}")
public Project detail(@PathVariable("id") Long id) {
return projectService.detail(id);
}
@ApiOperation(value = "添加工程项目",notes = "添加工程项目",httpMethod = "POST")
@PostMapping
public Project add(@RequestBody@Valid ReqProject req) {
return projectService.add(req);
}
@ApiOperation(value = "修改项目工程", notes = "修改工程项目", httpMethod = "PUT")
@PutMapping
public Project update(@RequestBody @Valid ReqProject req) {
return projectService.update(req);
}
@ApiOperation(value = "查询工程项目列表(分页)",notes = "查询工程项目列表(分页)",httpMethod = "GET")
@GetMapping(value = "/page")
public IPage<RespProject> page(ReqProjectQuery req) {
return projectService.page(req);
}
@ApiOperation(value = "删除工程项目",notes = "删除工程项目",httpMethod = "DELETE")
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") Long id) {
log.info("查询工程信息详情入参:{}",id);
projectService.delete(id);
}