如何创建RESTFul Web服务
想写这篇文章很久了,这是个大话题,不是一时半会就能说清楚的。 所以准备花个一星期整理资料,把思路理清楚,然后再在Team里做个sharing:)
其实RESTFul是架构风格,并不是实现规范,也不一定非要用HTTP,但鉴于HTTP的普世性和 SOA的实现基本都基于HTTP实现。 这句话只对了前一半, 实际上REST和HTTP是息息相关的,是一种Web架构,WWW是世界最大型的分布式应用,而其实现就是基于REST的web架构的设计标准,REST架构的提出者(Roy T. Fielding 2000年在他的博士论文中提出REST的架构风格),Roy
本身也是web标准(URI, HTTP, HTML) 的制定者,以及Web Server (Apache)的实现者,并且一直用REST的思想指导着标准制定,可以说HTTP就是该架构风格的一个典型应用,所以提到REST,就默认是用HTTP作为通信协议了。
一、HTTP 协议
2. Status Code
4. 中文扫盲
二、什么是REST
REST关键原则
- 为所有“事物”定义ID
- 将所有事物链接在一起
- 使用标准方法
- 资源多重表述
- 无状态通信
三、REST开发指导
去获得额外信息,我们也可以在每一个Product Item上附上获取详细的URL,这样做的好处是获得详细信息的动作对客户端是透明的,即使其URL有什么改动,客户端代码也可以不用修改,其次,服务器端可以根据业务扩展,向客户端推广新的URL,其坏处是,客户端为了理解URL的语义,需要增加额外的代码进行处理,从而复杂度也有所增加。
3,也就是最高等级。
和 标准的返回状态码
头部中标明可缓存内容和缓存有效时间,这样客户端在对同样资源的再次请求时,就可以利用本地缓存,而不用去服务器端取数据,在提高了性能同时,也节省了网络带宽和服务器的负载,当然其前提条件是我们设计的REST API要符合HTTP语义,即GET方法不能改变资源的状态,且必须是幂等的。如果在你的REST服务中,GET请求时能改变资源状态的,使用客户端缓存很可能就会导致数据不一致的情况,也就不符合缓存使用对于语义透明性的要求。除了客户端缓存,从HTTP代理到服务器之间,很多地方都可以利用缓存,在服务器端也可以利用缓存,能否合理的使用缓存在某种意思上决定了我们能否提供高质量、高性能和高伸缩性分布式应用。
什么是好的RESTful API?
1. 这个API应该是对浏览器友好的,能够很好地融入web,而不是与web格格不入,好的RESTful API应该能够使用浏览器+HTML完成所有的测试。
2. API中所包含的资源和对资源的操作,应该是直观和容易理解的,并且符合HTTP协议的要求。
3.API应该是松耦合的。(有待进一步理解)
REST的耦合度比SOAP更低,因为SOAP实现仍是基于RPC调用方式,RPC方式是紧密耦合的表现;而紧密耦合的系统是无法适应Web级的规模可伸缩性的。REST
Web服务则继承了Web松散耦合的特点,客户应用通过逻辑URL访问服务,服务的实现对客户来说是完全透明的,客户程序可以对服务的实现技术、方法毫无所知。
4.API中所有的格式应该是常见的通用格式,常见的有HTML、XML、JSON,常见的格式处理起来非常容易,有大量的框架和库提供支持。
5. 使用HTTP状态码来表达各种出错情况。如果一个所谓的”RESTful API“对任何请求都返回200 OK的响应,在响应的消息体中返回出错情况信息,这种做法显然不符合”确保操作语义的可见性“这个REST架构风格的基本要求。
6. 这个API应该对HTTP缓存是友好的
HTTP协议是个分层的架构,从两端的User agent(浏览器)到Origin server(Apache 服务器)之间,可以插入很多中间组件。在整个HTTP通信链条的很多位置,都可以设置缓存 。最常见的是浏览器缓存和服务器缓存:
浏览器端,下载一个类似HTTP watch的浏览器插件,就能很容易观察到对一个网站的进行第二次访问时,很多信息如图片,JS,JSS都是从浏览器缓存中取得,而不是去服务器取,节省了很多网络开销,也减轻了服务器压力。
在服务器端,也有很多缓存技术,可以参见这篇文章Caching your REST API来了解一种典型的服务器缓存技术,大概意思就是在对资源执行安全的操作如GET时,将response放入缓存,当对资源进行不安全操作如PUT/DELETE,将该response从缓存中移除(PURGE)出去,这样保证客户端不会得到过期的response。
在使用缓存时,不管是在客户端还是服务器端,一个非常重要的原则就是就语义透明性(Semantic Transparency)。
什么是缓存的语义透明性?就是不管在客户端还是服务器端使用缓存,对一个请求来说,其使用缓存得到的响应(Response)和直接访问服务器(Origin Server)所得到响应结果,应该是一模一样的,没有任何差别,缓存对服务的访问者来说应该是透明的。
完全达到语义透明性只是一个理想状态,Web是松耦合的,所以弱一致性(Weak consistency) 是基于Web的分布式应用的特点,但是我们可以通过一些手段来增强一致性,尽量达到语义透明性。常用的方式有失效、验证、过期。
如何对RESTful API进行版本控制?
一个比较简单实用的做法是直接在URI中插入版本号,这样做允许多个版本的API并行运行。另一个做法是在HTTP请求中加入自定义头信息,标明使用的版本号。不过这个做法其实对浏览器不够友好,简单地使用浏览器+HTML无法测试。
还有对于微小改动,最好可以做到向后兼容而不改变版本号,最关键的就是在扩展时不能破坏现有的客户端,例如,变更一个参数,可以选择同时兼容新旧两种输入,或者保持老参数不动,提供一个新参数,在文档中必须做出说明,不推荐新用户继续使用之前的参数。
HTTP1.1规范中给出的动词对于设计RESTful API 够用吗?
如果资源抽象做的很好,对于某个资源的任何操作,通常都能够映射到CRUD四个类别中。CRUD四个类别对于操作资源来说,绝大多数情况下是完备的。HTTP的四个方法对CRUD的映射关系是Create-POST, Retrieve-GET, Update-PUT, Delete-DELETE。如果在资源上定义的操作过多,往往这个资源可以拆分出更多的资源。
关于API的幂等性
幂等性是系统接口对外部调用的承诺,承诺只要调用接口成功,外部多次调用对系统影响是一致的。幂等性的好处是,外部在调用系统失败后,在进行重试时,无需更改请求内容。
在大规模分布式系统中,完成一个功能,需要很多服务或者组件的协作,通常我们会用一个uniqueRequestId or dedupeId 来标识一次请求的唯一性,而在调用服务出错时,如网络超时,系统内部错误,一般都要进行重试,幂等的接口允许重试时,使用相同的dedupeId。而非幂等的接口可能需要更改dedupeId来和上一次请求做区分,增加了客户端使用服务的负担。
所以在我看来,不仅GET/DELETE需要时幂等的,所有的REST API都应该尽量做到幂等,包括POST/PUT。比如在eLedger系统里,创建journal entry(流水账)是最常用的API,如果客户POST两次一模一样的请求(最主要是dedupeId一样),eLedger每次都会返回成功的结果,只不过在第二个POST到来时,系统检测到流水已经被创建,并不会创建新的流水,只是将已创建的结果返回给客户端,从某种意义上,减轻了客户使用eLedger服务的难度,因为其不用担心因为重复POST所造成的数据不一致。
关于REST的安全性
REST对安全性并没有像基于WSDL,SOAP的Web Service的WS-Security的安全规范,主要取决于REST service自己的实现,因为REST是架设在HTTP之上的,所以在底层通信(TCP)使用SSL是自然而然的,SSL基本可以解决中间人(man in middle) 和 重放攻击(replay attack)等安全问题,那么对于应用层,所要解决的就是认证(authentication),授权(authorization),访问(access)的问题了,鉴于可扩展性和开放性的考虑,使用OAuth是一个比较好的选择,首先OAuth是W3C的标准规范,提供了统一的标准和规范,降低了客户端的学习成本,其次是它把真个验证流程划分为认证、授权、访问三个步骤,不仅能满足传统的Client-Server验证,还具备非常良好的可扩展性,使得地方
如何定义Resource
REST开发又被称作“面向资源的开发”,这说明对于资源的抽象,是设计RESTful API的核心内容。RESTful API建模的过程与面向对象建模类似,是以名词为核心的。这些名词就是资源,任何可命名的抽象概念都可以定义为一个资源。而HTTP协议并不是一种传输协议,它实际提供了一个操作资源的统一接口。利用有限的几个方法(GET/POST/PUT/DELETE)来达到资源在不同表述状态(REpresentationalState)之间的转移(Transfer),这也是REST名称的由来。
所以RESTful API建模的过程,可以看作是具有统一接口约束的面向对象建模过程。
如果发现资源上的操作过多,以至于HTTP的方法不够用,应该考虑设计出更多的资源。设计出更多资源(以及相应的URI)对于RESTful API来说并没有什么害处。
五、REST 的成熟度模型(Maturity Model)

http://martinfowler.com/articles/richardsonMaturityModel.html
版权声明:本文为博主原创文章,未经博主允许不得转载。
如何创建RESTFul Web服务的更多相关文章
- 用 Java 技术创建 RESTful Web (服务 JAX-RS:一种更为简单、可移植性更好的替代方式)
作者: Dustin Amrhein, 软件工程师, IBM Nick Gallardo, 软件工程师, IBM 出处: http://www.ibm.com/developerworks/cn/we ...
- 用 Java 技术创建 RESTful Web 服务
JAX-RS:一种更为简单.可移植性更好的替代方式 JAX-RS (JSR-311) 是一种 Java™ API,可使 Java Restful 服务的开发变得迅速而轻松.这个 API 提供了一种基于 ...
- 用 Java 技术创建 RESTful Web 服务--转载
简介 JAX-RS (JSR-311) 是为 Java EE 环境下的 RESTful 服务能力提供的一种规范.它能提供对传统的基于 SOAP 的 Web 服务的一种可行替代. 在本文中,了解 JAX ...
- <转>用 Java 技术创建 RESTful Web 服务
转自:https://www.ibm.com/developerworks/cn/web/wa-jaxrs/#N1017E JAX-RS:一种更为简单.可移植性更好的替代方式 Dustin Amrhe ...
- 使用 Spring 3 来创建 RESTful Web Services
来源于:https://www.ibm.com/developerworks/cn/web/wa-spring3webserv/ 在 Java™ 中,您可以使用以下几种方法来创建 RESTful We ...
- Guzzle – 构建 RESTful Web 服务的 PHP HTTP 框架
Guzzle 减轻了发送 HTTP 请求和创建 Web 服务客户端的痛苦.它包含建立一个强大的网络服务客户端的工具,包括:服务描述定义的输入和输出的 API,资源迭代器遍历分页资源,尽可能有效地发送大 ...
- 使用Java创建RESTful Web Service
REST是REpresentational State Transfer的缩写(一般中文翻译为表述性状态转移).2000年Roy Fielding博士在他的博士论文“Architectural Sty ...
- 使用 Spring 3 来创建 RESTful Web Services(转)
使用 Spring 3 来创建 RESTful Web Services 在 Java™ 中,您可以使用以下几种方法来创建 RESTful Web Service:使用 JSR 311(311)及其参 ...
- MEAN Stack:创建RESTful web service
本文在个人博客上的地址为URL,欢迎品尝. 前段时间做了DTREE项目中的前后端数据存储功能,在原有的ngController上进行HTTP请求,后端接受到请求后再存储到mongoDB上.现将学习所得 ...
随机推荐
- 最长k可重区间集(cogs 743)
«问题描述:«编程任务:对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度.«数据输入:由文件interv.in提供输入数据.文件的第1 行有2 个正整数n和k,分别表示开区间 ...
- 《挑战程序设计竞赛》P196 铺砖问题
题意:给定n*m格子,每个格子被染成了黑色或者白色,现在要用1*2的砖块覆盖这些格子,块与块不得重叠,且覆盖所有的白色格子,但不覆盖任意一个黑色格子,求一共有多少种覆盖方法. 思路:书上给的思路太巧妙 ...
- 【HDOJ5996】dingyeye loves stone(Nim游戏)
题意:dingyeye喜欢和你玩石子游戏.dingyeye有一棵n个节点的有根树,节点编号为0到n−1,根为0号节点. 游戏开始时,第i个节点上有a[i]个石子.两位玩家轮流操作,每次操作玩家可以选择 ...
- 使用中科大源下载android源码
我的系统时manjaro linux 最新版的,安装过了git和curl软件 一.如果没有安装的同学,请使用命令: pacman -S git curl 我这里安装了python3和python2,但 ...
- python c++ Visual Studio相关 Unable to find vcvarsall.bat问题
使用Cython编译包的时候报错: Unable to find vcvarsall.bat 说明:https://jingyan.baidu.com/article/adc815138162e8f7 ...
- 定时执行rsync同步数据以及mysql备份
需求:把机器A中的附件.图片等,备份到备份机B中.将数据库进行备份 附件备份 在A中,启动rsync服务,编辑/etc/xinetd.d/rsync文件,将其中的disable=yes改为disabl ...
- vscode Go 1.11.4 编译错误 need Delve built by Go 1.11 or later
更新golang的版本为1.11.4之后vscode编译错误:executables built by Go 1.11 or later need Delve built by Go 1.11 or ...
- AC日记——第K大的数 51nod 1105
1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...
- TCP/IP握手协议
转自:http://www.js123.net/t/n/n/2013/4/28/n_272.shtml 这篇介绍的也很棒:http://www.cnblogs.com/rootq/articles/1 ...
- (转)C++常用函数汇总
1.标准C++库字符串类std::string的用法 begin 得到指向字符串开头的Iterator end 得到指向字符串结尾的Iterator rbegin ...