級 別: 初級 方 偉 (kevinth.fang@gmail.com), 軟件工程師, IBM
2009 年 7 月 20 日 企業(yè)級應用中越來越多地采用 Ajax,Widget 等 Web 2.0 技術進行開發(fā),SOA 架構中的一些傳統(tǒng)技術與 Web 2.0 技術的整合呈現出越來越多的需求,Tuscany 作為開源界最成熟的 SCA 框架之一,在 Web 2.0 方面提供了很多支持,本文將通過示例說明 Tuscany 在這方面提供的諸多功能,并且對其中的某些功能介紹其技術實現。 引言 如今在企業(yè)級應用中,Ajax、Widget、RSS/Atom 等 Web 2.0 技術正在得到越來越廣泛的使用,這些技術不但產生了良好的用戶體驗,同時也來越來越多地影響著許多前端系統(tǒng)的編程模式和系統(tǒng)架構。許多傳統(tǒng)的 Java EE 產品和框架也在越來越多地引入這些 Web 2.0 技術,如 Struts2 和 JSF 都有了越來越完善的 Ajax 擴展,Portal 產品中也基于 Dojo 等 javascript 框架引入部分刷新等機制,大幅提升了性能和用戶體驗??梢钥闯觯琖eb 2.0 不僅是互聯網應用的概念,它為企業(yè)級應用乃至整個軟件行業(yè)都產生著深遠影響。 基于 SOA 的企業(yè)應用,要考慮和 Web 2.0 的結合,首先需要解決的是怎樣將各種各樣的服務與那些 Web 2.0 技術整合在一起,在很多時候服務端和客戶端的整合是具有一定難度的。SCA 作為一種跟具體語言、平臺無關的 SOA 編程模型,必然需要考慮那些 SOA 傳統(tǒng)技術與 Web 2.0 技術的整合。Apache Tuscany 作為開源界最成熟的 SCA 框架之一,在這方面提供了很多支持。本文正是從這個角度出發(fā),結合實例介紹 Tuscany 在 Web 2.0 方面提供的諸多功能,同時對 SCA 和一些典型的 Web 2.0 技術作一定的介紹。
Tuscany 簡介 SCA 的基本概念以及 SCA 規(guī)范的具體內容并不在本文的范疇之內,有興趣的讀者可以通過一些相關文檔了解相關內容,這也是閱讀本文的基礎。下面本文首先對 Tuscany 框架做一定的介紹。 Tuscany 是 Apache 的開源項目,它是 IBM、Oracle、SAP 等廠商聯合成立的 SOA 標準化組織 -OSOA 支持下開發(fā)出的 SCA 框架,它既是開源界 SCA 的試金石,也是當前開源界最成熟的 SCA 框架之一。 Tuscany 基本架構 圖 1 為 Tuscany 的基本架構圖,從圖中可以看出,作為一個輕量級 SCA 框架,Tuscany 提供了非常松散耦合的框架結構。主要有以下幾個特點: - Tuscany 是平臺無關的可嵌入框架,可以在各種 Hosting Platform 上運行,如 Tomcat,JBoss,WAS 等 Web 容器上運行,也可以在 J2SE 環(huán)境下運行。
- Tuscany 的核心模塊提供了 SCA 規(guī)范的 API 實現,Tuscany 系統(tǒng)的 SPI 接口,一些系統(tǒng)基本實現(如事件,工廠類,存儲等),以及一整套擴展機制,這些擴展機制為 Tuscany 整合各個平臺的服務提供了基礎。
- Tuscany 的擴展是完全松散耦合的,框架本身提供了大量的擴展實現,用戶也可以在自己的系統(tǒng)中擴展 Tuscany 的實現,只需要遵循 Tuscany 的擴展規(guī)范以及 API 接口。
圖 1. Tuscany 基本架構圖 Tuscany 主要有以下幾個方面的擴展: - Implementation:SCA 組件(Component)的實現方式,一個 SCA 組件可以由各種語言或技術平臺實現,如:POJO,EJB,Spring Bean,bpel 流程,各種腳本語言等等。
- Binding:是 SCA 的綁定(Binding)規(guī)范的實現,SCA 服務(Service)和引用(Reference)的綁定方式,即一個 SCA 服務可以暴露為 Web Service,Java RMI 服務,http 資源,jms 消息等等,一個 SCA 引用也可以通過 Web Service,RMI 調用,http 調用,jms 調用等方式調用遠端服務。
- Databinding:數據綁定方式,這是 Tuscany 提出的概念,一般用與在 Binding 中定義參數的傳輸格式,比如 Web Service 的 Binding 一般用 XML 格式,SCA 的 Binding 一般用 SDO 格式,Jsonrpc 的 Binding 一般用 Json 格式等等。
- Interface:是 SCA 的接口(Interface)規(guī)范的實現,SCA 服務(Service)和引用(Reference)的接口暴露方式,一般有 Java,WSDL 等類型。
Tuscany 的 Web 2.0 擴展 Tuscany 在 Web 2.0 方面主要提供了以下幾類擴展: - Implementation 擴展:script implementation 提供了各種腳本語言的實現,如 Javascript,python,ruby 等,widget implementation 提供了將一個 SCA Component 封裝成 widget 的能力。resource implementation 提供了一種簡單的 http 資源的實現。
- Binding 擴展:atom binding 提供了 atom 方式的綁定實現,dwr binding 提供了利用 dwr 框架進行 ajax 調用的能力,http binding 提供了直接進行 http 訪問的能力,jsonrpc binding 提供了在 Javascript 中使用 jsonrpc 進行 ajax 調用的能力。
- Databinding 擴展:json 格式的 databinding 提供了將 json 格式的數據與其他格式(如 xml,Java Bean,SDO 等)之間互相轉換的能力。
以上只是簡要地列出了 Tuscany 在 Web 2.0 方面提供的一些擴展,后面本文將通過一些實例講述怎樣使用其中的某些擴展功能,并且對其中具體實現細節(jié)進行一定的介紹。
環(huán)境建立 下面介紹運行本中示例所需要的環(huán)境。 要運行基于 Tuscany 的應用,除了需要 Tuscany 的運行庫支持以外,還需要很多 Tuscany 的依賴庫,由于 Tuscany 是一個 SCA 集成框架,它使用了大量的第三方框架來進行各方面平臺的集成,因此它的依賴庫的管理比較復雜,因此本文的示例基于 Maven 構建,可以較為方便地管理依賴庫,并且 Tuscany 本身也是基于 Maven 建立的,下面首先對 Maven 作簡要的介紹。 Maven 簡介 Maven 是一個基于模型描述的軟件項目管理工具,通過一種 XML 格式的文件(POM)文件來描述項目對象模型。它兼有 Ant 的一部分功能,可以對 Java 項目進行編譯,測試,打包,安裝以及部署。它基于插件機制實現,以插件的方式實現軟件項目管理的生命周期中各個時期所需要執(zhí)行的任務(goal),它不僅 便于單個項目的構建,同時可以建立一個龐大的軟件資源庫(repository),資源庫可以在本地建立,也可以連接到遠程的、官方的,通過資源庫使項目 依賴更加方便。很多開源項目都具有自己的 Maven repository。Tuscany 也是基于 Maven 建立的,它的各個模塊和各個擴展都依賴著不同的開源框架。 M2Eclipse 簡介 本文的示例所用的 IDE 環(huán)境為 Eclipse,因此介紹一下 Maven 在 Eclipse 平臺上的插件:M2Eclipse。 基于命令行運行 Maven 比較直觀但是不利于在開發(fā)環(huán)境中部署和調試。M2Eclipse 提供了一整套 Maven 和 Eclipse 結合的插件,極大的方便了在 Eclipse 上開發(fā) Maven 項目,M2Eclipse 包括以下功能: - 最基本的 Maven 運行環(huán)境,Maven Builder 以及 Maven Launch 等等。
- 一系列簡化 Maven 配置文件編寫的可視化界面,如 POM 編輯器,Maven repository 搜索框等。
- 新建 Maven 工程和導入已有 Maven 應用的向導。會建立基本的 Maven 工程目錄結構。
- Maven repository 的本地索引庫,便于在 POM 文件中搜索和添加依賴。
- 將 Maven 與 WTP 結合,使得用 Maven 建立的 Web app 工程能直接部署到通過 WTP 配置的 Server 上,這極大地方便了 web 應用的部署和調試。
場景簡述 下面介紹一個簡單的業(yè)務場景,做為本文示例的出發(fā)點。 大家買股票的時候都比較關心一個股票的實際價值與成長性,因此在證券行業(yè),市盈率是一個比較重要的指標,它可以從一定程度上衡量股票的具體價值,市 盈率分靜態(tài)市盈率和動態(tài)市盈率,靜態(tài)市盈率的計算比較簡單,其計算公式為: 市盈率=股票每股市價/每股稅后利潤 即: 市盈率 = 股價 / 每股收益 本文的示例就是對靜態(tài)市盈率進行計算,并且用基于 Web 2.0 的界面顯示不同的公司市盈率的比較。一般情況下當前股價的獲取會來自固定的服務提供商,在本文的示例中,當前股價由一個 web service 提供,而每股收益由一個 Java 的 RMI 服務提供,以展示 Tuscany 整合不同服務的能力。
示例應用服務端開發(fā) 建立示例應用 首先通過 Eclipse 建立一個 Maven 工程,如圖 2 所示,在此對話框中,請勾選”Create a simple project (skip archetype selection)”,這個選項會直接通過屬性配置建立 Maven 工程,而不會使用 archetype 機制,本文的示例并不需要使用 archetype 機制。在 Advanced 選項里面,為 Name template 填入值,它將會作為新建工程的工程名。 圖 2. 新建 Maven 工程 下面配置剛建立的 Maven 工程的基本 POM 屬性,如圖 3 所示,主要有以下幾個屬性: - Group Id:該 Maven 產品的組織名稱,類似于 Java 的包名
- Artifact Id:該產品的產品名
- version:版本號
- Packaging:該產品的打包方式。這個屬性比較重要,由于我們需要建立一個 web 應用,這里的打包方式應選擇 war。該屬性還有其他選項,如 jar,ear 等。
圖 3. Maven 工程的基本屬性 等待示例工程創(chuàng)建完畢,Maven 會創(chuàng)建一個初始目錄結構,如圖 4 所示。這是一個典型的 Maven web 應用的目錄結構,其中,src/main 存放主程序源文件,src/test 存放測試文件。在 src/main 中有兩個 classpath 目錄:Java 和 resources,其中 Java 存放 Java 類源文件,resources 存放一些需要處于 classpath 中的資源文件。src/main/webapp 為 web 應用的根目錄。在工程目錄上右擊,選擇 Maven->Update Project Configuration。M2Eclipse 插件會為 WTP 創(chuàng)建必要的配置,使得該 web 應用能夠通過 WTP 部署到 web server 上。 圖 4. 初始目錄結構 添加工程依賴 下面我們需要為剛建立的工程添加依賴,本示例需要掩飾 Tuscany 的一些 Web 2.0 功能,因此需要添加 Tuscany 的基本庫以及一些 Web 2.0 擴展庫。雙擊工程根目錄中的 pom.xml,使用 POM 文件編輯器打開該文件,切換至 Dependencies 頁,添加必要的依賴。如圖 5 所示 圖 5. Maven 工程依賴 需要添加的工程依賴如表 1 所示 表 1. 示例應用工程依賴列表 groupId | artifactId | version | org.apache.tuscany.sca | tuscany-implementation-Java-runtime | 1.4 | org.apache.tuscany.sca | tuscany-binding-ws-axis2 | 1.4 | org.apache.tuscany.sca | tuscany-binding-rmi-runtime | 1.4 | org.apache.tuscany.sca | tuscany-host-webapp | 1.4 | org.apache.tuscany.sca | tuscany-binding-jsonrpc-runtime | 1.4 | SCA 組件開發(fā) 如前文所述,本示例需要開發(fā)一個用于計算股票市盈率的組件服務,該服務需要導入兩個外部服務接口,一個用于獲取當前股價,另一個用于獲取股票的每股 收益,當然在本示例中這兩個外部服務也是用 Tuscany 建立的應用,返回一定的示例數據,此處不詳述,請參見本文附件里面的源碼。 首先需要導入外部服務的接口,獲取當前股價的服務為 web service,其 wsdl 如圖 6 所示,Endpoint 為:http://localhost:8085/services/StockQuoteService 圖 6. stockQuote.wsdl 為了在 Java 實現里能調用該 web service 提供的服務,需要生成該 wsdl 對應的 Java 接口,該 Java 接口可以由一般的 wsdl2Java 的程序來實現,Tuscany 也提供了一個 wsdl2Java 的插件,該插件除了生成 Java 接口外,還在接口上添加了一些 Tuscany 的 annotation。本文示例中的 wsdl 比較簡單,它生成的接口 org.kth.demo.ws.StockQuote 如清單 1 所示。其中 @Remotable 是一個標準的 SCA annotation,它用于表示當前接口可以進行遠端調用。 清單 1. StockQuote 接口 import org.osoa.sca.annotations.Remotable; @Remotable public interface StockQuote { public float getQuote(String company, String date) throws Java.rmi.RemoteException; } <a name="_代碼清單與預格式化文本"/> | 獲取每股收益的服務有一個 Java rmi 提供,其接口 org.kth.demo.rmi.EarningPerShare 如清單 2 所示。 清單 2. EarningPerShare 接口 import org.osoa.sca.annotations.Remotable; @Remotable public interface EarningPerShare { public float getEarningPerShare(String company, String date) throws Java.rmi.RemoteException; } | 下面定義需要實現的 SCA 組件的接口 org.kth.demo.StockPE,該接口接受 2 個參數:公司名稱和日期,返回某個上市公司某一天的靜態(tài)市盈率。該接口的代碼如清單 3 所示。其中 @Service 也是一個標準的 SCA annotation,用于表示基于該接口的 SCA 組件可以暴露為服務。 清單 3. StockPE 接口 import org.osoa.sca.annotations.Remotable; import org.osoa.sca.annotations.Service; @Remotable @Service public interface StockPE { public float getPERatio(String company, String date) throws Java.rmi.RemoteException; } | 下面為 StockPE 組件開發(fā)具體的 Java 實現,新建 Java 類 org.kth.demo.impl.StockPEImpl,寫入如清單 4 所示的代碼。在該段代碼中,@Service(StockPE.class) 聲明了該 Java 實現是作為 SCA Interface StockPE 的實現??梢钥吹?,對于 stockQuote 和 earningPerShare 都有 get 和 set 函數,這里是將這兩個 Reference 暴露出來,讓 Tuscany 框架在運行時進行依賴注入。在運行時,Tuscany 會根據具體的 Reference 類型創(chuàng)建特定的 Java 實現,比如 web service 或者 RMI 的 Stub,并且將這些實現注入該 SCA 組件的實現。getPERatio 為具體的實現方法,它首先獲取外部服務的 reference,然后調用外部服務獲取當前股價和股票的每股收益,然后計算出市盈率并返回。 清單 4. StockPEImpl 實現 import org.kth.demo.StockPE; import org.kth.demo.rmi.EarningPerShare; import org.kth.demo.ws.StockQuote; import org.osoa.sca.annotations.Service; @Service(StockPE.class) public class StockPEImpl implements StockPE { private StockQuote stockQuote; private EarningPerShare earningPerShare; public StockQuote getStockQuote() { return stockQuote; } public void setStockQuote(StockQuote stockQuote) { this.stockQuote = stockQuote; } public EarningPerShare getEarningPerShare() { return earningPerShare; } public void setEarningPerShare(EarningPerShare earningPerShare) { this.earningPerShare = earningPerShare; } /* (non-Javadoc) * @see org.kth.demo.QuotePE#getPERatio(Java.lang.String, Java.lang.String) */ public float getPERatio(String company, String date) throws RemoteException { float quote = stockQuote.getQuote(company, date); float earning = earningPerShare.getEarningPerShare(company, date); if (earning != 0) return quote / earning; else return 0; }} | SCA 組件配置 在完成 SCA 組件的 Java 實現之后,我們需要配置具體的 SCA 環(huán)境,在 Tuscany 應用中,SCA 的配置主要放在 .composite 文件中,一個 .composite 文件實質上是一個 SCA Composite 的 XML 配置,這些 .composite 文件一般位于 classpath 下的 META-INF/sca-deployables 路徑中,Tuscany 的 runtime 在初始化的時候會在 classpath 中搜索所有 .composite 文件,并且將它們定義的 SCA Composite 初始化。本文的示例需要定義一個 SCA Composite:InvokeDemoComposite,我們在 src/main/resources/META-INFO/sca-deployables 下建立 XML 文件 invokeDemo.composite,清單 5 先列出此配置文件的內容,后面會對其中細節(jié)一一介紹。 清單 5. composite 配置文件 <?xml version="1.0" encoding="UTF-8"?> <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://tuscany.demo.kth.org" xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" xmlns:dbsdo="http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0" name="InvokeDemoComposite"> <component name="StockPEComponent"> <implementation.Java class="org.kth.demo.impl.StockPEImpl"/> <reference name="stockQuote"> <interface.wsdl interface="http://ws.demo.kth.org#wsdl.interface(StockQuote)"/> <binding.ws uri="http://localhost:8085/services/StockQuoteService"/> </reference> <reference name="earningPerShare"> <tuscany:binding.rmi host="localhost" port="8099" serviceName="EarningPerShareService" /> </reference> </component> <service name="StockPE" promote="StockPEComponent/StockPE"> <interface.Java interface="org.kth.demo.StockPE"/> <tuscany:binding.jsonrpc /> </service> </composite> | 首先看一下這個文件中需要定義的 namespace, - tagetNamespace:用于表示此 SCA Composite 的名稱空間,在 SCA 部署的時候,contribution 文件中的 composite 部署配置應于這個名稱空間一致。
- xmlns:tuscany:Tuscany 的特有 Binding 擴展的名稱空間,由于 Tuscany 是一個開放式框架,它的 binding 擴展有多種類型,其中有些是 SCA 規(guī)范中定義的擴展,這些擴展不需要名稱空間,有些是 Tuscany 自己定義的擴展,這些擴展就需要使用 xmlns:tuscany 定義的名稱空間,Web 2.0 擴展大多屬于這種類型。用戶也可以自己開發(fā)擴展,那使用的時候就需要引入用戶自定義的名稱空間。
- xmlns:dbsdo:Tuscany 的特有 databinding 擴展的名稱空間,一般來講每個 binding 都有自己默認的 databinding,比如 web service 的 binding 就會默認使用 JAXB 的 databinding,打多數情況下不需要特定指出 databinding 的類型,但是不排除某些特殊情況下需要用戶特別指出 databinding 的類型,此時就需要加上這個名稱空間。
接下來看 SCA Component 的配置,component 元素就是配置一個 SCA Component 的聲明,它有一個在同 composite 必須唯一的名稱,每一個 component 都必須有一個 implementation 元素,這里我們采用 Java 實現 Component,因此需要配置 implementation.Java,這個配置會制定一個 Java 類的全名作為此 Component 的實現。 Component 中可以配置 Service 以及 Reference,Service 是定義該 Component 暴露出的一些服務,Reference 是定義該 Component 需要引用的其他外部服務。在 Reference 中,需要指定該引用的接口(interface)和綁定(binding),在本文示例中,我們引入了兩個外部服務,因此需要定義兩個 Reference,其中一個 Reference 用來引用通過 web service 暴露的查詢股價的服務,在它的定義里需要制定 wsdl 方式的 interface,以及該 web service 的 endpoint 地址。另一個 Reference 用來引用通過 Java RMI 暴露的查詢股票每股收益的服務,它需要指定 Java RMI 的主機名,端口號,以及服務名。 最后看一下 SCA Component 暴露給 Web 2.0 應用的服務。通過一個外部的 service 定義,該 Component 可以指定一個在 composite 層暴露的服務。此服務的名稱必須與用 @Service 指定的接口名一致,在該服務的定義里也必須指定 interface 和 binding,其中 binding 采用 jsonrpc 方式,便于在 web client 端使用 ajax 調用,注意此處必須加上 tuscany 的名稱空間。 通過這個配置文件將之前開發(fā)的 Java 實現封裝成了 SCA Component,并使其可以在 Tuscany 中運行。到目前為止創(chuàng)建的實現和配置文件應該組成如圖 7 所示的目錄結構。 圖 7. 服務端組件目錄結構
示例應用客戶端開發(fā) 前文已經講述了如何利用 Tuscany 創(chuàng)建出服務端的 SCA 組件,接下來本章講述如何以 Web 2.0 的方式消費這些 SCA 組件。 Web 配置 要在 Web 應用中調用 SCA 組件,需要對 Web 應用進行一定的配置,主要是配置 SCA 的 contribution,SCA Contribution 是將 SCA 組件在 JAVA EE 容器或者 Web 容器部署的部署信息。在 src/main/webapp/ META-INF/ 下建立文件 sca-contribution.xml,并寫入如清單 6 的內容。該文件的內容比較簡單,就是聲明一個 SCA Composite,deployable 元素就是用做這樣的聲明,InvokeDemoComposite 為之前定義的 Composite 的名稱,sample 為其名稱空間,這里的定義必須與與 composite 配置文件中定義的一致。 清單 6. SCA Contribution 文件 <contribution xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:sample="http://tuscany.demo.kth.org"> <deployable composite="sample:InvokeDemoComposite"/> </contribution> | JsonRPC 示例 web 頁面開發(fā) 下面我們創(chuàng)建利用 JsonRPC 方式調用 SCA 組件的示例。我們的目標是創(chuàng)建一個 web 頁面,該頁面展示一張列表,列出中國石油,中國石化和工商銀行三家公司的市盈率。在 src/Java/webapp 中創(chuàng)建 html 頁面 StockDemoRpc.html,并且寫入如清單 7 的代碼。 清單 7. StockDemoRpc.html 頁面內容 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Tuscany RPC Stock Demo</TITLE> <script type="text/Javascript" src="SCADomain/scaDomain.js"></script> <script type="text/Javascript" src="jquery/jquery.js"></script> <script language="JavaScript"> window.onload = function(){ var companies = [" 中國石油 " , " 中國石化 " , " 工商銀行 "]; $.each(companies, function(){ var pe = StockPE.getPERatio(this , "2009-03-25").toFixed(2); $(".header").append("<th>" + this + "</th>"); $(".content").append("<td>" + pe + "</td>"); }) } </script> </head> <body> <h2> 市盈率列表 </h2> <table border="1" cellpadding="2" cellspacing="2"> <tr class="header" /> <tr class="content" /> </table> </body> </html> | 下面分析這個文件的內容,首先需要引入必要的 Javascript 庫,其中 scaDomain.js 比較重要,它不需要被導入到 webapp 中,是 Tuscany 運行時由 Servlet 動態(tài)生成的,它是 Tuscany 為客戶端創(chuàng)建的 Javascript 庫合集。頁面的主體是一個 <table>,它有兩行,一行顯示公司名稱,另一行顯示對應公司的市盈率值。在 window.onload 里面實現表格的生成工作,在這個方法里面,我們看到 StockPE.getPERatio 為獲取市盈率的操作,其中 StockPE 是在 scaDomain 中生成的專門用于做 JsonRPC 的 Javascript 對象,它封裝了 JsonRPC 所需要的 Ajax 調用操作,可以看作是服務端的 SCA 組件在 Javascript 客戶端的 Stub。在獲取到市盈率值后利用 HTML 操作生成整個表格 部署運行 下面需要將之前開發(fā)的服務端組件以及客戶端代碼打包部署到服務器上,圖 8 顯示了需要部署的服務器上的工程的目錄結構,由于我們使用了 M2Eclipse 可以直接在 Eclipse 中建立一個 Server,這里使用 Tomcat 的 Server,在 Tomcat Server 上右擊選擇 Add or Remove Projects,將 kth-tuscany-demo-invoke 工程加入到此 server 中,然后再右擊 Server,選擇 Start。等待 Server 啟動,如圖 9 所示。 圖 8. 部署目錄結構 圖 9. 安裝部署 運行結果 JsonRPC 示例的運行結果如圖 10 所示,該列表分別列出了三家公司的靜態(tài)市盈率值。 圖 10. JsonRPC 示例運行結果 Dojo 示例 上一個示例展示了在客戶端頁面中直接使用 Tuscany 生成的 JsonRPC 的 Javascript 對象來調用 SCA Component,在本例中豐富一下客戶端的內容,使用 dojo 框架顯示一個柱狀圖,來更直觀地展現中國石油,中國石化和工商銀行幾家公司的市盈率,可以有一個直觀的比較。 Web 頁面開發(fā) 在 src/Java/webapp 中創(chuàng)建 html 頁面 StockDemoDojo.html,并且寫入如清單 8 的代碼。 清單 8. StockDemoDojo.html 頁面內容 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Tuscany Dojo Stock Demo</TITLE> <script src="dojo/dojo/dojo.js" type="text/Javascript" djConfig="parseOnLoad: true ,usePlainJson:true"></script> <script src="dojo/dojo/custom/dojo-core.js" type="text/Javascript"></script> <script src="dojo/dojo/custom/graphics.js" type="text/Javascript"></script> <script language="JavaScript"> dojo.require("dojo.rpc.JsonService"); var PEService = new dojo.rpc.JsonService("StockPE?smd"); var companies = [" 中國石油 " , " 中國石化 " , " 工商銀行 "]; var labels = []; var pes = []; function renderChart(){ var chartNode = dojo.byId("chart"); var chart = new dojox.charting.Chart2D(chartNode); chart.addAxis("x", {fixLower: "minor", fixUpper: "minor", natural: true, labels:labels}); chart.addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}); chart.addPlot("default", {type: "ClusteredColumns", gap: 20}); chart.addSeries("PE", pes , {stroke: {color: "blue"}, fill: "lightblue"}); chart.render(); } function init() { dojo.forEach(companies, function(item , i){ labels.push({text : item , value : i + 1}); var pe = PEService.getPERatio(item , "2009-03-25").addCallback(function(res){ pes.push(res); if(pes.length == 3) renderChart(); }); }) } dojo.addOnLoad(init); </script> </head> <body> <h2> 市盈率圖表 </h2> <div id="chart" style="width:360px;height:200px"/> </body> </html> | 下面分析這個文件的內容,首先導入必要的 js 庫,主要是 Dojo 的庫,除了 dojo.js 以外導入了兩個通過自定義打包生成的 dojo 文件,本文的附件中包含了這些 dojo 文件,感興趣的讀者可以參考 dojo 的文檔了解自定義打包的內容。這里不再需要引入 scaDomain.js,因為 Dojo 有內置的 JsonRPC 實現,并且 Tuscany 除了在 scaDomain.js 里面提供 JsonRPC 的接口以外,還通過 Servlet 提供另一種 JsonRPC 接口,即以 ?swd 結尾的 JsonRPC 描述,dojo 的 JsonRPC 實現可以解析這種描述并且生成具體的 Javascript 對象。這個 web 頁的主體就是一個空的 div,dojo 會在這個 div 上生成我們所需要的圖表,下面主要分析頁面中的 Javascript 腳本。 首先通過 dojo.require 將 dojo 的 JsonRPC 實現類導入,然后創(chuàng)建 JsonRPC 的 Service:PEService,此 service 與之前的 JsonRPC 的 Stub 有所不同,它是采用異步調用的方式與服務端交互,而不是此前示例中的同步方式。PEService.getPERatio 方法會返回另一個 Javascript 對象,該對象可以添加 callback 來完成異步操作的響應。我們在 callback 中接收返回的數據,并且最后一個數據接收到之后生成圖表。 renderChart 為生成圖表的操作,主要是通過 dojox.charting.Chart2D 來生成一個二維柱狀圖,這里的實現細節(jié)不再細述。請有興趣的讀者參考 dojo 文檔 運行結果 此例的安裝配置界面與 JsonRPC 示例中類似,其運行結果如圖 11 所示,通過柱狀圖把三家公司的市盈率顯示出來,有一個直觀的比較。 圖 11. 市盈率圖表
總結 本文首先介紹了基于 SCA 進行 Web 2.0 開發(fā)的意義,然后分析了 Tuscany 的基本架構和擴展,接著通過一些示例簡單地展示了利用 Tuscany 開發(fā) Web 2.0 應用的典型過程。 在本文的示例中,SCA 作為一個整合框架,整合了基于 web service 和 Java RMI 的服務,并且將其暴露成 Json 服務以便于客戶端的 Javascript 進行調用。這樣的例子很典型了展示了 Tuscany 將各種平臺上的服務整合并且以 Web 2.0 的方式暴露給客戶端的特性和功能。其實 Tuscany 的 Web 2.0 特性還不至于此,它還有其他很多基于 Web 2.0 技術的擴展,如 widget,RSS,Atom 等等,感興趣的讀者可以通過分析 Tuscany 框架的樣例應用來進一步了解。
下載 描述 | 名字 | 大小 | 下載方法 | 本文代碼示例 1 | kth-tuscany-demo-invoke.zip | 1.2 MB | HTTP | 本文代碼示例 2 | kth-tuscany-demo-services.zip | 17 KB | HTTP |
參考資料 學習 獲得產品和技術 - 下載 IBM 產品評估版,獲得來 自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的應用程序開發(fā)工具和中間件產品。
討 論
關于作者 | | | 方偉,IBM CDL 軟件工程師,在 SOA Design Center 從事電信行業(yè)的解決方案開發(fā),對 Web2.0,SCA,Mashup 等技術較為熟悉,對多種 Java EE 輕量級框架及 Javascript 框架有熟練應用。對 RIA,UE 等方向有濃厚興趣。 | |