web编程(7) RESTful

1 引言

RESTful是一种流行的HTTP API接口设计风格,不仅仅局限于API范畴,它本质是一种面向资源的抽象理念。

REST概念首次提及,是 Roy Fielding 在2000年发表的博士论文《Architectural Styles and the Design of Network-based Software Architectures》(架构风格与基于网络的软件架构设计)。

Roy Fielding也是HTTP 1.1(1999年发布) 协议的负责人,REST也常常被认为是指导、设计 HTTP 协议的理论和思想,它把client端展示的内容,理解为server端"资源"的视图,每个资源都有唯一标识URL,通过不同的 HTTP方法 GET、POST、PUT、DELETE对资源进行操作处理。

在行业内,尤其是开放接口场景,RESTful API几乎成了HTTP API的代名词,但细扣起来,很多都不太严谨,有的还相去甚远,为何,大概是REST根红苗正的原因吧,跟它拉近关系,以显示自己政治正确。

目前主流HTTP API设计风格大致分两种:面向资源设计、面向过程设计。

2 准备

在讨论API风格之前,先了解一下基础知识HTTP。

HTTP协议,可以简单理解为,主要包含4部分内容:

(1) URL, 即服务端“资源”的路径、ID。 

(2) HTTP 方法,例如:GET、POST、PUT、DELETE、PATCH等。

(3) 请求Content, 即请求body部分内容。

(4) 响应Content, 即响应body部分内容。

HTTP协议,包含的其他部分内容:

(1) 响应结果的状态码,例如:2xx、3xx、4xx、5xx等。

(2) header部分,例如:Host、Accept、Cookie、Content相关等等。

主要起辅助说明作用,用来描述本次的处理是成功、还是失败,请求来自哪里Host,Content的大小、格式、编码等等。

3 风格

既然是风格,就没有好、坏之分,通常最令人担忧的是,没有风格、没有章法、乱来,就会增加没必要的理解成本,具体说,风格就是规则约束

3.1 面向资源

面向资源设计(RESTful),它希望把设计的重点放在抽象系统该有哪些资源, 而不是抽象系统该有哪些行为,说白了,就是把系统架构的重点放在"数据"上,有了清晰的"数据模型",其它都好说,可以从REST的底层思想看出,风格只是它的一种形式。

RESTful 充分利用了 HTTP 协议的各种特性,具体规则、约束如下:
(1) URL 应全部使用名词, 建议采用复数形式, 应该包含资源的ID。
(2) 动词由 HTTP Method 表示,增删改查分别对应:POST、DELETE、PUT、PATCH、GET。
(3) 请求的状态码,统一采用 HTTP 协议的状态码。
(4) 使用 XML 或 JSON 格式。
(5) 对于一些信息筛选,建议采用Url的查询参数处理,如: 分页等。

样例:

// 创建用户
Request:
POST /users
{"name": "xxx", "age": 18}

Response:
HTTP 201 Created
{"id": 1, "name": "xxx", "age": 18}

// 查询用户
Request:
GET /users/1

Response:
HTTP 200 OK
{"id": 1, "name": "xxx", "age": 18}

// 修改用户
Request:
PUT /users/1
{"name": "xxx", "age": 19}

Response:
HTTP 200 OK
{"id": 1, "name": "xxx", "age": 19}

// 删除用户
Request:
DELETE /users/1

Response:
HTTP 204 No Content

3.2 面向过程

面向过程设计,从风格形式上,它更像一个普通类库方法的自然形式,只关注3部分内容:输入参数、输出参数、方法名。仅依赖HTTP协议的URL、请求body、响应body,一般HTTP 方法只采用GET、POST,有些系统为了安全,统一采用POST,可以看出跟RESTful恰恰相反,该设计风格尽量不依赖HTTP协议,具体规则、约束如下:

(1) URL的命名,需要清晰的描述接口的行为。
(2) 请求数据、响应数据,通常统一采用 JSON 格式。
(3) 根据业务,自定义返回码,返回值格式:{"code": 0, "message": "", "data": {}} 
(4) HTTP 方法只采用GET、POST。

样例:

// 创建用户
Request:
POST /user/create
{"name": "xxx", "age": 18}

Response:
HTTP 200 OK
{"code": 0, "message": "", "data": {"id": 1, "name": "xxx", "age": 18}}

// 查询用户
Request:
POST /user/get
{"id": 1}

Response:
HTTP 200 OK
{"code": 0, "message": "", "data": {"id": 1, "name": "xxx", "age": 18}}

// 修改用户
Request:
POST /user/modify
{"id": 1, "name": "xxx", "age": 19}

Response:
HTTP 200 OK
{"code": 0, "message": ""}

// 删除用户
Request:
POST /user/delete
{"id": 1}

Response:
HTTP 200 OK
{"code": 0, "message": ""}

4 范围

不管那种风格的HTTP API,大多都位于系统的接入层,跟外界各种客户端交互,通过HTTP协议特有的简单、直观、低耦合,很好的将内部、外部进行了隔离。

系统内部服务间的通信,通常采用效率更高的dubbo、gRpc等RPC架构。

5 个人理解

HTTP API采用那种风格,一直是热门讨论话题,RESTful风格抽象程度偏高,对HTTP协议有深度依赖, 而面向过程风格,给人感觉就像一个普通的类库方法,只是通过HTTP协议简单封装了一下,由类库方法转换为HTTP API会更自然、对行为的表达也更丰富,更便于理解。

相对接口的风格,接口本身的定义,显然更重要,它跟风格没有关系。做过项目的都知道,最头疼的是,随着项目迭代升级,接口会野蛮生长,对接口边界的划分、功能的约束、可扩展等考虑, 更考验接口设计的功力,也是接口设计的根本。

6 注意事项

6.1 幂等性

分布式环境下,为保证消息的高可靠性,往往客户端会采用重试或消息补偿的形式,重复发送同一个请求。这时,需要保证接口的运行结果跟预期相符。

常见的解决方案:数据库的乐观锁设计、数据库唯一约束、分布式锁等。

6.2 返回值

建议采用目前行业最常见的数据格式:{"code": 0, "message": "", "data": {xxx}},通常 code,message两项内容,每次都需要返回。再就是,code最好进行统一编码,使各个接口的状态码风格一致,以下建议仅供参考:
(1) 状态码需要区分通用的公共码、具体业务码,公共码跟具体业务无关,例如:成功、失败、参数格式错误、没有登录、没有权限、异常等,最好在码的格式上,也能一目了然有所区分,例如:前缀不同,位数不同等。 
(2) 具体业务码,最好根据业务模块分配固定的码位区间,使各个业务模块间避免冲突。

6.3 规范命名

对常出现的方法,最好取一样的名字,例如:
create:新增
modify:修改
delete:删除
get:获取单个
list:获取列表

7 资料

以下只是对概念的简单罗列,细节请参考相关资料。

(1) Roy Fielding论文
REST架构风格的几点约束:
Client-Server 客服端-服务器模式
Stateless 无状态
Cacheable 可缓存
Layered System 分层系统
Code on Demand 按需扩展
Uniform interface 统一接口

(2) REST成熟度模型

第0级
只使用一个 URI 作为服务端口,使用 HTTP 协议传输数据。

第1级
使用多个 URI,不同的 URI 代表不同的调用入口,但只使用同一个 HTTP 方法传输数据。

第2级
使用多个 URI,不同的 URI 代表不同的资源,同时使用多个 HTTP 方法操作这些资源,例如使用POST/GET/PUT/DELETE 分别进行 CRUD 操作,这时候 HTTP 头和有效载荷都包含业务逻辑,例如 HTTP 动词对应相应操作,HTTP 状态码对应操作结果的状态。

第3级
最后这个级别引入了HATEOAS,它告诉我们下一步能做什么,以及对应的资源URI。

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值