使用POST和PUT管理条目标识在Atom,每个条目在其所属工作空间和集合中都有一个ID是至关重要的——这三个部分加起来使条目的URI成为该条目的唯一标识符,将其与服务中的其它条目分别开来。AtomServer支持使用两种不同HTTP方法创建新条目:
POST和
PUT。
当条目是由
POST方法创建时,所用的URI是该条目将要插入的集合的URI。在这种情况下,AtomServer将负责为新条目分配条目id,并在响应体中将这个id返回给
POST调用者。
POST http://your-atom-server/widgets/acme取而代之,当条目是由PUT方法创建时,为条目分配id的责任就落到了完成PUT操作的客户端头上。PUT要操作的URI就成了欲创建条目的URI。
PUT http://your-atom-server/widgets/acme/1000.xml现有条目更新是通过对该条目的URI进行PUT操作来完成的——从这种意义来说,使用PUT创建一个条目就好像是“延迟更新”。如果没有这样的条目,就创建它,否则就对该条目进行更新。
使用乐观并发性(Optimistic Concurrency)保证数据完整性为了在高度分布的Atom世界里确保一致、可预见的数据,AtomServer使用了乐观并发性(Optimistic Concurrency)管理对系统的写入。乐观并发性(Optimistic Concurrency)规定:AtomServer的写入者必须知道他编辑资源的当前修订号,并且应当在假定他的写入操作可以完成的前提下来进行操作,但要优雅地处理其他人同时对该资源进行写入操作的情形。
例如,假设系统A和B同时想要更改某个数据feed中的Acme部件。A先来到,它请求Acme部件 123的当前表述:
GET http://your-atom-server/widgets/acme/123.xml然后feed响应返回了如下的“编辑链接”。
于是现在A着手对123.xml的表述开始编辑。此时B来到并请求123.xml的当前版本,并得到了同样的响应。B的编辑比A用时要短,因此B立即将更改写回了编辑链接:
PUT http://your-atom-server/widgets/acme/123.xml/2操作成功,返回200 OK(200成功),让B知道其编辑已成功提交给AtomServer。此时,A完成了编辑并试图将其写入同一个编辑链接,但是由于B的编辑,修订号已经被改变了。因而,A将会收到一个409 CONFLICT(409冲突)HTTP错误,表示他尝试更新的资源自从他最近一次刷新其视图之后已被他人更改过了。遇到这种情况,A应该再次GET这个资源,这次会获取一个新的编辑链接,然后重复这个过程。注意,这使得A在B已经改动后的/widgets/acme/123.xml的副本上进行编辑,因此系统避免了A盲目地覆盖B的变更。
在许多系统中,对给定数据集合将只有单个权威的写入者。在那些场景中,为了降低乐观并发性(Optimistic Concurrency)带来的开销,可通过将星号(*)作为修订序号来屏蔽乐观并发性(Optimistic Concurrency):
PUT http://your-atom-server/widgets/acme/123.xml/*然而,使用这一特性记住一点非常重要:只适于客户端知道给定资源仅有一个写入者的情形。
类别查询在Atom中,条目“类别”是由一对值来明确说明的:Scheme和Term。Scheme实质上是类别的“名字空间”,而Term是这一名字空间中一个特定的值。
借用GData对Atom的扩展,AtomServer支持一种特殊的feed语法,它可以让客户端基于应用于条目的“类别”来对feed进行过滤。比如,为了只获取Acme部件中被标记为“红”颜色的feed,请求可能是这样的形式:
GET http://your-atom-server/widgets/acme/-/(urn:colors)red如果指明了多个类别,只有满足全部指定类别(逻辑与)的条目能被接受。例如,
GET http://your-atom-server/widgets/acme/-/(urn:colors)red/(urn:size)big将会返回所有大号、红色的Acme部件。利用前缀表示法可指明使用“AND(与)”和“OR(或)”的任意类别组合:
GET http://your-atom-server/widgets/acme/-/OR/(urn:colors)red/AND/(urn:size)big/(urn:color)blue这将返回所有要么是红色,要么是大号、蓝色的Acme部件。客户端应该将这些feed跟其它feed一视同仁:它们跟没有类别的feed一样同样可以被轮询与分页。
AtomServerAtomServer是实现Atom存储的一款现成实现。它是以Java web应用实现的,应该部属于任何J2EE Serlet容器中。幕后,AtomServer使用了Apache的Atom协议开源实现——
Abdera——处理RESTful动词与Atom的XML词汇。
就给现有应用加上Atom前端而言,Abdera是一款极其出色的类库。与之相比,AtomServer则是一个完整的Atom存储实现。它提供了开箱即用的存储和与Atom元数据(以及Atom条目本身内容)交互需要的所有组件。
AtomServer的协议尽可能地借鉴了GData的设计。在某些场合我们做了一些轻微的调整,以进一步提高URL的可读性,简化查询结构,或者实现GData规范所未能涉及的特性。
AtomServer在关系数据库中管理条目关联的所有Atom元数据;在关系数据库或文件系统中管理条目实际内容,这取决于你的具体需求。 AtomServer自动地为你处理Atom协议相关的每个方面(URI解释,解析Atom元素与扩展,更新时间戳,对条目分门别类),因此你只需要将改动发布到服务器并每隔一段时间轮询feed更新。
AtomServer使用非常方便。它可以部署为一个简单的WAR文件,或者作为替代,部署为一个独立的服务器,运行于其内部嵌入的Jetty服务器上。大多数的应用都只需要很少的配置(一些用于配置Atom工作空间和内容存储的Spring Bean)就可以用上AtomServer了。
结论AtomServer仍有一些重要、高级的特性我们还没有涉及到。这次就没有机会展开讨论了,在今后的文章我们将深入探讨:
- Atom类别自动标记器:一种方便的配置机制,用于创建或更新条目时对其进行“自动标记”。其中内置了XPathAutoTagger,使得你能够“XPath”你的内容并根据条件将其与Atom类别关联。
- 批处理操作:全面支持创建,更新或者删除等请求混合而成的“批处理”操作。
- Feed聚合:一种将来自不同集合或工作空间的不同条目聚合到一个条目的强大能力,使用了ATom类别。包括请求这些聚合feed的能力。因此它让你从与不同的feed 打交道——自行在后端将信息联结起来——中解脱出来,你只需监听一个单一的聚合feed,它将反映其内部任一部分的变化 。
AtomServer是看得见摸得着的。它正运用在我们公司的实际生产环境中,每天处理着上百万的请求,存储着几百万的条目。构建于Atom这样的 RESTful规范之上,同时利用诸如GData这样的现有服务的设计,保证了其构建根基是坚固的。我们希望你能下载一份拷贝,并告诉我们你的想法。你可以从这里得到它:
http://www.atomserver.org,只需简单的步骤它就能很好的为你工作。