RESTful API

首先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,在基本的增删改查接口之外,通常会设计一些业务接口(根据业务逻辑需要,一个接口中对多个资源的数据进行整合再返回)。

 

上一篇:Python爬取某财经网头条信息一段小程序


下一篇:mongoose 演示增删改查,完整版案例