Feed 的基本概念
在互聯網發展的早期,隨著信息發布變得越來越頻繁,單純使用傳統的遠程 Html 文檔來直接查看信息的方式逐漸難以滿足用戶對信息消費時效性的需要。這要求信息發布商們尋找新的方式來將更新的內容及時發送給用戶,於是 Web feed 應運而生,它實際上是一種以 XML 為基礎的數據格式,通常被用來發布那些互聯網上頻繁更新的內容,如博客、滾動新聞等等。
feed 的用途
大家在浏覽網頁時看到的橘紅色圖標就是 feed 的標志。點擊這個圖標就可以看到由互聯網內容服務商提供的 feed,用戶可以使用浏覽器通過 feed 的 URL 地址獲取更新內容。如使用 Firefox 浏覽器,遇到提供 feed 的網頁,用戶可以通過單擊地址欄右側的 feed 圖標來訂閱該網頁提供的內容更新。
用戶還可以使用專用的 feed 閱讀器“訂閱”這些 feed,根據個人的閱讀喜好有選擇的閱讀。現在流行的在線閱讀器如 Google Reader, 國內的鮮果網,還針對 feed 內容提供如分享、討論、加標記等功能,方便在朋友、同事和社會網絡中共享信息和知識。
feed 的特點
從開發人員的角度來看,feed 是一種包含指向資源鏈接和一系列元數據的 XML 文檔。目前最為流行的 feed 格式主要包括 RSS 和 Atom。
RSS 主要包括 4 部分:channel(包含 feed 發布者提供的元數據)、image(圖標、圖片)、item(feed 中更新的條目)和 text (用戶提供反饋信息的表單)。目前最常用的是 RSS 2.0 版本。感興趣的讀者可以通過參考資料中的文章來了解 RSS 格式的詳細內容。
針對 RSS 在國際化、內容復用性不足方面,Atom 提供了更嚴謹全面、更具可擴展性的 feed 數據格式和發布協議。現在我們討論的 Atom,往往指以 IETF 組織提出的 Atom 1.0。
清單 1. Atom 1.0 樣例 <?XML version="1.0" encoding="utf-8"?>
<feed XMLns="http://www.w3.org/2005/Atom">
<title>Example Feed</title>
<link href="http://example.org/"/>
<updated>2003-12-13T18:30:02Z</updated>
<author>
<name>John Doe</name>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<entry>
<title>Atom-Powered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03"/>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<summary>Some text.</summary>
</entry>
</feed>
feed 的優勢
相比每次使用電子郵件,使用 feed 作為信息發布的方式具有多種優勢。包括用戶無需提供個人郵件地址、隨時訂閱隨時退訂、feed 提供的信息摘要和資源鏈接更方便用戶閱讀等等。對網站開發人員來說,采用 feed 格式來發布內容數據,可以給用戶更多的閱讀選擇。用戶通過第三方的 feed 閱讀器有選擇地查閱,也可以通過聚合、過濾、排序、分享等手段將自己感興趣的內容組成新的 feed 重新發布,這大大提高了信息更新的時效性,而且更有益於信息的有效傳播。
通常 feed 中往往包含供人閱讀的內容信息,如新聞、博客、相冊等等。近些年來隨著 Web 2.0 的不斷流行,feed 也被用來發布結構化的數據:如 Google 在線電子表格數據、IBM 在線社區更新等等,甚至目前流行的在線開放 API 也采用 feed 作為數據格式,如 Yahoo! 搜索、豆瓣等等。
WebSphere sMash 中對 feed 的支持
WebSphere sMash 作為 IBM 面向 Web2.0 應用程序提供的開發和運行平台,針對開發人員使用 feed 的不同場景提供了多種支持,主要目的是讓使用基於 feed 的技術和協議變得更簡易,避免針對協議細節的編程。在 sMash 中有多個組件為 feed 編程提供不同類型的支持,詳見表 1。在簡單的文字介紹之後,本文將提供多個簡單場景的創建過程,展示 sMash 為 feed 編程帶來的簡單性和趣味性。
表 1. WebSphere sMash 中 feed 相關組件介紹
為數據提供 feed 視圖
第一個例子介紹如何為已有的數據提供 feed 視圖。這裡用一個 MySQL 數據庫代表數據源,有一張表 blog_posts 保存演示用的內容數據。Groovy 腳本將從中讀取最新的 10 條記錄,並為其提供 Atom 數據格式的 feed 視圖。
1. 首先用 sMash 命令行工具創建應用程序 feedvIEw.demo;
zero create feedvIEw.demo
2. 在創建好的 sMash 應用程序的依賴管理配置文件 config/ivy.XML 中加入所需的模塊。
清單 2. 使用 zero.atom 和 zero.data 模塊,以及 MySQL 的 JDBC 驅動 <dependencIEs>
<dependency org="zero" name="zero.core" rev="[1.1.0.0, 2.0.0.0["/>
<dependency org="zero" name="zero.atom" rev="[1.1.0.0, 2.0.0.0["/>
<dependency org="zero" name="zero.data" rev="[1.1.0.0, 2.0.0.0["/>
<dependency org="mysql" name="MySQL-connector-Java" rev="5.1+"/>
</dependencIEs>
3. 創建 Groovy 腳本並保存至 public/latest_posts/atom/index.groovy。
清單 3. 從數據庫獲取內容數據、創建 Atom 的數據結構,並將其發布成為一個 Atom feed // file: /public/latest_posts/atom/index.groovy
try {
// Get configured DataManager for data Access
def data = zero.data.groovy.Manager.create('blog_db')
// RetrIEve posts data
def result = data.queryArray(
'SELECT ID as id, post_date as updated, content as summary '
+ 'FROM blog_posts order by updated desc limit 0, 10')
def feed = [
title: "latest 10 posts",
updated: new Date(),
entrIEs: result
]
request.docType = 'feed'
request.vIEw = 'atom'
request.atom.output = feed
render()
} catch (Exception e) {
request.status = HttpURLConnection.HTTP_INTERNAL_ERROR
request.error.message = e.getMessage()
request.vIEw = "error"
render()
}
4. 當然你還需要在配置文件 config/zero.config 中加入必要的信息來連接數據庫。
清單 4. 連接 MySQL 數據庫 /config/db/blog_db = {
"class" : "com.mysql.jdbc.jdbc2.optional.MySQLDataSource",
"serverName" : "localhost",
"portNumber" : 3306,
"databaseName" : "MYDBNAME",
"user" : "someuser",
"password" : "secretpasssWord"
}
5. 在命令行中輸入如下命令來解析、獲取相關的模塊,並啟動這個 sMash 應用程序:
zero resolve
zero start
6. 使用浏覽器訪問 http://localhost:8080/latest_posts/atom/,你將會看到已經發布為 Atom feed 的數據。
個性化 feed 內容
除了將已有內容發布成 feed 之外,另一個主要的使用場景即為消費第三方提供的 feed 內容。sMash 提供了 zero.feed 包為消費和處理第三方的 feed 數據提供了豐富的功能支持和非常簡單易用的 API。以查看搜狐 IT 新聞為例,用戶只需要查看當天的內容,這時候你可以使用 zero.feed 組件提供的編程接口創建幾行腳本就搞定了!
1. 使用命令行工具創建名為 personalfeed.demo 的 sMash 應用程序:
zero create personalfeed.demo
2. 在 sMash 應用程序的依賴管理文件 config/ivy.XML 中增加對 zero.feed 模塊的依賴:
清單 5. 使用 zero.feed 模塊 <dependencIEs>
<dependency org="zero" name="zero.core" rev="[1.1+,2.0.0.0["/>
<dependency org="zero" name="zero.feed" rev="[1.1+,2.0.0.0["/>
</dependencIEs>
3. 創建腳本文件 /public/sohuITtoday/index.groovy:
清單 6. 使用 Groovy feed API // set response header "Content-Type"
headers.out."Content-Type" = "application/atom+XML"
// fetch sohu IT news feed and filter only today
zero.feed.FeedFactory.fetch("http://news.sohu.com/rss/it.XML")
.after("-P1D")
.writeTo(request.writer[])
4. 啟動 sMash 應用程序,訪問地址 http://localhost:8080/sohuITtoday/ 即可。
5. 如果你還需要查看新浪 IT 和網易 IT 新聞,還可以將他們聚合起來變成一個 feed. 在 personalfeed.demo 應用程序中創建文件 /public/ITtoday/index.groovy:
清單 7. 聚合並過濾 feed 內容 // set response header "Content-Type"
headers.out."Content-Type" = "application/atom+XML"
zero.feed.FeedFactory.aggregate(
"http://news.sohu.com/rss/it.XML",
"http://rss.sina.com.cn/news/allnews/tech.XML",
"http://tech.163.com/special/00091JPQ/rssit.XML")
.after("-P1D")
.writeTo(request.writer[])
最後在浏覽器中訪問地址 http://localhost:8080/ITtoday/,你將會看到一個 feed 包含了 3 大網站的 IT 新聞。
除了編寫服務器端運行的 Groovy 來獲取 feed 數據之外,zero.feed 模塊還提供 AJax 風格的 Javascript feed 編程接口。這意味著 Web 開發者只需要浏覽器即可針對 feed 進行編程。為了簡化 JavaScript 訪問 feed 數據時冗長的方法調用,Web 開發者可以使用 JSON 格式來代理 XML 格式來訪問 feed。
這裡仍以訪問搜狐 IT 新聞為例,直接創建 HTML 文件 public/sohuITToday/sample.Html:
清單 8. 使用 JavaScript 訪問 feed <Html>
<head>
<script type="text/Javascript" src="/dojo/dojo.JS"></script>
<script type="text/Javascript">
dojo.require("dojo.parser");
dojo.require("zero.feed.Feed");
</script>
<script type="text/Javascript">
function fetchSohuIT() {
zero.feed.FeedFactory.fetch("http://news.sohu.com/rss/it.XML")
.after("-P1D")
.loadAsJSON(function(feed) {
var items = feed.entrIEs;
var HtmlContent = "";
for (var i = 0; i < items.length; i++) {
var title = items[i].title;
var link = items[i].links[0].href;
HtmlContent += "<a href='" + link + "' target='_blank'>"
+ title + "</a><br/>";
}
dojo.byId("feed").innerHTML = HtmlContent;
});
}
</script>
</head>
<body>
<p>This sample shows how to get resulting feed in JSON format.</p>
<button onclick="fetchSohuIT();" dojoType="dijit.form.Button">
load sohu IT news!
</button>
<div id="feed"></div>
</body>
</Html>
運行 sMash 應用程序,訪問 http://localhost:8080/sohuITtoday/sample.Html, 單擊按鈕“load sohu IT news!”,稍後就可以看到如圖 1 所示。
圖 1. AJax feed API 訪問搜狐 IT 新聞
為數據服務提供 REST 風格的 API
ZRM 是什麼?
ZRM 是 Zero 資源模型(Zero Resource Model)的縮寫,它提供了一種創建 RESTful 資源的簡便方法,你可以輕松創建出 REST 風格的數據服務。
為數據服務提供開放 API 可以方便第三方數據消費者使用數據服務,而使用 REST 風格構建 API 已經成為目前最為普遍的做法。以豆瓣網提供的開放 API 為例,它提供 REST 風格的 URI, 並且使用 Atom 1.0 作為數據格式,方便開發者編寫程序訪問豆瓣提供的各種數據服務。使用 sMash 你可以輕松地創建這樣的開放 API。
我們使用 sMash ZRM 創建一個簡單的聯系人管理程序。在這個應用程序中,我們將為聯系人數據提供 RESTful API。為了簡化開發過程,推薦讀者使用 WebSphere sMash 的開發工具 AppBuilder。
1. 打開 AppBuilder 創建 sMash 應用程序 contact.demo。
圖 2. 使用 AppBuilder 創建應用程序 contact.demo
圖片看不清楚?請點擊這裡查看原圖(大圖)。
2. 為聯系人信息創建一個 Zero 資源模型 (ZRM),指定相關的列名稱和數據類型。
圖 3. 選擇創建文件類型 ZRM model
圖片看不清楚?請點擊這裡查看原圖(大圖)。
圖 4. 創建 ZRM model /app/models/contact.JSon
圖 5. 使用 ZRM model 編輯器指定列名稱和數據類型
圖片看不清楚?請點擊這裡查看原圖(大圖)。
圖 6. 創建 resource handler app/resources/contact.groovy
圖片看不清楚?請點擊這裡查看原圖(大圖)。
3. 創建數據庫和樣例數據。
圖 7. 切換到 Console 標簽運行命令 zero model sync 創建數據庫表
圖片看不清楚?請點擊這裡查看原圖(大圖)。
圖 8. 為樣例數據創建 SQL 腳本 /init_data.sql
圖片看不清楚?請點擊這裡查看原圖(大圖)。
圖 9. 運行 SQL 腳本導入樣例數據 : zero runsql init_data.sql
圖片看不清楚?請點擊這裡查看原圖(大圖)。
這時候單擊 AppBuilder 右上角的 “Start” 按鈕啟動 contact.demo 應用程序,在浏覽器中打開地址 http://localhost:8080/resources/contact?format_as=atom 即可看到 feed 格式的聯系人信息。
zero.resource 模塊為以上 RESTful API 接口提供豐富的查詢功能支持。如 http://localhost:8080/resources/contact?telephone_startswith=158&format_as=atom 將列出所有電話號碼以 158 開始的聯系人信息。
4. 為了保護數據服務的安全,你應該為開放的數據服務提供安全認證。這裡可以利用 sMash 的安全特性方便的將 REST API 保護起來。 在 config/zero.config 中加入如下配置:
清單 9. 安全設置@include "security/enableSecurity.config"
# secure contact API by basic authentication
@include "security/basicAuthentication.config" {
"conditions": "/request/path =~ /resources/contact(/.*)?"
}
# only people in group “frIEnds” can Access contact API
@include "security/authorization.config" {
"conditions": "/request/path =~ /resources/contact(/.*)?",
"groups" : ["FRIENDS"]
}
這段配置信息為訪問聯系人的 REST API 提供 HTTP 基本身份驗證,並且授權只有名為 FRIENDS 的群組成員可以訪問。
為第三方服務提供 feed 數據視圖
雖然 feed 已經成為 Web 2.0 流行風潮中數據服務最常見的發布格式,但現實 Web2.0 世界仍舊存在大量數據服務並沒有使用 RSS 或 Atom 等格式,如 Amazon Web Services,Ebay Web Services 等提供的 HTTP API。使用 WebSphere sMash 可以連接這類數據服務,並且提供將 XML 格式的數據轉換成 feed 格式。
這裡以 Last.fm 提供的 Track Search 服務為例,通過 XSL 和一個 groovy 方法來為 Last.fm 提供 feed 格式的數據視圖。
1. 第一步當然是創建 sMash 應用程序,這裡直接介紹接下來的步驟。打開 AppBuilder 的 DependencIEs 標簽中的 “Add” 按鈕,選中 zero.assemble.flow。
圖 10. 使用 zero.assemble.flow 模塊
圖片看不清楚?請點擊這裡查看原圖(大圖)。
2. 為 TrackSearch 服務提供服務描述文件 app/assemble/services/LastfmSearch.XML。
清單 10. 服務描述文件片段<?XML version="1.0" encoding="utf-8"?>
<entry XMLns="http://www.w3.org/2005/Atom"
XMLns:z="http://www.projectzero.org/assemble/component">
<title>Last.fm Web Services</title>
<link rel=
"http://www.projectzero.org/assemble/component/url-template"
type="text/XML"
href="http://ws.audiOScrobbler.com/2.0/?method=
{method}&api_key={apiKey}&artist=
{artist?}&track={track}"
/>
......
3. 創建 XSL 文件 public/stylesheet/lastfm.xsl 將 Last.fm 提供的結果轉換成為 Atom feed
清單 11. 格式轉換文件片段<?XML version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
XMLns="http://www.w3.org/2005/Atom"
XMLns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
<xsl:template match="/">
<feed><title>
Search result for <xsl:value-of select=
"lfm/results/opensearch:Query/@searchTerms"/>
</title>
<opensearch:totalResults>
<xsl:value-of select="lfm/results/opensearch:totalResults"/>
</opensearch:totalResults>
<xsl:apply-templates select="lfm/results/trackmatches/track"/>
</feed>
</xsl:template>
......
4. 在 config/zero.config 中填入你的 API Key:
/config/lastfm/apiKey = "Last.fm API Key: http://www.last.fm/api/account"
5. 最後創建 Groovy 腳本 public/testTrackSearch/index.groovy 調用這個 TrackSearch 服務。這裡使用關鍵詞 "BelIEve" 進行搜索:
清單 12. Groovy 腳本調用 Track Search 服務def criteria = [method: "track.search", track: "BelIEve", format: "atom"]
// use service description file /app/assemble/services/LastfmSearch.XML
def results = invokeService("TrackSearch", criteria)
// rendering
request.vIEw = "XML"
request.XML.output = results
headers.out."Content-Type" = "application/atom+XML"
render()
啟動這個應用程序,在浏覽器中輸入 http://localhost:8080/testTrackSearch 即可看到如圖 11 所示的 feed。
圖 11. 為 Track Search 服務提供 feed
圖片看不清楚?請點擊這裡查看原圖(大圖)。
綜合范例:統計 digg.com 熱門文章的 dig 數量
我們已經通過上面的內容了解了 sMash 為 feed 的各種應用場景提供了易用且全面的支持。最後這裡用 sMash 的 AJax feed API 編寫一個非常有趣的實例,來展示如何用 JavaScript 統計 digg.com 上熱門文章被 dig 的最大、最小以及平均次數。
首先創建 sMash 應用程序,參考“個性化 feed 內容” 部分修改配置文件增加對 zero.feed 模塊的依賴。然後創建文件 public/digStatistics.Html:
清單 13. Html 文件中的 JavaScript 代碼片段function doGrouping() {
dojo.byId("loadingImg").style.display = "block";
// grouping entrIEs with statistics of digg counts
var queryParams = {
"select": [
"digg:category/text() as atom:title",
"count($collection) as atom:summary",
"sum($collection/digg:diggCount) as digg:totalCount",
"max($collection/digg:diggCount) as digg:maxDiggCount",
"min($collection/digg:diggCount) as digg:minDiggCount",
"avg($collection/digg:diggCount) as digg:avgDiggCount"
],
"groupBy": "digg:category"
};
zero.feed.FeedFactory.fetch("http://digg.com/rss/index.XML")
.declareNamespaces({"digg":"http://digg.com/docs/diggrss/"})
.query(queryParams)
.filterByXPath("atom:summary > 1")
.loadAsXML(function(feed){
// …
});
}
最後啟動這個 sMash 應用程序,使用浏覽器訪問 http://localhost:8080/digStatistics.Html,單擊按鈕“digg.com statistics”,你就會看到如圖 12 的有趣的統計結果了!
如果你需要完整的演示程序代碼,可以在 sMash 的演示程序 zero.flow.demo 中找到它。
圖 12. 使用 AJax feed API 創建的 digg.com 統計
圖片看不清楚?請點擊這裡查看原圖(大圖)。
結束語
通過介紹使用 WebSphere sMash 開發 REST 風格的 Web 應用程序,尤其是 sMash 針對 RSS/Atom feed 這些流行的信息聚合格式提供的各種功能和工具支持,相信讀者已經對 feed 的應用和開發有了一定了解。文中例子的完整代碼都可以在下面的“下載”欄目中找到,你只需要安裝有 WebSphere sMash 的命令行工具即可運行他們,使用 AppBuilder 或者 Eclipse 插件可以讓開發變得更輕松。