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.rzrgm.cn/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);
});
}
運行結果如下圖:

浙公網安備 33010602011771號