目录:
一、对RESTful的理解
二、RESTful的使用方法
三、URL、URI的区别
四、REST与RESTful的关系与区别
五、RESTful与SOAP的粗略比较(webservice)
一、对RESTful的理解:
REST =》 Representational State Transfer,阮一峰大大的翻译是“表现层状态转化”,且认为少了一个主语:Resources(资源)。如果一个架构符合REST原则,就成为RESTful架构。下面从每个词的含义来理解整个规则。
Resources 所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。而所谓"上网",就是与互联网上一系列的"资源"互动,调用它的URI。
Representational: “资源”是一种信息实体URI,外在表现形式很多,而这个呈现出来的形式,就叫做它的“表现层”。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。
State Tranfer:在客户端与服务端互动的过程中,一定涉及到数据和状态的变化。而互联网通信协议http协议,是一个无状态协议。这意味着,所有状态保存在服务器端,如果客户端想要操作服务器,必须通过一定的方式,让服务器存储的状态发生转化。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。而客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
所以,RESTful架构就是:(1)每个URI代表一种资源(2)客户端与服务端之间,传递这种资源的某种表现层(3)客户端通过四个http动词,对服务器端资源进行操作,实现“表现层状态转化”。
RESTful架构有一些典型的设计误区:
(1)URI包含动词:“资源”实体是名词,URI不应该有动词,动词应放在http协议中;
POST /accounts/1/transfer/500/to/2
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
(2)在URI中加版本号: 因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分。
http://www.example.com/app/1.0/foo
Accept: vnd.example-com.foo+json; version=1.0
二、RESTful的使用方法:
1、URL设计:“动词” + “宾语”
其中,动词指的是HTTP的五种方法,对应CRUD操作(HTTP规范,动词一律应该大写):
GET:读取(Read)
POST:新建(Create)
PUT:更新(Update)
PATCH:更新(Update),通常是部分更新
DELETE:删除(Delete)
POST和PUT在创建资源的区别在于,所创建的资源的名称(URI)是否由客户端决定。 例如为我的博文增加一个java的分类,生成的路径就是分类名/categories/java,那么就可以采用PUT方法。
统一接口并不阻止你扩展方法,只要方法对资源的操作有着具体的、可识别的语义即可,并能够保持整个接口的统一性。
需要注意的是,像PATCH这种不是HTTP标准方法的,服务端需要考虑客户端是否能够支持的问题。
即使你按各个动词的原本意图来使用它们,你仍可以轻易禁止缓存机制。 最简单的做法就是在你的HTTP响应里增加这样一个报头: Cache-control: no-cache。 但是,同时你也对失去了高效的缓存与再验证的支持(使用Etag等机制)。
对于客户端来说,在为一个REST式服务实现程序客户端时,也应该充分利用现有的缓存机制,以免每次都重新获取表示。
而客户端只能使用GET及POST方法,服务器接收其他三种方法的时候,必须接受POST来模拟。模拟需借助“X-HTTP-Method-Override”属性,该属性的值即为要覆盖POST的方法:
POST /api/Person/4 HTTP/1.1
X-HTTP-Method-Override: PUT
其中,宾语必须是名词。而名词的形式一般建议采取复数,因为常见的操作是读取一个集合。
除此之外,常见的情况,资源多级分类,但建议将多级URL转为“一级+参数”的形式。(“/”用来表示层级;“?”过滤资源;“_”或“-”URI可读性更好;“,”或“;”可以用来表示同级资源的关系)
GET /authors/12/categories/2 =》 GET /authors/12?categories=2
GET /articles/published =》 GET /articles?published=true
由于有时候不可能将所有信息返回提取显示,所以提供了过滤信息这一方法。
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page_number=2&page_size=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,
GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的。
2、状态码:客户端的每一次请求,服务器都必须给出回应。包括HTTP状态码 + 数据。分为五个类别:1XX:相关信息;2XX:操作成功;3XX:重定向;4XX:客户端错误;5XX:服务器错误。约么100多种,为的就是精确,涵盖尽可能多的情况。API一般不需要1XX,重点介绍其他四种。
// 2XX:
GET: 200 OK
POST: 201 Created 生成了新资源
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content 资源已经不存在
202 Accepted状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作。
// 3XX:
API 用不到301状态码(永久重定向)和302状态码(暂时重定向,307也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况。
API 用到的3xx状态码,主要是303 See Other,表示参考另一个 URL。它与302和307的含义一样,也是"暂时重定向",区别在于302和307用于GET请求,而303用于POST、PUT和DELETE请求。收到303以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办。
// 4xx:
400 Bad Request:服务器不理解客户端的请求,未做任何处理。
401 Unauthorized:用户未提供身份验证凭据,或者没有通过身份验证。
403 Forbidden:用户通过了身份验证,但是不具有访问资源所需的权限。
404 Not Found:所请求的资源不存在,或不可用。
405 Method Not Allowed:用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之内。
410 Gone:所请求的资源已从这个地址转移,不再可用。
415 Unsupported Media Type:客户端要求的返回格式不支持。比如,API 只能返回 JSON 格式,但是客户端要求返回 XML 格式。
422 Unprocessable Entity :客户端上传的附件无法处理,导致请求失败。
429 Too Many Requests:客户端的请求次数超过限额。
// 5XX:
5xx状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
500 Internal Server Error:客户端请求有效,服务器处理时发生了意外。
503 Service Unavailable:服务器无法处理请求,一般用于网站维护状态。
3、服务器回应:
现下开发模式基本上采取前后端分离,返回一个json对象便于操作数据,因此,服务器回应的HTTP头的Content-Type属性要设为“application/json”;客户端也要明确设置ACCEPT属性值为“application/json”。
发生错误时,一定不要返回200。有的开发者会在200之后添加错误码code及msg信息,用来区分。但是此种控制下不建议采取该方式。
API 的使用者未必知道,URL 是怎么设计的。一个解决方法就是,在回应中,给出相关链接,便于下一步操作。这样的话,用户只要记住一个 URL,就可以发现其他的 URL。这种方法叫做 HATEOAS。HATEOAS 的格式没有统一规定,上面例子中,GitHub 将它们与其他属性放在一起。更好的做法应该是,将相关链接与其他属性分开。
{
...
"feeds_url": "https://api.github.com/feeds",
"followers_url": "https://api.github.com/user/followers",
"following_url": "https://api.github.com/user/following{/target}",
"gists_url": "https://api.github.com/gists{/gist_id}",
"hub_url": "https://api.github.com/hub",
...
}
vs
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "In progress",
"links": {[
{ "rel":"cancel", "method": "delete", "href":"/api/status/12345" } ,
{ "rel":"edit", "method": "put", "href":"/api/status/12345" }
]}
}
三、URL、URI的区别:
URL:(Uniform/Universal Resource Locator 的缩写,统一资源定位符)。
URI:(Uniform Resource Identifier 的缩写,统一资源标识符)(代表一种标准)。
URI – 统一资源标识符
URI是使用一小串数字、字母和符号来识别文档的标准。它是在RFC 3986定义的:URI指的是通用句法。所有的URL、URN及URC都是URI。
URL – 统一资源定位符
URL中包含了如何通过其位置来获取资源的信息。例如:
http://example.com/mypage.html
ftp://example.com/download.zip
mailto:user@example.com
file:///home/user/file.txt
tel:1-888-555-5555
http://example.com/resource?foo=bar#fragment
/other/link.html (一个相对URL,只有在另外一个完整的URL上下文中才有用)
URL总是以一个协议头开始,通常包括诸如主机名(example.com)和一个文件路径(/foo/mypage.html)。URL可能也会有查询参数及片段识别符。
URN – 统一资源名称
URN通过一个唯一及持续的名字来标识资源,但却不必告诉你如何在网络上定位到它。它通常是以一个urn前缀的开头的。例如:
urn:isbn:0451450523 to identify a book by its ISBN number.
urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 a globally unique identifier
urn:publishing:book - An XML namespace that identifies the document as a type of book.
URN可以识别想法和概念。他们并不限于识别文件。当一个URN代表一个文件时,它可以被一个解析器转换成一条URL。然后这个文件就这个用转换后的URL下载了。
URC – 统一资源引用符
URC指的是一个文件的元数据,而不是文件本身。URC的一个例子是一个指定HTML网页的源代码,如:view-source:http://example.com/
Data URI
我们可以直接将数据放到一个URI中,而不是在互联网上定位或命名它。一个数据URI:data:,Hello%20World。
四、REST与RESTful的关系与区别
RESTful是由REST派生出来的。
REST:Representational State Transfer 表述性状态转移,是一种架构风格。
REST原则:
(1)、网络上的所有事物都被抽象为资源
(2)、每个资源都有一个唯一的资源标识符
(3)、 同一个资源具有多种表现形式(xml,json等)
(4)、 对资源的各种操作不会改变资源标识符
(5)、所有的操作都是无状态的
RESTful: 遵守了REST原则 的web服务
理解:RESTful与REST相比,多了一个ful,就英语层面来说是一个形容词,RESTful翻译为中文为: “REST式的”
是REST式的什么呢?答案是REST式的应用,REST风格的web服务也是REST式的应用,REST式的web服务是一种ROA(The Resource-Oriented Architecture)(面向资源的架构)
五、RESTful与SOAP的粗略比较(webservice)
首先需要了解:REST是一种架构风格,其核心是面向资源;而webService底层SOAP协议,主要核心是面向活动;
WebService 是一种跨编程语言和跨操作系统平台的远程调用技术。其通过HTTP协议发送请求和接收结果时采用XML格式封装,并增加了一些特定的HTTP消息头,这些特定的HTTP消息头和XML内容格式就是SOAP协议。
对比
效率与易用性:SOAP由于各种需求不断扩充其本身协议的内容,导致在SOAP处理方面的性能有所下降。同时在易用性方面以及学习成本上也有所增加。而RESTful API 在请求方法、资源、地址都进行了规范,其最大限度的利用了HTTP最初的应用协议的设计理念。
安全性:RESTful 对于资源型服务器接口比较适合,适合对于效率要求很高,但是对于安全要求不高的场景。SOAP 的成熟性可以给需要提供给多开发语言的,对于安全性的要求较高的接口设计带来便利,你可以在客户端和服务端应用证书进行安全措施。所以关键看应用场景。