应用之间的通讯可以使用Web Services,也可以使用REST(表述性状态转移),后者因为轻量级和优雅而颇受欢迎,REST基于Http,实际上就是一套对HTTP/URI的最佳实践套路。在设计应用时能坚持REST原则,那就预示着你将会得到一个使用了优质架构的系统。
使用REST,套路分解为五条原则:
为资源定义ID
充分使用ID来做链接
使用标准动词
资源可以有多重表达形式
无状态
定义ID
从需求文本中提取名词和动词是一条设计的捷径。比如在电子商务应用中的一段需求描述:“客户可以点击列表内的订单,查询获得此订单”。那么订单(order)就是一个名词。定义ID也就是让每个订单可以有一个ID来标识它。使用REST,标识的方式是这样的:
http://example.com/order/1
http://example.com/order/2
分别表明查询1号订单、2号订单。类似的,对于客户、商品,可以如此表达:
http://example.com/customer/1234
http://example.com/product/4554
哦我去,那不是等于这玩意吗:
class OrderManager{
Order get(id:integer);
}
OrderManager.get(1)
而且前面还多了一个方案(http://)和主机(example.com) ,好啰嗦。然而,好处就体现在这个啰嗦里面了:
利用已被定义,现成的方案,易于理解的规则。
在全球范围中一直在运行的。你的订单可以来自example.com,或者其他叫做foo.com,bar.com之类的镜像站上,它们可能分布到全球各地。
利用现有的工具。比如订单的链接可以被多种渠道分享到朋友那里,或者加入到浏览器的书签中
处理单数名词外,还有复数的,就是一组资源,类似这样的:
http://example.com/orders/2007/11
http://example.com/products?color=green
对一类事物集合的标识。
充分利用链接表达资源和动作
链接是我们在HTML中常见的概念,但还可以更加通用。如下XML片段把对应order的product和customer链接进来:
<order self="http://example.com/customers/1234">
<amount>23</amount>
<product ref="http://example.com/products/4554">
<customer ref="http://example.com/customers/1234"> </customer>
</product>
</order>
应用程序可以由此XML“跟随”链接检索product和customer的更多数据。
还可以通过链接加入对资源的动作。比如你的账户还有100美元的情况下,你可以做存款取款转账四个操作:
GET /account/12345 HTTP/1.1
HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
<account_number>12345</account_number>
<balance currency="usd">100.00</balance>
<link rel="deposit" href="/account/12345/deposit" />
<link rel="withdraw" href="/account/12345/withdraw" />
<link rel="transfer" href="/account/12345/transfer" />
</account>
要是你的账户已经赤字,你可以做的动作就只有存款了:
GET /account/12345 HTTP/1.1
HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
<account_number>12345</account_number>
<balance currency="usd">-25.00</balance>
<link rel="deposit" href="/account/12345/deposit" />
</account>
这个动作清单是和状态有关的,术语叫做HATEOAS (Hypertext As The Engine Of Application State) 。
使用标准方法
我们已经提过,”从需求文本中提取名词和动词”,名词说了,就是资源的命名。动词呢。比如对订单的“查询”就是动词。
http://example.com/order/1
在REST内默认就是GET,也就是“查询”。使用浏览器的场合,上面的URI在发给服务器时,会被翻译为
GET http://example.com/order/1
语义上来说,就是查询在example.com上的ID为1的订单,使用http协议。当使用这套,在服务器放准守REST的话,你还可以得到额外的好处,就是:
幂等。如果你发送了一个GET请求没有得到结果,你可能不知道原因是请求未能到达目的地,还是响应在反馈的途中丢失了。幂等性保证了你可以简单地再发送一次请求解决问题。
缓存。所以在很多情况下,你甚至不需要向服务器发送请求。
GET在HTTP中被叫做动词(verb),除了GET,还有POST之外,还有PUT、DELETE、HEAD和OPTIONS。作为OO开发者的话,就可以想象到RESTful HTTP方案中的所有资源都继承自类似于这样的一个类:
class Resource {
Resource(URI u);
Response get();
Response post(Request r);
Response put(Request r);
Response delete();
}
幂等性同样适用于:
PUT。语义为:更新资源数据,如果资源不存在的话,则根据此URI创建一个新的资源
DELETE。语义为:删除一个资源,或者删除不存在的东西没有任何问题
POST方法,通常表示“创建一个新资源”,也能被用于调用任意过程,因而它既不安全也不具有幂等性。
为什么使用标准方法如此重要?从根本上说,它使你的应用成为Web的一部分,统一接口也使得所有理解HTTP应用协议的组件能与你的应用交互。通用客户程序(generic client)就是从中受益的组件的例子,例如curl、wget、代理、缓存、HTTP服务器、网关还有Google、Yahoo!、MSN等等。
无状态通信
REST要求状态要么被放入资源状态中,要么保存在客户端上。或者换句话说,服务器端不能保持除了单次请求之外的,任何与其通信的客户端的通信状态。
这样做的最直接的理由就是可伸缩性—— 如果服务器需要保持客户端状态,那么大量的客户端交互会严重影响服务器的内存可用空间(footprint)。
资源多重表述
同样一个order资源,可能响应检索的格式是xml,为了轻量级的支持移动app,现在需要支持json。这样的资源表达方式变化可以直接利用HTTP内容协商(content negotiation),而无需自己定义参数。比如本来的请求包:
GET /order/1 HTTP/1.1
Host: example.com
Accept: application/vnd.mycompany.order+xml
现在可以让移动客户端发出:
GET /order/1 HTTP/1.1
Host: example.com
Accept: application/vnd.mycompany.order+json
返回的响应包内,可以在其HTTP Content-type头中包含着数据类型。
才有已有标准的好处是客户端和服务器都可以更好的达到互换:
如果客户程序对HTTP应用协议和一组数据格式都有所“了解”,那么它就可以用一种有意义的方式与世界上任意一个RESTful HTTP应用交互。
倘若从客户端传来的数据符合应用协议,那么服务器端就可以使用特定的格式处理数据,而不去关心客户端的类型
原文: https://www.infoq.com/article...
改编自: http://www.infoq.com/cn/artic...
demo code : https://github.com/1000copy/s...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。