周梦康 发表于 2016-01-03 分类于 笔记 61818 次浏览 标签 : REST
 

一些常见的误解

不要以为 RESTful Api  就是设计得像便于 SEO 的伪静态,例如一个 Api 的 URL 类似于 http://xxx.com/blog/1 ,我们可以通过浏览器访问该 URL 而读取文章,但是这并不代表着它就是 RESTful Api 。

也不要认为URL 里有 queryString 就不是 RESTful Api ,例如 http://xxx.com/users/?page=10&page_size=30

更不要认为 HTTP + JSON 就是 RESTful ApI 了。

REST 和 HTTP/1.1

Roy Fielding (Apache HTTP 服务器的核心开发者,Apache 软件基金会的合作创始人,HTTP/1.1 协议专家组的负责人)总结了一套理论框架,然后使用这套理论框架中的指导原则,来指导HTTP/1.1协议的设计方向。后来他在其的博士学位论文 Architectural Styles and the Design of Network-based Software Architectures 中更为系统、严谨地阐述了这套理论框架,并且使用这套理论框架推导出了一种新的架构风格,并且为这种架构风格取了一个令人轻松愉快的名字 REST。

想必通过这个你已经明白了 REST 和 HTTP/1.1 的密不可分的关系了吧。HTTP/1.1 的很多特性就是 REST 的特性,比如连接的无状态性。还有后面说的 REST 五大特性都和 HTTP/1.1 协议密不可分。

RESTful Api 与 SOAP Web API 在 URL 形式上的对比

从设计一个删除评论的 api 说起

我们可以这样设计成类似于:

http://mengkang.net/?method=comment.del&id=x 

http://mengkang.net/comment/del/id/x 

或者其他形式的 url。

而 RESTful Api 则是:

[DELETE] http://mengkang.net/comments/1 

我们对比可以发现①和② URL 中,都有del的动作指示。

SOAP Web API采用RPC风格,它采用面向功能的架构,所以我们在设计SOAP Web API的时候首相考虑的是应高提供怎样的功能(或者操作)。

而 RESTful Api 是面向资源的架构。是查询、新增、修改、删除,都该资源无关。

所以我们在③ URL 中没有看到del的关键字,对比②和③最为明显。

进一步认识 RESTful Api

我们知道 URL 全称为“统一资源定位符(Uniform Resource Locator)”,用于描述 Web 资源所在的位置。RESTful Api 是以 HTTP 协议为强烈依托的,将类似于①和②这种以功能为主导的URL风格舍弃,还原 URL 的本质,它的宗旨就是一个 URL 就应该是一个资源,不能包含任何动作。

  1. [POST]     http://mengkang.net/users   // 新增
  2. [GET]      http://mengkang.net/users/1 // 查询
  3. [PATCH]    http://mengkang.net/users/1 // 更新
  4. [PUT]      http://mengkang.net/users/1 // 覆盖,全部更新
  5. [DELETE]   http://mengkang.net/users/1 // 删除

PUTPATCH的功能都可以代表更新,但略有不同,PUT大多时候表示更新该资源的全部信息,而PATCH则更新部分信息。

PUTPOST又一些功能的重叠,都可以是新建一个资源,POST时,新建资源的地址是由服务器返回给客户端的。也就是说客户端在发送POST请求资源之前还无法预知该资源的地址,这在我们的 Api 开发中非常常见,新建一个帖子,新建一条评论,都如此。

而资源的地址是客户端预先知道的情况则比较少。也有人如此设计而使用PUT,比如需要对 github 上的某人的项目 star ,则可能会设计成:http://github.com/xxx/zhoumengkang/projectname/star 这里把“对这个项目已经点赞过”看成了一个资源,那么就可以用PUT,因为要删除这个资源时,还是访问这个 URL。

关于这些功能上有交集的地方,可能后面会有一些更加标准的规范或者协议吧。

最后说下HEADOPTIONSHEAD请求的是资源的元数据,比如一张照片,的元数据则可能包含了,照片拍摄的设备,地点,时间等。服务器一般将对应资源的元数据置于响应的报头集合返回给客户端,这样的响应一般不具有主体部分。OPTIONS则是发送一种“探测”请求以确定针对某个目标地址的请求必须具有怎样的约束(比如应该采用怎样的HTTP方法以及自定义的请求报头),然后根据其约束发送真正的请求。

关于过滤筛选,排序和 token 等 query string 是支持使用,和唯一资源的概念并不冲突。

我所理解的无状态性和唯一资源对 Api Url 的设计指导

举一个实际的例子,用户黑名单的 CURD。我们可是设计成

  1. [GET]      /blacklist
  2. [PUT]       /blacklist/{id#把 id 加入到当前授权用户的黑名单中
  3. [DELETE]   /blacklist/{id}

如上的 api 设计中,首先如上的 url 设计中,通过授权码中获取登录用户 uid。则是有状态的了,其次因为所有的用户访问的资源都是同一个地址,这与唯一资源的概念是相违背的。如果是无状态的,那么就与唯一资源的概念相吻合了。(这只是 restful 所建议的,实际是否需要完全遵守视情况而定)

  1. [GET]      /user/{uid}/blacklist
  2. [PUT]       /user/{uid}/blacklist/{id}  #把 id 加入到当前授权用户的黑名单中
  3. [DELETE]   /user/{uid}/blacklist/{id}

REST的五大特性

  1. 资源(Resource)

  2. 资源的表述(Representation)

  3. 状态转移(State Transfer)

  4. 统一接口(Uniform Interface)

  5. 超文本驱动(Hypertext Driven)

资源的概念是 RESTful 里面最重要的一个概念,很容易被我们忽视和误解,所以就重点阐述了这一特性。

而其他特性,我们日常开发应该都是遵守的,就不再展开说了,需要了解的可以看我的这篇笔记 REST的五个特性 。

Server 端代码的基本设计思想

按照 RESTful Api 的规范,严格来说根据endpoint找到在 server 端映射成一个资源对象,例如通过 http://mengkang.net/users/1 找到UserResource对象

而在这个对象里对应着该资源支持的 Http 协议的方法。如果一个对象支持7种方式的请求,则类似于:

  1. public class UserResource {
  2.     private User user;
  3.     public UserResource() {
  4.     }
  5.     public UserResource(int id) {
  6.         //从数据查询处该用户的数据
  7.         String name = "xxx";
  8.         short age = 23;
  9.         user = new User(id,name,age);
  10.     }
  11.     /**
  12.      * 获取单个用户
  13.      * 从 new UserResource(int) 开始
  14.      * @return
  15.      */
  16.     public User get(){
  17.         return user;
  18.     }
  19.     /**
  20.      * 覆盖用户的全部信息
  21.      * 从 new UserResource(int) 开始
  22.      * @return
  23.      */
  24.     public boolean put(){
  25.         return true;
  26.     }
  27.     /**
  28.      * 只更新用户的部分信息
  29.      * 从 new UserResource(int) 开始
  30.      * @return
  31.      */
  32.     public boolean patch(){
  33.         return true;
  34.     }
  35.     /**
  36.      * 创建一个 UserResource
  37.      * @return
  38.      */
  39.     public int post(){
  40.         return 1;
  41.     }
  42.     /**
  43.      * 删除用户
  44.      * @return
  45.      */
  46.     public boolean delete(){
  47.         return true;
  48.     }
  49. }

如果有关注的 api 那么对于该用户的 star 操作则应新建一个UserStarResource资源对象,因为每个资源最多只有这7中方法,构造方法除外,而不能有其他的相关的动作方法。

假如我们规定 URL 为 http://mengkang.net/user/1/star 表示是访问者对 id 为 1 的这个用户的 star 状态的一个资源。(当前访问者的信息通过 query string 传递 auth token 的形式获取)

  1. public class UserStarResource {
  2.     public boolean get(){
  3.         return true;
  4.     }
  5.     public boolean post(){
  6.         return true;
  7.     }
  8.     public boolean delete(){
  9.         return true;
  10.     }
  11. }

REST 状态码

理论上来说我们应该以 Http response status code 作为客户端的标准,而不是在 Http body 体里面定义。这样客户端的能够更快速的获取服务端的响应状态码。

但是由于国内某些网络商会劫持状态码非200的请求,跳转到他们的广告地址。所以大家还是考虑国内的实际情况。

REST 架构风格约束

  1. 客户-服务器(Client-Server)通信只能由客户端单方面发起,表现为请求-响应的形式。

  2. 无状态(Stateless)通信的会话状态(Session State)应该全部由客户端负责维护。

  3. 缓存(Cache)响应内容可以在通信链的某处被缓存,以改善网络效率。

  4. 统一接口(Uniform Interface)通信链的组件之间通过统一的接口相互通信,以提高交互的可见性。

  5. 分层系统(Layered System)通过限制组件的行为(即,每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。

文字比较学院派,仔细一想,想必也发现我们实际工作都已经遵守这五条架构风格了。

短短的一篇文章无法涵盖所有内容,这里推荐下 Github Api, 可以作为大家设计 RSETful Api 的最佳范例。

一个基于 netty 的轻量级的 RESTful Api Server https://github.com/zhoumengkang/netty-restful-server

更多更详细的信息可以阅读下面两篇文章

http://www.cnblogs.com/artech/p/restful-web-api-02.html

http://www.infoq.com/cn/articles/understanding-restful-style/

书籍推荐

RESTful Web Services Cookbook

深入理解 RESTful Api 架构-copy的更多相关文章

  1. 深入理解 RESTful Api 架构

    转自https://mengkang.net/620.html 一些常见的误解 不要以为 RESTful Api  就是设计得像便于 SEO 的伪静态,例如一个 Api 的 URL 类似于 http: ...

  2. RESTful API 架构解读

    RESTful API 架构解读 首先我们还是先介绍下 RESTful api 的来龙去脉. 首先, RESTful (下文都简称 RESTful api 为 RESTful ) 1.RESTful ...

  3. RESTful api架构设计

    阮老师的这两篇文章足够了 理解 RESTful 架构 RESTful API 设计指南

  4. 理解Restful api的意义

    RESTful API 只是API的设计规范或者是一套设计理论. 单就URL和Method这两个点,你可以这样理解: URL 是用来唯一标示一个互联网资源的,而 Method 是用来标识当前请求对该资 ...

  5. 我是如何根据豆瓣api来理解Restful API设计的

    1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...

  6. RESTful API架构和oauth2.0认证机制(概念版)

    1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的 ...

  7. Restful API 架构与设计参考原则

    1. 什么是RESTREST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的博 ...

  8. 理解 RESTful API 设计规范

    RESTful是目前最流行的API设计规范,它是用于Web数据接口的设计.从字面可以看出,他是Rest式的接口,所以我们先了解下什么是Rest. REST与技术无关,它代表的是一种软件架构风格,RES ...

  9. SpringBoot RESTful API 架构风格实践

    如果你要问 Spring Boot 做什么最厉害,我想答案就在本章标题 RESTful API 简称 REST API . 本项目源码下载 1 RESTful API 概述 1.1 什么是 RESTf ...

  10. 理解RESTful API

    近日妹子向我求助RESTful API到底是个什么东西.原因是她们公司一个新启动的项目因为RESTful API起了争执.服务端同学坚持要用RESTful API,而前端同学则认为服务端用RESTfu ...

随机推荐

  1. VMware安装Ubuntu操作系统 2024.9.27

    1.安装 Ubuntu的官方网站是:https://www.ubuntu.com/download 点进去可以直接下载 文件下载会比较慢,我这点用了约5分钟 然后就可以打开vmware,选择: 就可以 ...

  2. nsenter 常用操作

    nsenter 是一个可以用来进入到目标程序说在 namespace 中运行命令的工具,一般可以用于在容器外 debug 容器中运行的程序.简单记录一下 nsenter 的常用用法. 常用参数 最常用 ...

  3. 离线快速LCA(最近公共祖先) Tarjan算法

    离线快速LCA(最近公共祖先) Tarjan算法 前言 对于 OIer 来说,LCA 一直是处理树上问题的好帮手,无论是倍增还是树剖都有着优秀的 \(\log n\) 的复杂度.不过由于我们(数据规模 ...

  4. Blazor 组件库 BootstrapBlazor 中AutoComplete组件介绍

    AutoComplete组件介绍 AutoComplete组件和文本框基本上样子是一样的,只不过AutoComplete组件还带有一个下拉列表,可以从中选择对应的内容. 其同样继承自Bootstrap ...

  5. MySQL底层概述—10.InnoDB锁机制

    大纲 1.锁概述 2.锁分类 3.锁实战之全局锁 4.锁实战之表级锁(偏读) 5.锁实战之行级锁(偏写)-行级锁升级表级锁 6.锁实战之行级锁(偏写)-间隙锁 7.锁实战之行级锁(偏写)-临键锁 8. ...

  6. 为什么你用的 MyBatis 慢?一行配置让它性能翻倍!

    为什么你用的 MyBatis 慢?一行配置让它性能翻倍! 在 Java 后端开发的江湖里,MyBatis 堪称一员大将,凭借着灵活的 SQL 编写.方便的数据库对接能力,深受广大开发者的喜爱.但不少小 ...

  7. AFL分析与实战

    文章一开始发表在微信公众号 https://mp.weixin.qq.com/s?__biz=MzUyNzc4Mzk3MQ==&mid=2247486292&idx=1&sn= ...

  8. docker启动所有容器命令

    启动所有容器 docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) 关闭所有容器 docker stop $(docker ps ...

  9. Flutter之GetX之国际化

    Flutter之GetX之国际化 在GetMaterialApp中设置 GetMaterialApp( locale: Get.deviceLocale, translations: Messages ...

  10. ASP.NET Core: ConfigurationBuilder

    在 ASP.NET Core 中,大量使用了建造模式 Builer,从类型的名称就可以看出来这一点,例如 HostBuilder.ConfigurationBuilder 等等. 建造模式是对象的创建 ...