首先API设计六要素
1. 资源路径(URI)
资源:所有在服务器保存的数据(如:音乐/视频/文章/个人信息...)都是服务器端资源.(项目中资源通常都是指的数据表的一条数据)
URI(Uniform Resource Identifier):统一资源标志符,包含URL和URN。
URL(Uniform Resource Locator):统一资源定位符
URN(Uniform Resource Name):统一资源命名
2. HTTP动词(Method)
对于资源, 一般有4个操作, CURD(增/删/改/查)
GET: 从服务器获取资源(一项或多项)
POST: 在服务器新建一个资源
PUT: 在服务器更新资源, 服务器返回完整的属性
DELETE: 从服务器删除资源
3. 过滤信息(query-string)
通常也叫做请求参数或查询字符串。
4. 状态码(Status-code)
服务端返回的信息, 用来告诉客户端操作结果。
GET
200(OK) - 表示已在响应中发出
204(无内容) - 资源有空表示
301(Moved Permanently) - 资源的URI已被更新
303(See Other) - 其他(如,负载均衡)
304(not modified)- 资源未更改(缓存)
400 (bad request)- 指代坏请求(如,参数错误)
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务端当前无法处理请求
POST
200(OK)- 如果现有资源已被更改
201(created)- 如果新资源被创建
202(accepted)- 已接受处理请求但尚未完成(异步处理)
301(Moved Permanently)- 资源的URI被更新
303(See Other)- 其他(如,负载均衡)
400(bad request)- 指代坏请求
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
409 (conflict)- 通用冲突
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)- 接受到的表示不受支持
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务当前无法处理请求
PUT
200 (OK)- 如果已存在资源被更改
201 (created)- 如果新资源被创建
301(Moved Permanently)- 资源的URI已更改
303 (See Other)- 其他(如,负载均衡)
400 (bad request)- 指代坏请求
404 (not found)- 资源不存在
406 (not acceptable)- 服务端不支持所需表示
409 (conflict)- 通用冲突
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)- 接受到的表示不受支持
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务当前无法处理请求
DELETE
200 (OK)- 资源已被删除
301 (Moved Permanently)- 资源的URI已更改
303 (See Other)- 其他,如负载均衡
400 (bad request)- 指代坏请求
404 (not found)- 资源不存在
409 (conflict)- 通用冲突
500 (internal server error)- 通用错误响应
503 (Service Unavailable)- 服务端当前无法处理请求
5. 错误信息(Error)
如果状态码是4xx或者5xx, 需要告诉客户端对应的错误信息. 通常以Json格式返回:
{
“error”: “错误信息”,
}
6. 返回结果(Result)
针对不同的操作, 服务需要返回的结果应该符合这样的规范
GET /collections -- 返回资源列表(数组)
GET /collections/:id -- 返回单个资源 eg. /collections/1
POST /collections -- 返回新生成的资源
PUT /collections/:id -- 返回资源的完整属性
DELETE /collections/:id -- 返回204状态码+空文档
实际开发中,通常会将 状态码、错误信息、返回数据,都放到返回结果中。
{"code":200, 'msg':'success', "data":{"id":1,"goods_name":"tp"}}
RestFul接口设计风格
RESTFul是一种软件设计风格, 主要用于有客户端与服务端交互的软件.
RESTFul 是目前最流行的 API 设计规范,用于 Web 数据接口的设计。
RESTFul风格的数据接口示例:
以新闻资源为例:URI及HTTP动词设计如下
| HTTP动词 | URI路径 | 说明 |
| -------- | -------------------- | ------------------ |
| GET | http://域名/news | 获取列表数据 |
| GET | http://域名/news/:id | 根据id获取一条数据 |
| POST | http://域名/news | 添加一条数据 |
| PUT | http://域名/news/:id | 根据id修改一条数据 |
| DELETE | http://域名/news/:id | 根据id删除一条数据 |
RestFul实战
①创建api模块
php think build --module api
②创建news控制器
php think make:controller api/News
③设置路由(application/route.php)
Route::resource('news','api/news');
相当于分别设置了以下路由:
Route::get('news','api/news/index'); Route::get('news/create','api/news/create'); Route::post('news','api/news/save'); Route::get('news/:id','api/news/read'); Route::get('news/:id/edit','api/news/edit'); Route::put('news/:id','api/news/update'); Route::delete('news/:id','api/news/delete');
设置后会自动注册7个路由规则,如下:
| **标识** | **请求类型** | **生成路由规则** | **对应操作方法(默认)** |
| -------- | ------------ | ---------------- | ------------------------ |
| index | GET | news | index |
| create | GET | news/create | create |
| save | POST | news | save |
| read | GET | news/:id | read |
| edit | GET | news/:id/edit | edit |
| update | PUT | news/:id | update |
| delete | DELETE | news/:id | delete |
④修改News控制器,返回json格式数据
<?php namespace app\api\controller; use think\Controller; use think\Request; class News extends Controller { /** * 显示资源列表 * * @return \think\Response */ public function index() { return json(['code' => 200, 'msg' => 'success', 'data'=>'index']); } /** * 显示创建资源表单页. * * @return \think\Response */ public function create() { return json(['code' => 200, 'msg' => 'success', 'data'=>'create']); } /** * 保存新建的资源 * * @param \think\Request $request * @return \think\Response */ public function save(Request $request) { return json(['code' => 200, 'msg' => 'success', 'data'=>'save']); } /** * 显示指定的资源 * * @param int $id * @return \think\Response */ public function read($id) { return json(['code' => 200, 'msg' => 'success', 'data'=>'read']); } /** * 显示编辑资源表单页. * * @param int $id * @return \think\Response */ public function edit($id) { return json(['code' => 200, 'msg' => 'success', 'data'=>'edit']); } /** * 保存更新的资源 * * @param \think\Request $request * @param int $id * @return \think\Response */ public function update(Request $request, $id) { return json(['code' => 200, 'msg' => 'success', 'data'=>'update']); } /** * 删除指定资源 * * @param int $id * @return \think\Response */ public function delete($id) { return json(['code' => 200, 'msg' => 'success', 'data'=>'delete']); } }
通过接口调试插件 或者 postman 分别访问以下七个地址:
请求方式 请求地址 get http://www.tpshop.com/news get http://www.tpshop.com/news/create post http://www.tpshop.com/news get http://www.tpshop.com/news/33 get http://www.tpshop.com/news/33/edit put http://www.tpshop.com/news/33 delete http://www.tpshop.com/news/33
ajax请求restful接口:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax请求restful接口</title> <script src="/static/admin/js/jquery-1.8.1.min.js"></script> </head> <body> <input type="button" id="index" value="index"> <input type="button" id="create" value="create"> <input type="button" id="save" value="save"> <input type="button" id="read" value="read"> <input type="button" id="edit" value="edit"> <input type="button" id="update" value="update"> <input type="button" id="delete" value="delete"> <script> $(function(){ $('#index').click(function(){ $.ajax({ "url":"/news", "type":"get", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#create').click(function(){ $.ajax({ "url":"/news/create", "type":"get", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#save').click(function(){ $.ajax({ "url":"/news", "type":"post", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#read').click(function(){ $.ajax({ "url":"/news/33", "type":"get", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#edit').click(function(){ $.ajax({ "url":"/news/33/edit", "type":"get", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#update').click(function(){ $.ajax({ "url":"/news/33", "type":"put", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); $('#delete').click(function(){ $.ajax({ "url":"/news/33", "type":"delete", "data":"", "dataType":"json", "success":function(res){ console.log(res); } }); }); }); </script> </body> </html>
Restful常用的资源路由
新增页面页面展示 create方法 和 修改页面页面展示 edit方法 一般可以不用。
| 标识 | 请求类型 | 生成路由规则 | 对应操作方法(默认) | 备注 |
| ------ | -------- | ------------ | -------------------- | ---------------------------------- |
| index | GET | news | index | 查询多条数据(列表) |
| read | GET | news/:id | read | 查询一条数据(详情、修改页面展示) |
| save | POST | news | save | 新增一条数据 |
| update | PUT | news/:id | update | 修改一条数据 |
| delete | DELETE | news/:id | delete | 删除一条数据 |
实际开发中的Restful
Restful接口通常返回的是完整的数据模型,粒度过于“粗”,对客户端不友好(客户端可能只需要其中一小部分字段)。
Restful典型使用场景:开放API(各种开放平台的数据api)。开放API之所以开放,就是因为不知道也不关心客户端需要什么返回结果,直接返回完整的数据,好处是通用。
实际开发中,通常都是内部接口开发,需求非常明确,所以一般都是灵活借鉴Restful中的优点,结合自己的实际情况,来设计自己的内部api,在基本的增删改查接口之外,通常会设计一些业务接口(根据业务逻辑需要,一个接口中对多个资源的数据进行整合再返回)。