认识 RESTful
REST 不是 “rest” 这个单词,而是几个单词缩写。REST ——REpresentational State Transfer,是一种网络应用程序的设计风格和开发方式,基于 HTTP,可以使用 XML 格式定义或 JSON 格式定义。
- REST 描述的是在网络中 client 和 server 的一种交互形式;REST 本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口);
- Server 提供的 RESTful API中,URL 中只使用名词来指定资源,原则上不使用动词。
比如:
- http://api.qc.com/v1/friends: 获取某人的 friends (好友列表);
- http://api.qc.com/v1/profile: 获取某人的 profile (详细信息);
- 用 HTTP 协议里的动词来实现资源的增删改查的操作。即通过 HTTP 动词来实现资源的状态扭转:
GET
用来获取资源,POST
用来新建资源(也可以用于更新资源),PUT
用来更新资源,DELETE
用来删除资源。
比如:
- DELETE http://api.qc.com/v1/friends: 删除某人的好友 (在http parameter指定好友id);
- POST http://api.qc.com/v1/friends: 添加好友;
- UPDATE http://api.qc.com/v1/profile: 更新个人资料;
- 以我们最近例子举例:
https://blog.csdn.net/SongXJ_01/article/details/118963187
这个是本文的 CSDN 资源地址,其意思就为 “SongXJ_01” 博主的 article 的详细信息,博客编号为 118963187 。
统一资源接口
RESTful 架构应该遵循统一接口原则,统一接口包含了一组受限的预定义的操作,不论什么样的资源,都是通过使用相同的接口进行资源的访问。
下面列出了 GET,DELETE,PUT 和 POST 的典型用法:
GET
- 200(OK) - 表示已在响应中发出
- 204(无内容) - 资源有空表示
- 301(Moved Permanently) - 资源的URI已被更新
- 303(See Other) - 其他(如,负载均衡)
- 304(not modified)- 资源未更改(缓存)
- 400 (bad request)- 指代坏请求(如,参数错误)
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务端当前无法处理请求
POST
- 200(OK)- 如果现有资源已被更改
- 201(created)- 如果新资源被创建
- 202(accepted)- 已接受处理请求但尚未完成(异步处理)
- 301(Moved Permanently)- 资源的URI被更新
- 303(See Other)- 其他(如,负载均衡)
- 400(bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 409 (conflict)- 通用冲突
- 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
- 415 (unsupported media type)- 接受到的表示不受支持
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务当前无法处理请求
PUT
- 200 (OK)- 如果已存在资源被更改
- 201 (created)- 如果新资源被创建
- 301(Moved Permanently)- 资源的URI已更改
- 303 (See Other)- 其他(如,负载均衡)
- 400 (bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 409 (conflict)- 通用冲突
- 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
- 415 (unsupported media type)- 接受到的表示不受支持
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务当前无法处理请求
DELETE
- 200 (OK)- 资源已被删除
- 301 (Moved Permanently)- 资源的URI已更改
- 303 (See Other)- 其他,如负载均衡
- 400 (bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 409 (conflict)- 通用冲突
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务端当前无法处理请求
GET,DELETE,PUT 和 POST 区别
HTTP 请求
其实 HTTP 中定义的请求方法不止有这四种,其总共有 7 种请求方法:① GET;② POST;③ PUT;④ DELETE;⑤ HEAD;⑥ TRACE;⑦ OPTIONS。
- GET 方法:对这个资源的查操作。
- DELETE 方法:对这个资源的删操作。但要注意:客户端无法保证删除操作一定会被执行,因为HTTP规范允许服务器在不通知客户端的情况下撤销请求。
- HEAD 方法:请求资源的头部信息,并且这些头部与 GET 方法请求时返回的一致。该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载,以此可以节约带宽资源。
- TRACE 方法:是 HTTP 协议定义的一种协议调试方法,该方法使得服务器原样返回任何客户端请求的内容。这样客户端就可以查看 HTTP 请求报文在发送的途中,是否被修改过了。
- OPTIONS 方法:用于获取当前URL所支持的方法。若请求成功,则它会在 HTTP 头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。
易混淆
PUT 和 POST
PUT 和 POST 都有更改指定 URI 的语义,但 PUT 被定义为Idempotent(幂等) 的方法,POST 则不是。【Idempotent 的方法:如果一个方法重复执行多次,产生的效果是一样的,那就是 Idempotent (幂等)的。】
也就是说 ,PUT 请求,如果两个请求相同,后一个请求会把第一个请求覆盖掉,所以 PUT 用来改资源。而 POST 请求,后一个请求不会把第一个请求覆盖掉,所以 POST 用来增资源。
GET 和 POST
- GET 参数通过 URL 传递,POST 放在 Request body 中;
- GET 请求会被浏览器主动缓存,而 POST 不会,除非手动设置;
- GET 请求参数会被完整保留在浏览器历史记录里,而 POST 中的参数不会被保留;
- GET 请求中有非 ASCII 字符,会在请求之前进行转码,POST不用,因为 POST 在 Request body 中,通过 MIME(Multipurpose Internet Mail Extensions),也就可以传输非 ASCII 字符;
- GET 请求产生一个 TCP 数据包,POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200;而对于 POST,浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应 200 ok;
相同:GET/POST 都是 TCP 链接。
误区
RESTful 架构有一些典型的设计误区。最常见的一种设计错误,就是 URI(Uniform Resource Identifier,统一资源标识符) 包含动词。因为"资源"表示一种实体,所以应该是名词,URI 不应该有动词,动词应该放在 HTTP 协议中。
举例来说,某个 URI 是 /posts/show/1
,其中 show 是动词,这个 URI 就设计错了,正确的写法应该是/posts/1
,然后用 GET 方法表示 show。
如果某些动作是 HTTP 动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的 URI 是:
POST /accounts/1/transfer/500/to/2
正确的写法是把动词 transfer 改成名词 transaction,资源不能是动词,但是可以是一种服务:
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
另一个设计误区,就是在URI中加入版本号:
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个 URI。版本号可以在 HTTP 请求头信息的 Accept 字段中进行区分:
Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1
Accept: vnd.example-com.foo+json; version=2.0
总结
博主认为 RESTful 架构就类似我们平时习惯使用的驼峰式命名方法一样,只是程序员们为了方便统一而约定俗称的一个“规则”,并没有说 GET 请求就一定要用作获取资源,POST 请求就一定用作新建资源,每种请求方式只不过是01编码的不同打包方式罢了。