程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> WebSphere >> 用Flickr API擴展Project Zero和WebSphere sMash的腳本平台

用Flickr API擴展Project Zero和WebSphere sMash的腳本平台

編輯:WebSphere

開放 Flickr API 讓您可以將元素整合到 Project Zero 應用程序中

Flickr 照片共享服務是當今最流行的 Web 應用程序之一。它提供了具備優秀社會性網絡的健壯托管服務,讓上載、組織和尋找照片變得異常簡單。這一切都很棒,但從一個開發者的角度來看,Flickr 最讓人著迷的部分是其用來讀寫照片數據的公共 API。您可以借助任何編程語言通過 HTTP 發送 API 請求,而且現在也有很多開源項目湧現出來,可以針對各種語言封裝此 API 。在本文中,您將了解如何通過提供可在 Project Zero 應用程序中輕松重用的 Groovy 綁定來 “Zero 化” Flickr API。學完本文後,只需幾行代碼即可從 Groovy 腳本讀寫照片數據。

開始之前

本文假設您已經下載了 Project Zero 並或者已經完成了 介紹性教程 的學習或者自己編寫過簡單的應用程序。該概覽包括了如何獲得 Flickr API 鍵的指令,這些都是測試本文中所提供的代碼所必需的。

簡介

Flickr 照片共享服務是當今最為流行的 Web 應用程序之一,它包括了一個公共 API,讓開發人員可使用 HTTP 請求訪問照片數據。Flickr 的 API 是 RESTful 的而且十分容易理解,但若想進行請求和讀取響應,還需要執行一些乏味的步驟。本文展示了如何去除這些乏味的步驟並讓 Zero 和 Flickr 間的通信簡單到只需幾行代碼。本文還探討了 Project Zero 幾個有趣的擴展點。

用 Groovy 封裝 Flickr API

讀寫照片數據的 Flickr API 的基礎是以 HTTP 發送的消息和以 XML 或 JSON 為格式的數據結構。本文使用的是 JSON,因為它的數據結構(簡單映射和列表)更容易從 Groovy 的角度處理。在本節,將會介紹如何使用 Zero 的全局上下文和 Groovy 的腳本為 Flickr 的 API 創建一些簡單的包裝器方法。

創建示例項目

要完成我們的 Flickr API “Zero 化”處理,需要創建兩個 Zero 項目:一個針對用來與 Flickr 交互的 Groovy 代碼,一個使用這些 Groovy 代碼完成某些任務。第一個項目名為 zero.services.flickr,第二個項目名為 flickr.test。如果想要親自編寫代碼,則可以使用清單 1 所示的 Zero 命令行創建這兩個簡單的項目:

清單 1. 創建測試項目

$ zero create zero.services.flickr
$ zero create flickr.test

為 flickr.test 編輯 Ivy 文件並在 zero.services.flickr 上添加一個依賴項。打開 /config/ivy.xml 並添加如清單 2 所示的 XML 代碼行:

清單 2. 添加 Ivy 依賴項

<dependency name="zero.services.flickr" org="zero" rev="1.0+"/>

zero.services.flickr 項目並不需要額外的庫或依賴項,因為 Flickr API 構建在 HTTP 和 JSON 基礎上;我們將使用 Zero Core 所包含的 HTTP 和 JSON 庫與 Flickr 通信並創建到實際圖像文件的 URL。

調用 Flickr API

每個 Flickr 請求都需要一個方法名和一組參數集(參數集也可能為空)。響應作為 JSON 對象返回,JSON 對象除了所請求的數據外還具有狀態屬性(設為 ok 或 fail)。您可以充分利用這樣一個事實,即 JSON 對象在 Groovy 中表示為簡單的映射和列表並創建一個十分簡單的 API 來發送請求和讀取響應。讓我們開始一個用例:您可能想讓您的用戶能用三四行代碼即可發出 Flickr 請求,如清單 3 所示:

清單 3. “Zero 化” 的 Flickr API 原型 #1

def method = "flickr.photosets.getPhotos";
def params = [
   photoset_id: 1234567890,
   per_page: 25
];
def response = invokeMethod("flickr.groovy", "flickr");

該代碼非常棒,但還可以通過利用 Zero 的全局上下文加以改進。將請求和響應數據存儲在全局上下文中讓開發人員可以更為容易地跨腳本或文件劃分進行請求和響應處理;例如,一個服務器端腳本可能會向一個或多個服務發出 API 調用,而同時響應數據則由客戶端的模板呈現。清單 4 顯示了如何相應處理此用例:

清單 4. “Zero 化” 的 Flickr API 原型 #2

request.flickr.method = "flickr.photosets.getPhotos";
request.flickr.params = [
   photoset_id: 1234567890,
   per_page: 25
];

invokeMethod("flickr.groovy", "flickr"); // uses GC for I/O

   def response = request.flickr.response[];

設計好之後,就可以開始編寫代碼了。在 zero.services.flickr 項目內,在 /app/scripts/flickr.groovy 下創建 Groovy 腳本。第一個要添加到此文件中的方法是清單 3 和 4 中的 flickr() 方法。要實現此方法,需要注意如下三個方面:

Flickr API 調用所需的 URI 格式。

Flickr API 鍵的值。

外向(outbound) HTTP 請求的 Zero Connection API。

有關 Flickr API 調用所需的 URI 格式的相關內容在 Flickr API 文檔可以找到;其本質是為用戶所提供的每個請求參數創建一個含查詢參數的 URI。此外,還必須包含 API 鍵,這意味著為了提供此 API 鍵,必須要有一個約定(以免用戶在腳本中硬編碼其 API 鍵)。清單 5 顯示了構建這個請求 URI 所需要的代碼:

清單 5. 構建 Flickr 請求 URI

def uri = "http://api.flickr.com/services/rest/?format=json&nojsoncallback=1";

uri += "&api_key=${config.flickr.key[]}";
uri += "&method=${request.flickr.method[]}";

request.flickr.params[].each() {
  uri += "&${it.key}=${it.value}";
}

請注意清單 5 中已經硬編碼了基本的 Flickr URI 並使用了 JSON 數據結構 — 這些不應更改。還有,這個 API 鍵是從一個名為 config.flickr.key 的全局上下文屬性中讀取的;我們將要求用戶在其應用程序配置文件中設置這個值以鼓勵好的編程實踐。清單 5 代碼中最後一點需要注意的是 Groovy 的語法技巧是如何簡化將 JSON 對象(映射)轉變為有效 URI 的過程的。通過使用嵌入式變量和 each() 方法來在此映射上進行迭代,用五行非常易讀的代碼,我們就創建了一個相當復雜的 URI。

一旦有了 URI,只需使用 Zero 的 Connection API 發送請求即可。幸運的是,這個 API 有很多簡便的方法來調用 RESTful 服務。清單 6 中的代碼做了這樣一個 HTTP GET 請求並以 JSON 解析了相應的響應:

清單 6. 處理 Flickr 請求

def response = Connection.doGET(uri);
def json = response.getResponseBodyAsString();
request.flickr.response = JSONObject.parse(json);

對於此項目,我們假設所有操作都是 GET(讀取);所提供的代碼可以很容易地擴展到 POST(寫入),但這超出了本文的范圍。

整個 flickr() 方法是由清單 5 和 6 中的代碼組成的,也可以在本文所附的示例項目下載中得到。如果在將兩個清單合並成一個可用函數方面遇到任何麻煩,可以參考下載中的 flickr.groovy 文件。

創建照片 URL

調用方法只是用戶將 Flickr 數據合並到應用程序中的所有工作中的一部分。一旦有了一個或更多照片的元數據,用戶將需要創建到由 Flickr 用戶共享的這個實際圖像文件的 URL。圖像文件 URL 不包括在 JSON 響應數據中 — 必須用 Flickr 提供的格式化指令將它們合並 ;因為這些 URL 通常很長並且包括很多變量,為了能從 JSON 響應中構建這些 URL,需要有一些簡便的方法。

清單 7 顯示了兩個簡單方法,用來獲取 Flickr 的 photo 數據結構之一(為所有返回照片元數據的方法所用)並為它的圖像文件創建 URL。受托管的照片實際上都有幾個圖像文件,我們的代碼說明了這一點;用戶可以將 Flickr 返回的 photo 數據傳遞給我們的 thumbnail() 和 original() 方法以查看縮略圖和原始圖像。清單 7 中的代碼包括在與 flickr() (/app/scripts/flickr.groovy) 相同的文件裡:

清單 7. 配置 Flickr API 鍵

def original(photo)
{
   def server = "http://farm${photo.farm}.static.flickr.com/${photo.server}";
   def name = "${photo.id}_${photo.originalsecret}_o.${photo.originalformat}";
   return "${server}/${name}";
}

def thumbnail(photo)
{
   def server = "http://farm${photo.farm}.static.flickr.com/${photo.server}";
   def name = "${photo.id}_${photo.secret}_t.jpg";
   return "${server}/${name}";
}

Groovy 內的全局上下文捷徑

代碼到目前為止很有效,但我們用戶代碼中的 invokeMethod() 的使用還不夠完美。invokeMethod() 方法對於所有運行於 Zero 平台上的 Groovy 腳本都可用,它還提供了一種迅捷的方法來調用另一腳本中的代碼;對於只需重復使用一兩次的代碼而言,這種做法還可以,但對於像這樣的一個庫來說,調用可能更實際些。如果能更新清單 4 中的代碼來直接調用 flickr() 方法,就最好不過了,如清單 8 所示:

清單 8. “Zero 化” 的 Flickr API 原型 #3

request.flickr.method = "flickr.photosets.getPhotos";
request.flickr.params = [
   photoset_id: 1234567890,
   per_page: 25
];

flickr();

def response = request.flickr.response[];

Zero Core 已經為常用的幾個 API 實現了這種功能,包括 render()、listFiles() 和 getRequestedUri()。這些常用的方法就稱為綁定。此外,Zero Core 還允許您用自己的方法擴展默認的 Groovy 綁定,以便能更容易地從應用程序的任何位置對其進行調用。本節將介紹如何為 Flickr 方法創建 Groovy 綁定並提高它們的可用性。

創建定制捷徑

要想添加定制的 Groovy 綁定,需要編寫一個類,該類實現 zero.core.groovysupport.bindings.BindingHandler 接口,然後再在應用程序的 zero.config 文件注冊該類。BindingsHandler 接口只有一個方法 — addVariables() — 用來將綁定名(比如 flickr())映射到它們的實際實現。清單 9 顯示了如何在 zero.config 中配置 BindingsHandler 類:

清單 9. 向 Zero Core 添加 Groovy 綁定

[/config/bindings/.groovy[]]
my.bindings.handler.ClassName

如果所提供的是方法綁定(正如我們現在所做的),那麼通過在 zero.core.groovysupport.bindings.InvokeBindings 中擴展類可以簡化很多工作 — 這種做法能將方法調用轉給 invokeMethod(),由它負責處理 Groovy 代碼的執行。有了這個機制,就能夠享用這些更巧妙的方法調用的所有益處,且不必自已加載和執行 Groovy 腳本。不管接口如何實現,這個配置文件將不會改變。

FlickrBindings 類

為了使這三個 Flickr 方法對於其他 Groovy 腳本編寫器也方便使用,我們已經創建了一個名為 FlickrBindings 的類,它將方法名映射給對 invokeMethod() 的調用,包括用戶提供的參數。清單 10 顯示了此類的代碼。請把清單 10 中的這個類加入到 zero.services.flickr 示例項目中:

清單 10. FlickrBindings 類

package zero.services.flickr;

import java.io.FileNotFoundException;
import java.util.Map;

import org.codehaus.groovy.runtime.MethodClosure;

import zero.core.groovysupport.bindings.InvokeBindings;
import zero.json.java.JSONObject;

public class FlickrBindings extends InvokeBindings
{
   private static final String _SCRIPT = "flickr.groovy";

   private static final String _FLICKR = "flickr";
   private static final String _ORIGINAL = "original";
   private static final String _THUMBNAIL = "thumbnail";

   public void addVariables(Map<String, Object> variables)
   {
     super.addVariables(variables);
     variables.put(_FLICKR, new MethodClosure(this, _FLICKR));
     variables.put(_ORIGINAL, new MethodClosure(this, _ORIGINAL));
     variables.put(_THUMBNAIL, new MethodClosure(this, _THUMBNAIL));
   }

   public void flickr()
     throws FileNotFoundException, NoSuchMethodException 
   {
     invokeMethod(_SCRIPT, _FLICKR, null);
   }

   public String original(JSONObject photo)
     throws FileNotFoundException, NoSuchMethodException 
   {
     Object gstring = invokeMethod(_SCRIPT, _ORIGINAL, new Object[]{ photo });
     return gstring.toString();
   }

   public String thumbnail(JSONObject photo)
       throws FileNotFoundException, NoSuchMethodException 
   {
     Object gstring = invokeMethod(_SCRIPT, _THUMBNAIL, new Object[]{ photo });
     return gstring.toString();
   }
}

此類中的如下兩項需要注意。第一個是為了將方法名映射到方法調用而使用了 Groovy 運行時的 MethodClosure 類; 此類所要實現的全部功能就是在調用給定對象上指定的方法並將結果返回給調用的腳本。第二點要注意的是返回字符串的 Groovy 方法也可能會返回 Groovy Strings(或 "GStrings"),它們是包含嵌入式變量的一些字符串;我們在 original() 和 thumbnail() 方法中遇到過這種情況。為了防止在用戶想要字符串,得到的卻是 GString 的情況下拋出異常,在傳遞方法返回值之前,我們使用了 toString() 方法。調用 toString() 就確保了所有 GString 的變量均被解析而且所創建的是所想要的字符串。

類完成後,剩下所要做的就是通過 zero.config 注冊它。打開 zero.services.flickr 項目中的 /config/zero.config 文件並加入清單 11 中顯示的語句:

清單 11. 向 Zero Core 添加 Groovy 綁定

[/config/bindings/.groovy[]]
zero.services.flickr.FlickrBindings 

任何將 zero.services.flickr 作為依賴項加以包含的應用程序現在都能從其任意的 Groovy 腳本中調用這些 Flickr 方法。在一下節中,將實際應用這些方法來創建一個可在您自已站點內使用的、基於 Flickr 的小部件。

用 Groovy 和 Flickr 拼接照片

至此,我們已經編寫了很多代碼,但還沒有真正地將這些代碼投入測試,亦無從知道這些代碼是否真的可以簡化基於 Flickr 的服務和小部件的編寫。現在,我們將使用這些代碼去創建一個很常見的用戶界面組件:照片拼接。圖 1 顯示了我們想要創建的這種照片拼接的一個屏幕快照。您可能已經在 blog 和其他關注 Web 2.0 技術或社會性網絡的網站中看到過類似的照片集。通過使用在前兩節中編寫的 Groovy 庫,僅僅用幾行代碼就能創建這個小部件。

圖1. 照片拼接的屏幕快照

創建如圖 1 所示的照片拼接最簡單的方法就是使用一個查找照片集的 Groovy 模板,然後使用由 Flickr 返回的照片集構建一個 HTML 表。更具體地說,就是使用 flickr() 方法查找照片記錄,使用 thumbnail() 方法構建照片拼接,使用 original() 方法創建這個拼接到 Flickr 原始圖像的超級鏈接。清單 12 顯示了構建拼接表所需的 Groovy 代碼;可以把它復制到一個更大的模板文件中,作為應用程序的完整用戶界面的一部分。如果想立即測試一下這個小部件,它已經包括在 flickr.test 示例項目中 /public/index.gt 下。只要運行這個應用程序並用所喜歡的浏覽器訪問 http://localhost:8080 就可以看到這個小部件的運行。

清單 12. 配置 Flickr API 鍵

<table border='0' cellpadding='0' cellspacing='10'>

<%
def set = "72157602828759420"; // flickr photo set ID

def length = 4; // size of the photo display box

for (page in 1..length) {
   //
   // set name-value pairs as specified by flickr API
   //
   request.flickr.method = "flickr.photosets.getPhotos";
   request.flickr.params = [
     photoset_id: set,
     per_page: length,
     page: page,
     extras: "original_format"
   ];

   flickr(); // send request to flickr

   def response = request.flickr.response[];

   println "<tr>";

   response.photoset.photo.each() { // build the photo display box 
    println "<td>";
    println "<a href='${original(it)}'><img border='0' src='${thumbnail(it)}'></a>";
    println "</td>";
   }

   println "</tr>";
}
%>

</table>

清單 12 中的頭兩行代碼分別提供了 Flickr 照片集 ID 以及拼貼圖框的大小;可以改變這些值,以決定所顯示的是何照片以及這個框有多大(如果您手頭沒有可用於測試的照片集,就可以使用清單 12 中的這個 Project Zero 團隊的照片集)。另外一個值得注意的地方就是您不會同時得到所有的照片數據;照片數據在頁面中讀取,這樣就有一些照片已被呈現,其他照片則尚在顯露的過程中。如果允許在同一時間得到所有照片,並且隨後創建表單元格,那麼在拼貼圖最終彈出前,加載時的初始等待時間將會比較長。

在自己運行這個代碼前,需要在應用程序中的 zero.config 文件中設定 Flickr API 鍵。本文開始的部分就曾指導您參考 Flickr 站點來獲得自己的 API 鍵,希望您現在已經有了 API 鍵。清單 13 顯示了如何使用您的個人 API 鍵設置前面章節討論過的 config.flickr.key 屬性:

清單 13. 配置 Flickr API 鍵

[/config/flickr]
key=1234567890

有了 API 鍵,就可以使用我們的定制 Groovy 綁定自由地讀寫 Flickr 數據。

結束語

Flickr 為那些想要將站點元素合並到自己的應用程序中的開發人員提供了一種非常有用、靈活的 API ,若能使用 Groovy 腳本編寫和 Project Zero 平台會讓事情更加簡單。此外,本文中所介紹的這些技巧也可以適用到其他綜合了社會性和數據分享的熱門站點(比如 YouTube、Blogger 等)。只要 Web 站點能繼續用 RESTful API 和可移植的數據格式公開其共享數據,您就總是能夠將它們合並到 Zero 編程模型中。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved