如何创建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上.现将学习所得 ...
随机推荐
- 【21】vuex 与element iu表单校验
转:http://www.cnblogs.com/gsgs/p/6753682.html element-ui的官网上写的自定义表单验证,方法都是写在单vue文件中的,不容易共享.怎么使用vuex将方 ...
- 问题:viewController不会调用dealloc()不会销毁
问题 在调试程序时,我从ViewController A push进 ViewController B,在从B back时发现程序不会执行B里面的dealloc(),很诡异的问题,因为按理说此时点击b ...
- 2018华南理工大学程序设计竞赛 H-对称与反对称
H-对称与反对称 题目描述 给出一个N*N的方阵A.构造方阵B,C: 使得A = B + C.其中 B为对称矩阵,C为反对称矩阵. 对于方阵S中的任意元素,若(S)ij = (S)ji,则称S为对称矩 ...
- 更改MVC3默认错误提示信息 模型验证 validation
原文发布时间为:2011-07-20 -- 来源于本人的百度文章 [由搬家工具导入] Model Metadata and Validation Localization using Conventi ...
- 获取所有querystring变量名
原文发布时间为:2009-12-04 -- 来源于本人的百度文章 [由搬家工具导入] protected void Page_Load(object sender, EventArgs e) { ...
- linux2.4内核调度
进程调度需要兼顾3种进程:交互进程,批处理进程,实时进程,在设计一个进程调度机制时需要考虑具体问题 (1)调度时机? 答:进程在用户空间可以pause()或者让内核设置进程为睡眠状态,以此调度,调度还 ...
- [SaltStack] Minion-conf自动更新
minion-conf配置文件自动更新, 加载 minion-conf是每个minion自身以来的配置, 为了方便我们在中心管控机上(Master)统一配置, 然后下发文件, 进而使得Minion能够 ...
- phpexcel--导入excel表格
最近在做一个小项目,就是一个管理信息的小系统:要求有导入和导出的信息为excel的功能,研究过导入导出功能的肯定知道导出要比导入的简单多了,导入用的phpexcel,当时对phpexcel是完全不了解 ...
- 泛型数组 + 记录类型 + Json 之间的转换
unit Unit3; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- 【转载】51CTO-Android设置模拟器屏幕大小
在Eclipse Android中设置模拟器屏幕大小是本文要介绍的内容,主要是来了解并学习Eclipse Android中模拟器的设置,具体关于Eclipse Android内容的详解来看本文. ...