037、RESTful设计风格

    xiaoxiao2025-08-07  15

    在进行API接口设计时,不同的开发人员可能有不同的设计风格,风格迥异。

    那是否存在一种统一的接口设计方式,被广大开发人员所接受呢?

    答: 这就是被普遍采用的RESTful API设计风格。

    1. Restful风格设计-关键点

    1. URL路径

    路径又称"终点"(endpoint),表示API的具体网址,每个网址代表一种资源(resource)。

    (1)URL地址尽量使用名词,不使用动词。

    举例来说,以下是不好的例子:

    /getProducts /listOrders

    对于一个简洁结构,应该始终用名词。

    GET /products:将返回所有产品信息

    POST /products:将新建产品信息

    GET /products/4:将获取产品4

    PUT /products/4:将更新产品4

    (2)API中的名词应该使用复数,无论单个资源或者所有资源。

    举例来说,获取产品的API可以这样定义:

    获取单个产品:http://127.0.0.1:8080/products/1

    获取所有产品: http://127.0.0.1:8080/products

    2. 请求方式

    访问同一个URL地址,采用不同的请求方式,代表要执行不同的操作。

    常用的HTTP请求方式有下面四个:

    请求方式

    说明

    GET

    获取资源数据(单个或多个)

    POST

    新增资源数据

    PUT

    修改资源数据

    DELETE

    删除资源数据

    例如:

    GET /zoos:列出所有动物园 POST /zoos:新建一个动物园(上传文件) GET /zoos/ID:获取某个指定动物园的信息 PUT /zoos/ID:更新某个指定动物园的信息 DELETE /zoos/ID:删除某个动物园

    3. 过滤信息

    过滤参数可以放在查询字符串中。

    在访问API接口获取数据时,可能需要对数据进行过滤。

    下面是一些常见的参数:

    ?limit=10:指定返回记录的数量 ?offset=10:指定返回记录的开始位置。 ?page=2&per_page=100:指定第几页,以及每页的记录数。 ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。

    4. 响应数据

    针对不同操作,服务器向用户返回的响应数据应该符合以下规范:

    GET /collection:返回资源对象的列表数据。 GET /collection/resource:返回单个资源对象数据。 POST /collection:返回新创建的资源对象数据。 PUT /collection/resource:返回完整的资源对象数据。 DELETE /collection/resource:返回空。

    5. 响应数据格式

    服务器返回的响应数据格式,应该尽量使用JSON。

    6. 响应状态码

    服务器向客户端返回的状态码和提示信息,常见的状态码如下:

    200 OK - [GET/PUT]:服务器成功返回用户请求的数据 201 CREATED - [POST]:用户新建数据成功。 204 NO CONTENT - [DELETE]:用户删除数据成功。 400 INVALID REQUEST - [POST/PUT]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

    状态码的完全列表参见这里或这里。

    2. Restful风格设计-其他

    1. 域名

    应该尽量将API部署在专用域名之下。

    https://api.example.com

    如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。

    https://www.example.com/api/

    2. 版本

    应该将API的版本号放入URL。

    http://www.example.com/api/1.0/foo http://www.example.com/api/1.1/foo http://www.example.com/api/2.0/foo

    另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

    3. 错误处理

    如果状态码是4xx,服务器就应该向用户返回出错信息。

    { error: "<error message>" }

    4. 超媒体

    RESTful API最好做到Hypermedia(即返回结果中提供链接,指向其他API方法),使得用户不查文档,也知道下一步应该做什么。

    比如,Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

    { "current_user_url": "https://api.github.com/user", "authorizations_url": "https://api.github.com/authorizations", // ... }

    从上面可以看到,如果想获取当前用户的信息,应该去访问api.github.com/user,然后就得到了下面结果。

    { "message": "Requires authentication", "documentation_url": "https://developer.github.com/v3" }

    上面代码表示,服务器给出了提示信息,以及文档的网址。

     

    3、REST接口开发的核心任务

    分析一下上节的案例,可以发现,在开发REST API接口时,视图中做的最主要有三件事:

    将请求的数据(如JSON格式)转换为模型类对象操作数据库将模型类对象转换为响应的数据(如JSON格式)

    1. 序列化Serialization

    在以上操作中,涉及到两个概念:序列化和反序列化。

    1)序列化

    将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象转换为JSON字符串,这个转换过程我们称为序列化。

    如:

    queryset = BookInfo.objects.all() book_list = [] # 序列化 for book in queryset: book_list.append({ 'id': book.id, 'btitle': book.btitle, 'bpub_date': book.bpub_date, 'bread': book.bread, 'bcomment': book.bcomment, 'image': book.image.url if book.image else '' }) return JsonResponse(book_list, safe=False)

    2)反序列化

    将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。

    如:

    json_bytes = request.body json_str = json_bytes.decode() # 反序列化 book_dict = json.loads(json_str) book = BookInfo.objects.create( btitle=book_dict.get('btitle'), bpub_date=book_dict.get('bpub_date') )

    通过上节课的例子可以看到,在开发REST API时,视图中要频繁的进行序列化与反序列化的操作。

    注:维基百科中对于序列化的定义。

    2. 总结

    在开发REST API接口时,我们在视图中在做的最核心的事是:

    将数据库数据序列化为前端所需要的格式,并返回;将前端发送的数据反序列化为模型类对象,并保存到数据库中。

    最新回复(0)