目前互联网公司的应用架构基本都是前后端分离
后端的接口也基本上都是采用restful架构了

使用restful架构最主要的是遵循rest的思想 “统一资源接口“
REST全称 Representational State Transfer 翻译成中文就是“表述性状态转移” 表述的对象就是资源
在web的rertful架构中都是通过uri来一一对应资源 如 /api/person/1
URI既可以看成是资源的地址 也可以看成是资源的名称
代表的就是唯一的资源 但是不能表示对资源的操作 操作是结合标准的http方法(get post put等)来实现的


幂等
是个数学用语 对于单个输入或无输入的运算方法 如果每次都是同样的结果 则称其是幂等的
对于两个参数 如果传入值相等 结果也等于每个传入值 则称其为幂等的 如min(a,b)


restful的http方法 GET HEAD POST PUT DELETE OPTIONS TRACE PATCH
根据RFC2616第九章说明 http方法的定义有两点 safe and Idempotent 即安全性和幂等性 可以结合这两点对以上方法进行说明

1 GET
安全 幂等

用于获取资源
2 HEAD
安全 幂等
与get方法类似 但不返回message body内容 仅仅是获得获取资源的部分信息(content-type content-length)
restful框架中较少使用

3 POST
非安全 非幂等
用于创建子资源

4 PUT
非安全 幂等
用于创建 更新资源

5 DELETE
非安全 幂等
删除资源

6 OPTIONS
安全 幂等
用于url验证 验证接口服务是否正常

7 TEACE
安全 幂等
维基百科“回显服务器收到的请求 这样客户端可以看到(如果有)哪一些改变或添加已经被中间服务器实现 ”
restful框架中较少使用

8 PATCH
非安全 幂等
用于创建 更新资源 于PUT类似 区别在于PATCH代表部分更新
后来提出的接口方法 使用时可能去要验证客户端和服务端是否支持

接下来说一下日常中的使用

1 post和put的区别
post和put的区别在于uri 或说post用于创建子资源 如接口 POST /api/person/  会创建个资源如 /api/person/1或/api/person/2 ... 或/api/person/n 创建了新的uri 而put方法创建资源的uri是 PUT /api/person/1 这样就创建了个资源 如果1已经存在那么就是更新 所以put并不是只是更新操作 再有post是非幂等的
通常情况下 都会将post get put delete对应到CRUD操作上 但实际上put并不是只能更新

2 patch的使用
patch是2010后成为的正式http方法 详见RFC5789 它是对put的补充 在没有patch之前 都是用put进行更新操作 这时候 的接口中通常会有个逻辑规则 如 如果对象的的个字符属性为NULL 那么就是不更新该属性(字段)值 如果对象的字符属性是“” 那么就更新该属性(字段)的值 通过这种方式来避免全部覆盖的操作 现在有了patch就解决了这种判断 在put接口中不管属性是不是null 都进行更新 在patch接口中就对非null的进行更新

3 uri的使用问题
uri即使代表资源 通过不同的方法来区分操作 那么像如下的接口就已经违反了restful规范
GET /api/getPerson/1
DELETE /api/delPerson/1
GET /api/person/get/1
DELETE /api/person/delete/1

在复合规范的前提下 uri的定义应该也是实际使用中应该考虑的 如uri包涵那些信息?如版本 资源分类 资源名称 表述格式等 对于设计上的不多说了 直接看下面的url
/api/1.0/person/man/1.xml
/api/2.0/person/man/1.json
这样的url很常见也很直观 对不同版本接口增加了版本信息 并且对数据的表述格式进行了显式指定 不是不好
但是按照“统一资源接口”的思想 资源的uri已经不唯一了 有说对于版本号 表述形式等可以放到http的accept中进行指定 但具体没有验证过

4 查询问题的讨论
按照rest建议 查询操作要使用get方法 但是实际情况中处理起来比较麻烦 如 报表统计查询 需要传递的参数很多 就SpingMVC来说 如果采用get方法 那么@RequestParam接收的参数非常多 接口很难看 通常会封装为java对象 希望通过@RqeustBody接收并处理 但这是不支持get方法
对于这种情况 最简单的方式就是改成post方式 而且很多公司都是这么干的
但又觉得违反了restful规范 不改成post方式的话可能就需要将传递的参数对象细腻转为json串
后端字符串接收后再转为对象 这样感觉耶不太好 url中显式输出参数信息 个别情况json串太长活着包含特殊字符等也都很麻烦

///
HTTP请求类型
HTTP协议定义了很多类请求 包括OPTIONS HEAD GET POST PUT DELETE TRACE CONNECT 具体介绍如下

OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送’*’的请求来测试服务器的功能。
HEAD 向服务器索要与GET请求相一致的响应 只不过响应body将不会返回。这一方法可以在不必传输整个响应内容的情况下 就可以获取不包含在响应消息头中的元信息
GET 向特定的资源发出请求。
POST 向特定资源提交数据进行处理请求(例如提交表单或上传文件)。数据被包含在请求body中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
PUT 向指定资源位置上传其最新内容。
DELETE 请求服务器删除所表示的资源
TRACE 回显服务器收到的请求 主要用于测试或诊断
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
在实际应用中常用的也就是get和post 其 的请求方式也可以通过get和post间接实现。

GET和POST请求的区别

GET提交的数据放在HTTP请求报文的URL中 用?分割URL和传输数据 参数之间以&连接 如/Response/get?key1=value1&key2=value2。 POST把提交的数据放在HTTP请求报文的body中。
GET提交的数据大小有限制 而POST方法提交的数据没有限制
GET需要使用_GET[“key”] 而POST通过使用_POST[“key”] 以及读取php://input流 或读取HTTP_RAW_POST_DATA常量来实现
HTTP Request 报文结构

HTTP Request 结构如下图所示
这里写图片描述
这里写图片描述
Request Line 包含HTTP 请求类型(GET POST等), 请求URL  Http版本号
当使用“GET”方法的时候 body为空

HTTP Request Header中包含HTTP请求操作参数. header属性定义了所传输数据的各种特性.

HTTP Request Body 包含请求中携带的其 信息

HTTP Request Header

HTTP Request Header包含以下内容

Cache 头域
Client 头域
Cookie/Login 头域
Miscellaneous 头域
Cache 头域

If-Modified-Since

作用  把浏览器端缓存页面的最后修改时间发送到服务器去 服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致 那么返回304 客户端就直接使用本地缓存文件。如果时间不一致 就会返回200和新的文件内容。客户端接到之后 会丢弃旧文件 把新文件缓存起来 并显示在浏览器中.

例如 If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT

If-None-Match

作用: If-None-Match和ETag一起工作 工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时 将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新) 将返回个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag. 使用这样的机制将提高网站的性能

例如: If-None-Match: “03f2b33c0bfcc1:0”

Pragma

作用  防止页面被缓存  在HTTP/1.1版本中 它和Cache-Control:no-cache作用一模一样
Pargma只有个用法  例如  Pragma: no-cache
注意: 在HTTP/1.0版本中 只实现了Pragema:no-cache, 没有实现Cache-Control

Cache-Control

作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。常用各个指令含义如下

Cache-Control:Public 可以被任何缓存所缓存
Cache-Control:Private 内容只缓存到私有缓存中
Cache-Control:no-cache 所有内容都不会被缓存
Client 头域

Accept

作用  浏览器端可以接受的媒体类型 例如  Accept: text/html 代表浏览器可以接受服务器回发的类型为 text/html 也就是 常说的html文档 如果服务器无法返回text/html类型的数据,服务器应该返回个406错误(non acceptable)。

通配符 * 代表任意类型

例如 Accept: / 代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)

Accept-Encoding

作用  浏览器申明自己接收的编码方法 通常指定压缩方法 是否支持压缩 支持什么压缩方法(gzip deflate) (注意 这不是只字符编码);

例如  Accept-Encoding: gzip, deflate

Accept-Language

作用  浏览器申明自己接收的语言。 语言跟字符集的区别 中文是语言 中文有多种字符集 如big5 gb2312 gbk等等;

例如  Accept-Language: en-us

User-Agent

作用 告诉HTTP服务器  客户端使用的操作系统和浏览器的名称和版本.

上网登陆论坛的时候 往往会看到一些欢迎信息 其中列出了你的操作系统的名称和版本 你所使用的浏览器的名称和版本 这往往让很多人感到很神奇 实际上 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统 浏览器和其它属性告诉服务器。

例如  User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)

Accept-Charset

作用 浏览器申明自己接收的字符集 这就是本文前面介绍的各种字符集和字符编码 如gb2312 utf-8(通常 说Charset包括了相应的字符编码方案)
Cookie/Login 头域

Cookie

作用  最重要的header, 将cookie的值发送给HTTP 服务器
Entity 头域

Content-Length

作用 发送给HTTP服务器数据的长度。

例如  Content-Length: 18

Content-Type

作用 发送给HTTP服务器数据的类型

例如 Content-Type: application/x-www-form-urlencoded
Miscellaneous 头域

Referer

作用  提供了Request的上下文信息的服务器 告诉服务器我是从哪个链接过来的 如从我主页上链接到个朋友那里 的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问 的网站。

例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
Transport 头域

Connection

例如  Connection: keep-alive 当个网页打开完成后 客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭 如果客户端再次访问这个服务器上的网页 会继续使用这一条已经建立的连接

例如  Connection: close 代表个Request完成后 客户端和服务器之间用于传输HTTP数据的TCP连接会关闭  当客户端再次发送Request 需要重新建立TCP连接。
Host(发送请求时 该报头是必需的)

作用: 请求报头域主要用于指定被请求资源的Internet主机和端口号 它通常从HTTP URL中提取出来的
例如: 在浏览器中输入 http://www.baidu.com 浏览器发送的请求消息中 就会包含Host请求报头域 如下
Host http://www.baidu.com

此处使用缺省端口号80 若指定了端口号 则变成 Host 指定端口号