REST笔记(四):Atom发布协议------ AtomPub

  前一节介绍了一种IETF推荐的一种超媒体格式------Atom,这一节中主要Atom发布协议-------Atom Publish Protocol,简称AtomPub,有时更简洁写作APP。
  开篇之前介绍几个重要概念先:
  1、媒体类型
  描述相关资源表述所使用的类型,如XML、JSON、JPG、MP3等、处理模型以及链接关系值
  2、HTTP惯用语
  它规范了如何对资源进行操作以及处理HTTP头信息和状态码
  3、领域应用协议。
  领域应用协议(Domain Application Protocol DAP),它为服务端与客户单的资源的交互定义了一套规范,如资源的媒体类型、链接关系值、以及HTTP惯用语。DAP居于HTTP之上,具体化了HTTP的广义应用。服务实现DAP后,通过在返回给客户端的资源的表述中添加链接,以对资源进行广告,提示消费者可以进行哪些操作来驱动业务的运行。
  4、条目资源(entry resource):可以使用atom条目表现的成员,如文本
  5、媒体资源(media resource):不可以使用atom条目表现的成员,如视频、音乐等可执行文件
  6、代理资源(proxy resource):没有资源连接条目,被插入到集合中,用来替代媒体资源。
  AtomPub是一种建立在Atom超媒体格式之上的应用协议,用于发布和编辑Web资源。它采用一种标准化的机制来创建和编辑Web资源,并能解决任何可能发生的冲突,如对Web资源操作时的并发等问题。本节中将说明Atom如何实现服务端与客户端如何实施一套领域应用协议(Doamin Application Protocol ,简称DAP)。

  目录:
  1、AtomPub概述
  2、AtomPub四个要素
  3、AtomPub的扩展
  4、AtomPub如何解决并发操作
  5、REST WCF中使用AtomPub
  6、.Net中消费Atom资源


  1、AtomPub概述:
  1.1、AtomPub是一个应用协议,而不是传输协议,制定了服务和消费者对资源操作的规范,所以它是基于对资源的发布和编辑设计的
  1.2、AtomPub指明服务发回给消费者的Atom资源之间如何进行转移
  AtomPub处理模型规范了一下几点:1、资源以何种格式进行表述 2、消费者操作资源的HTTP惯用语 3、服务端如何通对资源进行广告 4、超媒体控件的标记

  2、AtomPub四个要素。
  成员和集合是针对发布活动的事物的抽象名词。成员是封装了资源的表述或处于草案状态等待发布资源的表述。集合是一组成员。如下为一个包含三个成员的集合.服务文档与分类文档见下图:

图1

图2


  2.1、集合
  集合是在服务文档中定义的。在实际开发过程中,点击图2中的collection 后的href,就应该能获取到一个类似图1的集合。消费者通过每个集合的href属性与每个集合所包括的资源交互。在图1中,此集合就是一个包含三个条目(entry)的提要(feed)的Atom表述。AtomPub中没有规定如何创建或者删除集合。集合支持一下操作:

  • 客户端通过collection所指明的href值获取Atom格式资源
  • 若客户端打算创建资源,需将资源的表述POST到表述所指定的URI。

集合通过Accept指定资源所支持的媒体类型。集合通过分类文档对多种类别进行广告。

  2.2、成员
  对成员的操作与集合类似。注意:对于媒体资源,应当使用代理资源进行处理,也就是在集合插入代理资源,然后通过制定的链接来获取媒体资源。

  2.3、分类文档
分类文档包含对集合和成语进行分类的列表。如下图:

  2.4、服务文档
  服务文档包含访问集合而对外公布的入口点。图2就是一个服务文档。

  集合与成员描述了Web资源的表述形式,分类文档与服务文档则从整体上描述协议。一个服务文档,可以包含多个工作区,它通过工作区来对集合进行分组;一个集合可以出现在多个工作区中。而一个工作区又包括多个成员。

3、AtomPub的扩展
  3.1、对Atom的扩展

  • 通过利用Atom的可扩展添加了三个条目(entry)元素edited,control,draft.以上三个在Atom的命名空间。以control为例,扩展代码如下:
SyndicationItem item = new SyndicationItem("item4", "content4",
new Uri("http://tyb1222.cnblogs.com/",
UriKind.Absolute), "Id", DateTime.Now);
item.ElementExtensions.Add(new SyndicationElementExtension("control","tyb1222.cnblogs.com","control content"));

  

  edited元素表示一个成员创建时间或者编辑。集合中的成员通过edited倒序排列,它总是由服务区控制的。control元素用于发布控件。发布控件是致力于控制发布生命周期的Atom扩展元素。<draft>就是一个发布控件,它的值表示客户对成员可见性的期望。

  • 添加了两个链接关系值,edit、edit-media。前者用于指向条目资源,后者用于指向媒体资源。消费者可以edit、edit-media链接关系值发送GET\PUT\DELETE请求
  • 通过type参数指定Atom媒体类型。type参数是为了方便不同的客户端处理能力。

  3.2、对HTTP头进行扩展
  AtomPub引入了一个新的HTTP头信息:Slug。当客户端提交一个新成员时,可以包含一个Slug头信息。这个Slug头信息代表了对服务器的一个请求:将这个头信息放入资源表述的ID、标题或者URI中。客户端通过它来让服务端创建人类可读的URI。

4、AtomPub如何解决并发操作
  通过edit链接可以获取一个资源的表述,这样就可能导致多个不同的消费者并发操作改资源。在这种情况下,一个消费者对资源所做的操作可能被另外一个消费者所覆盖,这就是所谓的丢失更新。为了解决丢失更新,服务端可以选择将资源挂起,直到资源一个生命周期的结束,这是一种悲观锁的方式来解决这个问题。但是它同时限制了在资源生命周期中对资源的除了GET之外的其他操作。AtomPub也可以通过之前介绍的ETag(实体标签:EntityTag)和条件匹配(If-Match)通过乐观锁定的方式来解决这个问题。
1、客户端通过POST请求创建资源,创建成功后,服务端返回:
HTTP/1.1 201 Created
Location: Order/3ad3b19b-a7fc-4ee6-a446-fa4b2d9b0140
ETag: "634600748498750000"
2、此时不同的消费者都可以通过Location指定的值获取资源的表述。当不同的消费者发送修改资源的请求,如PUT\DELETE时,需要向请求HTTP头中添加If-Match信息与ETag值。
如:

PUT Order/3ad3b19b-a7fc-4ee6-a446-fa4b2d9b0140
......
If-Match:"634600748498750000"

  如果自从最近一次生成ETag值以来发生过变化,则服务器返回412状态码,即 ttpStatusCode.PreconditionFailed。当消费者获取到412状态码后,它必须决定下一步业务如何进行。最常见的方式是再次发送GET请求以获取最新的资源表述以及ETag值,然后连同ETag值再次通过条件匹配发送到服务端。

关于ETag值以及并发控制,之后还会有更详细的介绍,敬请期待。。。

  5、REST WCF中使用AtomPub
  使用WCF构建REST架构风格的服务时,在.Net FCL(Framework Class Library)中使用AtomPub最基本的是如何发布AtomPub的服务文档。FCL中封装了一些 类来为我们发布服务文档,如:AtomPub10ServiceDocumentFormatter
ResourceCollectionInfo、Workspace、CategoryDocument、ServiceDocument。代码如下:

List<ResourceCollectionInfo> resourceCollectionInfos = new List<ResourceCollectionInfo>();
ResourceCollectionInfo resourceCollectionInfo = new ResourceCollectionInfo("Title",
new Uri("tyb1222", UriKind.Relative));
CategoriesDocument categoriesDocument = CategoriesDocument.Create(new Uri("http://www.cnblogs.com/tyb1222", UriKind.Absolute));
categoriesDocument.ElementExtensions.Add(new SyndicationElementExtension("outer", "outNamespace", 1000));
categoriesDocument.ElementExtensions.Add(new SyndicationElementExtension("in", "outNamespace", "inValue"));
resourceCollectionInfo.Categories.Add(categoriesDocument);
resourceCollectionInfo.Accepts.Add("application/atom+xml;type=entry");
resourceCollectionInfos.Add(resourceCollectionInfo);
ResourceCollectionInfo resourceCollectionInfo2 = new ResourceCollectionInfo("Title2",
new Uri("tyb1222", UriKind.Relative));
resourceCollectionInfo2.Accepts.Add("image/png");
resourceCollectionInfos.Add(resourceCollectionInfo2);
List<Workspace> workspaces = new List<Workspace>
{
new Workspace("workspace1",resourceCollectionInfos),
};
ServiceDocument serviceDocument = new ServiceDocument(workspaces) { BaseUri = new Uri("http://localhost:1209/AtomPub/feed") };
AtomPub10ServiceDocumentFormatter serviceDocumentFormatter =
serviceDocument.GetFormatter() as AtomPub10ServiceDocumentFormatter;

运行服务代码如上图2。
  当点击<app:collection href="tyb1222">中的href链接,则能获取到此集合资源,以超媒体格式Atom显示。如上图1所示。

  6、.Net中消费Atom资源
由于Atom也是一种XML格式,所以在.Net中,直接通过获取资源的URI读取到XML文件内容,然后再对资源做相应处理

static void ConsumeAtom()
{
  XmlReader reader = XmlReader.Create("http://localhost:1209/AtomPub/feed/tyb1222");
  SyndicationFeed feed = SyndicationFeed.Load(reader);
  List<SyndicationItem> syndicationItems = feed.Items.ToList();
  syndicationItems.ForEach(item=>
                    {
                      Console.WriteLine(item.Title.Text);
                    });
}

  运行结果如下图:

posted @ 2011-12-21 16:07  tyb1222  阅读(5388)  评论(2编辑  收藏