REST在逐渐演变的过程中,大家慢慢的放弃掉很多非必要的内容,比如WADL,比如REST原本的格式要求等等,甚至连最基本的数据交互的方式,大家也广而用之,不仅仅局限在json跟xml中
本着两个基本原则:“对于大家认同的标准知识的传承最为简单”以及“能复用别人的思想就是站在了别人的肩膀上”,
存在的一个bug
在我们日常常见的系统中,webservice往往都会返回一个状态码,用以标识用户当前请求的状态。但是这里面存在几个小问题:
- 很多时候服务器返回给我们的结果并不是我们想要的,但是我们只有在解析完整个报文之后才能知道
- 每当我们从一套系统转移到另一套系统,系统所返回的状态码的方式跟映射(00-成功,01-失败这种)方式都不一致,导致我们的很多知识需要重新学起
- 最重要的,对于使用这些系统的人员而言,每当需要接入新的webservice的时候,都将面临全新的学习
从上面的几个角度看,貌似SOAP格式反而有不少的可取之处,毕竟SOAP拥有更加一致的interface,在某种程度上可以降低学习成本
站在巨人的肩膀上
对于上面的问题,其实一个很简单的解决方案就是标准化,任何公司或者系统都可以推出一套标准化的方案,用以解决上面的问题。
比如,建立自己的映射码对照系统,或者强制要求所有的开发人员跟随自己的标准。
但是,问题依然,我们的开发人员依然需要有特定的学习,也许在公司内部切换学习的成本会降低了,但是当出现公司级别或者更大的项目级别的合作和对接的时候,学习的成本依然存在。
那么有没有一套成型的标准,是我们可以直接借鉴的?有没有什么标准是在整个程序界,可以跨语言,跨系统而适应的?很高兴,我们的前辈为了HTTP交互制定了一套HTTP status。
在深入解释HTTP status之前,先看一下我们的身边,每天我们使用的最多的一款软件-浏览器,就是完全基于HTTP协议而工作,每天我们实现的系统之间的调用都是通过HTTP来进行,也就是说HTTP是一种普世性的方案,不管是什么语言或者什么公司,只要你的程序是通过HTTP交互,那么你的程序将或多或少地follow了HTTP的标准。
既然HTTP的标准已经被大量的使用了,那么我们更多的使用HTTP的标准来为我们服务看起来将会是一件特别的愉快的事情。
以前我们已经使用http来传输我们的内容,现在,我们一起来探索一下,是不是可以利用HTTP自身的特点让我们的应用或者API更加的丰富鲜活起来。
一个建议的分类方案
其实HTTP标准所实现的状态,可以基本分为:协议基本状态
,服务器状态
和用户请求状态
三种。
HTTP的状态码包含了从1到6,6个不同种类的返回码,其中,1(消息相关-重传/切换协议),3(移动/代理)和6*(特例)。
其中 1* 所对应的为协议的基本状态,3* 和 5* 为服务器状态,而2 ,4则是用户请求状态。
从webservice的角度而言,我们的一次请求不外乎会成功或者失败,而失败则包含了请求数据错误跟服务器错误两种,因此,我们只要从HTTP的状态码中选取能描述我们的成功失败相关的状态进行复用即可。
刚刚好,HTTP的状态码中,2 *,可以几乎完美的覆盖我们所需要的成功的状态(成功/部分成功/受理未处理等),而4 *跟5 * 则几乎可以覆盖常见的用户错误跟服务器错误。(3 * 主要是给浏览器用的,所以可以在webservice中忽略掉)
成功状态
2 * 状态码简析
- 200 OK : 可用于标识GET类请求,并返回相应的数据,如果对方数据已经缓存,此时应刷新缓存
- 201 Created : 可用于标识POST类请求,并返回约定的数据,或者数据查询的URL
- 202 Accepted : 服务器已经接受请求,可用于标识POST/PUT/DELETE类,但是处理方式为异步的情况
- 203 Non-Authoritative Information : 留着吧,webservice貌似没什么用
- 204 No Content : 可用于标识PUT类请求,并不返回任何数据。
- 205 Reset Content : 可用于标识PUT类请求,并不返回实体数据,但是通过HEADER返回最新数据拉取的URL
- 206 Partial Content : 处理部分完成,可用户处理GET请求,查询时没有最终结果时的返回。并同时返回下一次查询所应该使用的查询URL
错误码部分
4 * 状态码简析
- 400 Bad Request : 请求参数错误,可以用于参数格式校验不通过的地方
- 401 Unauthorized : 缺乏校验相关字段或者校验不通过
- 402 Payment Required : 没有支付相关的步骤,支付系统可以有
- 403 Forbidden : 拒绝访问,可以用在某些并发策略中,如果单一IP或者用户请求过多,直接拒绝并返回原因远比将系统拖垮来的好
- 404 Not Found : 对应于GET请求,如果没有数据直接返回404
- 405 Method Not Allowed : 服务器使用,对于webservice没有语义价值
- 406 Not Acceptable : 服务器使用,webservice没有语义价值
- 407 Proxy Authentication Required
- 408 Request Timeout
- 409 Conflict : 对于重复提交的请求,可以直接返回409
- 410 Gone
- 413 Request Entity Too Large : 可用于对账单拉取或者其他大规模数据拉取时,如果webservice同时拉取的数据过大,可以返回部分数据并给出拉取下一次数据的URL,此方法可以让对方在不了解分页机制的同时完成数据的拉取。
- 414 Request-URI Too Long
- 415 Unsupported Media Type
- 416 Requested Range Not Satisfiable
- 417 Expectation Failed
- 421 There are too many connections from your internet address
- 422 Unprocessable Entity
- 423 Locked : 资源被锁定,对应于分布式系统对于同一资源的请求,可以返回423
- 449 Retry With : 这个返回码对于某些有步骤相关性操作的行为,如果越过了其中的某个步骤可以返回这个响应码,以协助理解系统
5 * 状态码简析
- 500 Internal Server Error : 对于不可辨识或者不方便告知用户的异常
- 501 Not Implemented
- 502 Bad Gateway :当你的服务器需要访问另外的服务器并且对方的服务器无法正常响应的时候返回,可以协助多套系统同步定位该问题
- 504 Gateway Timeout : 同502,但是仅仅描述超时
对于5 *的状态码,需要很好的内容封装以方便自己定位问题的同时尽可能少的暴漏服务器的信息
Java中的受益,建立错误码对于Exception的映射
通过上面的描述,我们发觉错误码可以简单的理解为用户/数据错误,跟系统错误。
在Java的世界里面刚好存在两种我们最常见的Exception,运行时Exception跟需要检查的Exception。那么在我们进行系统编码的时候,可以简单的通过定义自己的BusinessException跟SystemException来完成跟上面4 *和5 *的错误码的对照,然后再借助于J2EE体系中的Filter,可以很简单的实现自己的系统跟HTTP STATUS的绑定。