1. 前言
??? 在一些多功能服務(wù)系統(tǒng)的開發(fā)過程中,,我們遇到了這樣的問題:作為體系框架的應(yīng)用程序和基于瀏覽器和WEB頁面的網(wǎng)絡(luò)服務(wù)很難溝通起來,。有什么方法能夠把這兩種傳統(tǒng)意義上大相徑庭的開發(fā)方式高效、穩(wěn)定地集成,,以盡可能地發(fā)揮其各自的優(yōu)勢呢,?
2. 問題與思考
??? 運行在瀏覽器上的HTML語言有著高效,靈活的優(yōu)勢,,在JAVA程序中,,通過內(nèi)嵌" title="內(nèi)嵌">內(nèi)嵌開放式的JAVA瀏覽器Mozilla,用WEB頁面的形式實現(xiàn)一些用戶操作界面,,能夠節(jié)約很多開發(fā)的精力,。但瀏覽器的編程接口一般限于導(dǎo)航,對網(wǎng)頁內(nèi)部的構(gòu)件和數(shù)據(jù)的訪問支持不夠,。當主程序" title="主程序">主程序中采集到的數(shù)據(jù)參數(shù)需要經(jīng)由HTTP協(xié)議提交到數(shù)據(jù)遠程服務(wù)器,,并由瀏覽器顯示返回的結(jié)果頁面時,如何將這些參數(shù)傳遞給瀏覽器的提交頁面,,同時又使主程序能得到遠程返回的數(shù)據(jù),,便成為了一個需要解決的問題。
圖1. 問題所在——主程序與瀏覽器頁面的數(shù)據(jù)傳遞
??? 傳統(tǒng)的基于瀏覽器的Web服務(wù)模式是:瀏覽器與服務(wù)器直接建立連接關(guān)系,,服務(wù)器直接返回Web頁面,。如果嘗試打破這種模式,由主程序提交數(shù)據(jù),,服務(wù)器以XML文件的形式返回必要的結(jié)果數(shù)據(jù),,交由程序處理,那么數(shù)據(jù)共享的問題就得以解決。同時根據(jù)預(yù)先制定的HTML模板生成本地頁面文件,,再通過瀏覽器向用戶顯示,,也能達到與遠程頁面相同的效果。
圖2. 問題的解決——另一種數(shù)據(jù)傳輸模式
?
3.基本原理
??? 由JAVA實現(xiàn)程序的主框架,,內(nèi)嵌Mozilla的WebClient瀏覽器組件,。發(fā)生服務(wù)請求時,在程序中利用Http網(wǎng)絡(luò)對象將參數(shù)以Post的方式提交至遠程Servlet數(shù)據(jù)服務(wù)器,。服務(wù)端" title="服務(wù)端">服務(wù)端處理請求后返回一個包含結(jié)果數(shù)據(jù)的XML頁面,。客戶端" title="客戶端">客戶端得到XML文件后使用DOM對象解析出結(jié)果數(shù)據(jù),并根據(jù)預(yù)先設(shè)計的HTML頁面模板,,通過關(guān)鍵字替換的方式在本地生成結(jié)果頁面,。最后在程序中調(diào)用瀏覽器的SetURL接口指定瀏覽器打開本地頁面。
4.JAVA中的Http請求
??? Sun的jdk1.3.1中,,java.net包提供了一些網(wǎng)絡(luò)訪問功能的對象,。其中網(wǎng)絡(luò)地址對象URL和連接對象HttpURLConnection類用于建立一個遠程的Http訪問。
???下面是它們的一些主要方法及描述,。
URL類:
?
??? 下面是使用這兩個對象對網(wǎng)絡(luò)上的Servlet服務(wù)器進行數(shù)據(jù)查詢的例子,。
??? 使用查詢腳本的地址描述作為參數(shù)創(chuàng)建一個URL對象實例,調(diào)用URL的openConnection方法打開連接,。此時程序試圖連接遠端并請求腳本服務(wù),,如成功即返回一個HttpURLConnection連接實例。
??? 用連接實例的getOutputStream方法取得它的輸出流,,在輸入?yún)?shù)字串" title="字串">字串后,,服務(wù)器從后臺數(shù)據(jù)庫中查詢出結(jié)果數(shù)據(jù),組成XML字符流并輸出,,客戶端由getInputStream得到的輸入流取得并保存XML文件,。寫入?yún)?shù)前可以通過setRequestMethod方法設(shè)置提交方法,建議在參數(shù)較復(fù)雜時使用“POST”方法,。根據(jù)HTML的協(xié)議規(guī)范,參數(shù)之間用“&”號隔開,。
??? 以下是主要程序代碼,,已通過jdk1.3.1調(diào)試。
//指定遠程的查詢服務(wù)腳本地址
URL url = new URL("http://192.168.0.176:7001/WebApp/BasicInfQuery");
//打開Http連接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
//提交參數(shù)pid和name
PrintWriter out = new PrintWriter(connection.getOutputStream());
String pid = "pid="+URLEncoder.encode(“97133225");
String name = "name="+URLEncoder.encode("yang");
out.println(pid+“&”+name);
out.close();
//讀取查詢服務(wù)返回的數(shù)據(jù)
BufferedReader in
= new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
}
5.XML數(shù)據(jù)結(jié)構(gòu)定義和文件解析
??? 以一個學生信息查詢?yōu)槔?,為XML作如下的數(shù)據(jù)結(jié)構(gòu)定義:以“學生信息”為根,,“學生”為節(jié)點,每個節(jié)點有一個屬性“性別”,,及“姓名”,、“年齡”、“電話”三個子節(jié)點。
??? 客戶端程序在提交查詢后,,得到服務(wù)端程序動態(tài)生成的XML文件,,然后利用JAVA下的DOM對象將文件中的數(shù)據(jù)解析出來?!拔臋n對象模型”DOM是W3C制定的XML數(shù)據(jù)概念描述,,它允許開發(fā)者在 XML 結(jié)構(gòu)內(nèi)引用、檢索和更改 XML 結(jié)構(gòu)中的各項,。在Sun的jdk1.4.1中包含了XML解析接口javax.xml.parser和DOM對象,,它們對XML文件的處理提供了很完整的一套接口。
??? DOM在處理XML文件之前,,首先將XML文件解析成對象化的文檔(Document),。javax.xml.parsers中的DocumentBuilder通過parse方法對一個XML文件進行解析,生成一個Document對象。簡單要代碼如下:
//為解析XML作準備,,創(chuàng)建DocumentBuilderFactory實例,指定DocumentBuilder
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
//解析指定的XML文件,,創(chuàng)建Document對象
Document doc = db.parse(inFile);
??? 解析后的Document將所有數(shù)據(jù)以父子的節(jié)點層次結(jié)構(gòu)裝入內(nèi)存,這些節(jié)點可以是元素,、文本,、屬性或其它節(jié)點類型。節(jié)點元素對象Element提供了對其元素的值和子節(jié)點的訪問,。下面是Element對象的一些方法定義和描述,。
?
方法?描述???
GetAttribute(String name)?取得指定屬性名的屬性值???
GetElementsByTagName(String name)?取得指定節(jié)點名的子節(jié)點隊列?
getElementsByTagName 返回的NodeList對象實質(zhì)是一個Element的隊列,其item(n)方法返回其中的第n個Element對象,。
?以下一段代碼用于讀取Document對象中樹形節(jié)點的值:
Element root = doc.getDocumentElement();
//取"學生"元素列表
NodeList students = root.getElementsByTagName("學生");
for (int i = 0; i < students.getLength(); i++)
{
?//依次取每個"學生"元素
?Element student = (Element) students.item(i);
?//取學生的性別屬性
?String sex = student.getAttribute("性別");
//取"姓名"元素,,其他類同
?NodeList names = student.getElementsByTagName("姓名");
?if (names.getLength() == 1) {
??Element e = (Element) names.item(0);
??Text t = (Text) e.getFirstChild();
??String name = t.getNodeValue();
?}
}
注:在Apache提供的XML開發(fā)工具包crimson的幫助下,DOM對象也能用于將一個Document的數(shù)據(jù)寫入XML文件,。在我們的數(shù)據(jù)服務(wù)器端,,因為生成XML文件相比較解析文件來的簡單,我們并沒有使用這一功能,,但在一些XML結(jié)構(gòu)較復(fù)雜的情況下,,使用一個清晰的文檔對象也是很有必要的。相關(guān)的資料可參考Apache網(wǎng)站上crimson的開發(fā)文檔,。
6.HTML模板定義和頁面的動態(tài)創(chuàng)建
??? HTML模板是在源碼中添加了一些自定義的標記(tag)的HTML文件,,這些tag用于在動態(tài)創(chuàng)建頁面時指示數(shù)據(jù)字串的插入位置。
??? 對于預(yù)先設(shè)計的HTML頁面,,以文本方式編輯他們的源碼,。在顯示數(shù)據(jù)的位置用自定義的tag作出標記,這些tag以一個在HTML語法中不常出現(xiàn)的特殊符號作為起始和終止符,,如”%”,,以它們的數(shù)據(jù)意義來命名,。例如姓名的tag定義為”%name%”,性別為”%sex%”,,類似,。下面是一個模板中部分代碼的舉例:
?姓名 %name%
?性別 %sex%
?年齡 %age%
??? 在創(chuàng)建頁面時,程序?qū)⒛0逡晕谋痉绞阶x入一個String類型變量中,,然后依次查找每個數(shù)據(jù)所對應(yīng)的tag的位置,,用表示數(shù)據(jù)的字串替換它。在Java中實現(xiàn)字串替換的代碼如下:
? public void ReplaceStr(String sTag, String sData){
??? int index;
??? while((index=sHTML.indexOf(sTag))>=0)
????? sHTML=sHTML.substring(0,index)+sData+sHTML.substring(index+sTag.length(),sHTML.length());
? }
??? 把所有定義的tag替換之后,,就創(chuàng)建出一個表示當前操作的結(jié)果數(shù)據(jù)的動態(tài)HTML頁面,。通過程序內(nèi)置的瀏覽器在本地打開這個HTML頁面,最終實現(xiàn)了將服務(wù)結(jié)果向用戶輸出,。
7.方法的優(yōu)缺點討論
優(yōu)點:
??? 成功解決了數(shù)據(jù)共享的問題,,因而極大地拓展了瀏覽器在服務(wù)系統(tǒng)開發(fā)中的應(yīng)用領(lǐng)域,從而能夠充分利用開發(fā)資源,,高效的開發(fā)出基于網(wǎng)絡(luò)的數(shù)據(jù)服務(wù),。
??? 以XML作為數(shù)據(jù)載體,直接以數(shù)據(jù)的形式返回結(jié)果,,可讀性強,,易于調(diào)試。
??? XML的體積較小,,可以減輕服務(wù)器和網(wǎng)絡(luò)的負擔,。
??? 方法不僅限于JAVA程序,在其他開發(fā)平臺上也可以通過類似的辦法實現(xiàn),。
??? 可以通過XSL擴展XML在瀏覽器上的顯示功能,,省去創(chuàng)建動態(tài)網(wǎng)頁的步驟。
缺點:
??? 文本形式的XML存在著不小的安全問題,,對一些機密的數(shù)據(jù)需要加密后傳輸,。
??? 將HTML頁面存放在客戶端的形式在多臺客戶機的情況下會對維護和更新頁面造成一定的難度,可以考慮在客戶端建立一個被動式的遠程頁面更新服務(wù),。
8.結(jié)束語
??? 因為篇幅有限,,這里只舉了一個最簡單的例子,但我們?nèi)匀荒荏w會到在應(yīng)用程序的Web服務(wù)中使用瀏覽器所帶來的便捷和強大的功能,。這種方法突破了數(shù)據(jù)訪問上的束縛,,能夠最大限度的發(fā)揮各自的優(yōu)勢,提高了軟件的整體性能,,又節(jié)約了寶貴的開發(fā)時間和精力。
參考文獻
1.Mark Birbect 等著,,裴劍鋒 等譯,,XML 高級編程(第2版),,2002
2.Tom Myers Alexander Nakhimovsky 著,王輝 等譯,,Java XML編程指南,, 2001
3.Bruce Eckel 著,侯捷 譯,,Java編程思想(第2版),,2002
4.Dan Becker, Explore online XML data with Java programming,,IBM developerWorks journal.,,August 2002
?