XML——連接SQL和Web程序的橋樑

XML——連接SQL和Web程序的橋樑

摘要
過去幾年XML技術作爲Internet上交換信息的格式受到了極大的歡迎。今天XML常常被描述成一種孤立的技術,但它最初誕生的時候卻是一種(介於HTML和SGML之間的)Internet技術。本文討論XML如何被用作數據庫和最終用戶間的“通訊協議”。

當 前最流行的關係數據庫管理系統用SQL查詢語言來與數據打交道。雖然面向XML(XML-oriented)的數據庫已經面市,卻不常見。而XML如此流 行,關係數據庫開發者也在爲產品增加XML兼容性的過程中學習進步。本文考察其中一種途徑:讓數據庫返回XML。示範代碼中用到了一個Oracle數據 庫,它被假定是XML兼容的,能處理XML數據。

本文分爲兩部分。第一部分預備和Oracle數據庫打交道的Java代碼:提交一個SQL查詢,獲取一個XML輸出;第二部分專注於一個web程序:將從數據庫獲取的XML數據輸出爲HTML文本。

要求
本文中用到下列軟件:
BEA WebLogic Platform 8.1 with SP4 ——作應用程序服務器。
Oracle 10g Database Server ——作數據庫服務器。你可以用不同版本的服務器來試驗代碼;據我們所知,本方案不需要特定的版本。
Oracle XML-SQL Utility (XSU) ——XSU是一組充當PL/SQL包裝(wrapper)的Java類,它允許查詢返回XML包裝起來的結果集或對象。
Oracle XML Parser, Version 2 ——Oracle的基於Java校驗XML有效性的解析器(parser),支持XSL。一般來講XSU和XML解析器是Oracle Developer Suite的一部分。
本文中的代碼在微軟Windows XP系統上運行,但只需要很小的改動也應該能在任何操作系統上正確工作。
我們假定讀者是有經驗的Java開發者,熟悉BEA WebLogic Server,並且有JDBC編程經驗。

準備連接池(Connection Pool)和數據源
如果你熟悉JDBC連接池和數據源的配置,請跳過這一節。
首 先需要配置連接池和數據源。代碼稍後會用JNDI來獲取數據源,這需要一點配置。我們要配置一個JDBC連接池來保持和數據庫的連接。登入 WebLogic的控制檯並選擇Service Configurations -> JDBC -> Connection Pools節點。
現在選擇“Configure a new JDBC Connection Pool...”以創建一個新的連接池,在接下來的畫面裏選擇數據庫類型和驅動(圖1)。


圖1. JDBC連接池:選擇數據庫

可以看到多種不同數據庫可供選擇。我們需要的數據庫類型(Database Type)是Oracle,並且將使用BEA的Oracle Driver(Type 4)。然後點“Continue”按鈕定義連接屬性(圖2)。

image
圖2. JDBC連接池:連接屬性

在這個畫面中,爲JDBC連接池選擇一個名字,並設置其它諸如數據庫名和主機名、連接端口和口令等數據庫參數。
這 裏並不創建一個新數據庫和一組表,我們將使用Oracle的示例SCOTT/TIGER模式(schema)和EMP表。幾乎每個Oracle安裝中都有 這個示例,因此不需要你再去配置。如果沒有EMP表或者這個表是空的,可以用Oracle目錄下的/sqlplus/demo/demobld.sql腳 本重建這個表並裝入數據,還可以用/sqlplus/demo/demodrop.sql刪除原有的值。
配置好這些參數之後點“Continue”(圖3)。

image
圖3. JDBC連接池:連接測試

一 般情況不必對這一頁做任何改動,這是一個連接測試頁(可以點“Skip This Step”跳過)。WebLogic Server顯示了驅動類名、(JDBC驅動使用的)URL和身份驗證(用戶名和密碼)以供覈對。複覈完這些參數後準備測試,點“Test Driver Configuration”按鈕,如果一切正確,將看到“Connection Successful”的信息。最後點“Create and deploy”按鈕完成JDBC連接池配置。
完成了JDBC連接池的工作,現在我們需要創建相應的數據源。回到WebLogic Server控制檯的主頁,按照這個順序選擇:Service Configurations -> JDBC -> Data Source。在接下來的畫面中點擊“Configure a new JDBC Data Source”鏈接,將看到數據源配置成功頁(圖4)。


圖4. 數據源配置成功頁

要 定義JDBC數據源名稱和能找到數據源的地方——JNDI路徑。務必記住JNDI路徑,稍後將用它來建立一個與我們代碼的連接。接下來選擇 “Continue”,然後選擇正確的連接池和數據源關聯。選中剛剛創建的連接池,再點“Continue”,下一頁允許你選擇部署數據源的服務器和簇。 從列表裏選中需要的一個,接着點“Create”。數據源已經創建好,我們準備寫代碼了。


準備獨立(Stand-Alone)Java程序的環境
讓 我們給即將編寫的小客戶程序準備一個環境。爲了能執行SQL查詢和獲取XML數據作爲輸出,將用到Oracle XML-SQL utility (XSU),需要配置環境變量CLASSPATH指向Oracle XML-SQL Utility的庫(library)和Oracle XML解析器。一般情況下XSU可以在Oracle的目錄/rdbms/jlib/xsu12.jar找到,XML 解析器在/lib/xmlparserv2.jar。還有我們在使用JNDI,需要在CLASSPATH中包括weblogic.jar文件,一般在 WebLogic Server的安裝目錄下:/bea/weblogic81/server/lib/weblogic.jar。
典型的CLASSPATH 看起來會像下面這樣:

CLASSPATH=c:/Program Files/java/jdk1.5.0_01/lib;.;
  C:/DevSuiteHome/rdbms/jlib/xsu12.jar;
  C:/DevSuiteHome/lib/xmlparserv2.jar;
  C:/bea/weblogic81/server/lib/weblogic.jar;


考察獨立Java程序的代碼
在 展示代碼前,注意到Oracle中有兩種處理XML的方法是有意義的。二者的區別很大,你應該採用適合你手頭任務的辦法。第一種辦法是用Oracle的 XSU,允許從任何SQL查詢返回XML;第二種辦法是用Oracle的XMLType列類型(column type)。

XMLType 列允許將XML當做數據庫中的一種本地數據類型。因此,這些列可以像其它類型的列一樣參與查詢Consequently。Oracle提供了 XMLTYPE()函數來創建一個XMLType數據對象,同時還提供了其它處理這個數據類型的函數,比如XMLELEMENT()和XMLAGG()。 從WebLogic Server的在線文檔(The Oracle Driver)或技術網站(Oracle Technology Network)可以讀到關於這種辦法的說明和示例。本文將專注於使用XSU的方法。
下面是在Oracle數據庫上執行SQL查詢併產生XML輸出所需要的全部代碼(oraxml.java)。

1. import javax.naming.*;
2. import javax.sql.*;
3. import java.sql.*;
5. import oracle.xml.sql.query.*;

5. public class oraxml
6. {
7.        public static void main(String args[]) throws SQLException, NamingException
8.        {
9.                String tabName = "emp";
10.                int maxRows = 3;

11.                Context ctx = new InitialContext ();
12.                DataSource ds = (DataSource) ctx.lookup ("MyOra");

13.                Connection conn = ds.getConnection ();

14.      OracleXMLQuery qu = new OracleXMLQuery (
                         conn, "select EMPNO, ENAME from " + tabName);
15.                qu.setMaxRows (maxRows);
16.                qu.setRowsetTag ("EMPLOYERS");
17.                qu.setRowTag ("PERSON");

18.                String xmlString = qu.getXMLString();

19.                System.out.println (xmlString);

20.                conn.close ();
21.         }
22. }


這 段代碼很簡單。11-12行獲取一個JNDI名稱爲MyOra的數據源;13和20行分別建立和關閉連接;最有意思的是14-18行執行了一個所謂的 “XML查詢”;從技術上講,這是一個經XSU轉換爲XML的SQL查詢;14行初始化查詢;15-17行設置XML文檔的結構,15行設定返回的最大行 數不超過maxRows,16和17行設定文檔的根元素(root element)和項目分隔符(item delimiters);18行生成一個XML文檔並將其放在xmlString變量中。就像你看到的這樣,代碼很簡單易懂。(英文編者注:注意,這不是 成品代碼。最後應該在一個finally語句的括號中關閉連接。)

別忘記這段代碼中用到了JNDI。作爲一個獨立的Java程序,必須安 排一個命名提供者(naming provider)給它使用。我們將用WebLogic Server作爲提供者,配置方法首先要建一個jndi.properties文件,然後確保可以從環境變量訪問這個文件。如果CLASSPATH包含當 前目錄(.),就應該將jndi.properties文件放在當前目錄中。這是一個jndi.properties 文件的內容:

java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://localhost:7001


典型的編譯命令和運行結果像下面所展示的這樣(注意輸出被限制爲不大於maxRows):

C:/white/work/Java/xmlweb_src>javac oraxml.java

C:/white/work/Java/xmlweb_src>java oraxml
<?xml version = '1.0'?>
<EMPLOYERS>
   <PERSON num="1">
      <EMPNO>7369</EMPNO>
      <ENAME>SMITH</ENAME>
   </PERSON>
   <PERSON num="2">
      <EMPNO>7499</EMPNO>
      <ENAME>ALLEN</ENAME>
   </PERSON>
   <PERSON num="3">
      <EMPNO>7521</EMPNO>
      <ENAME>WARD</ENAME>
   </PERSON>
</EMPLOYERS>


現 在來稍微瞭解一點Oracle XML-SQL Utility的細節。可以看出,要執行SQL查詢並以XML格式輸出的話,這是一個相當順手的工具。當然,XSU絕非只有區區這麼一點功能。它可以動態 生成DTD(Document Type Definition,文檔類型定義),也可以執行簡單的轉換。XSU還可以生成XML文檔的字符串或DOM表示形式;將XML插入數據表或視圖;更新或 者刪除數據對象中的記錄;對一個給出的XML文檔生成一組複雜的嵌套XML文檔,並在平面表上創建對象視圖,然後在這些視圖上執行查詢,從而將這些文檔存 儲到一些關係表中。 從Oracle9i開始,XSU還支持對一個SQL查詢生成XML模式(schema)。還有,在生成過程中支持XML屬性。要完全搞懂如何用XSU的功 能來滿足你的需要請參考XSU的文檔。

用XML搭橋的好處
作 者想強調本教程中描述的XML轉換方法的優點並解釋爲什麼我們覺得它有用處。讀者或許會這樣問自己:“爲什麼要在這裏要使用XML?爲什麼將它稱爲‘橋 ’?”最好的辦法是通過一個小例子來解釋將XML作爲“橋”的優點。假設你現在有一個信息門戶網站,設計這個門戶的目的是爲了將新聞從SQL數據庫傳達到 最終用戶;這些用戶可能是任何人,包括使用WAP瀏覽器的移動電話用戶,或者裝備了現代瀏覽器的常規網上衝浪者。此外,你作爲信息的所有者,可以將這些新 聞轉售出去,而且新聞標題要不一樣,例如“News from the Acme, Corp.”和“Latest news from Big Company”或者別隨便的什麼。而要新聞本身卻是沒有改變,所以,技術上只是改變了“外觀(look and feel)”,那爲什麼要爲可能收到新聞的每一類最終用戶都寫一次代碼呢?

現在你發現自己需要某種既能接受SQL又能生成不同數據格式的 透明橋樑——這座橋是XML。你編寫的servlet向數據庫提出一個請求,接收XML輸出然後將一個XSL模板應用在之上,爲最終用戶生成一個頁面。這 樣需要改動的僅是一個XSL設計,沒有別的東西。沒有額外的代碼,不會浪費時間。想和其他人共享你的新聞?主意不錯,但何必允許別人訪問你的SQL數據 庫?又何必費神解釋數據庫的結構呢?——只要簡單地由基本的SQL查詢生成並共享XML就行了。

準備web程序的環境
到 這裏已經成功的編寫了獨立程序的代碼,能夠執行SQL查詢並生成XML文檔,我們完成了一半的工作。下一步要掌握WebLogic Server中將XML轉換成不同格式的選項,再構建一個web程序。現在有許多不同的處理XML流的技術,我們只關注其中一種——使用XSLT JSP標籤(tag)的方法。WebLogic Server提供這個小型JSP標籤庫就是爲了在JSP中方便地訪問XSTL轉換器。可以用它將XML文檔轉換爲HTML、WML,以及其它格式。首先看 看怎麼爲我們的web程序準備一個能夠利用這些工具好處的環境。

每有一個web程序就配置一次CLASSPATH不是個好辦法,所以必須 將要用到的Oracle數據庫jar文件放到web程序的/WEB-INF/lib目錄。同時還要從Oracle的主目錄把/rdbms/jlib/ xsu12.jar和/lib/xmlparserv2.jar兩個jar文件拷進去。WebLogic Type 4 JDBC驅動沒有和WebLogic Server一起被安裝在主目錄,但該驅動已經被自動加入到服務器的CLASSPATH中。

使用WebLogic XML標籤的過程十分簡單,並且在Developing XML Applications with WebLogic Server站點有很好的說明文檔。當然,爲了讀者更容易使用它,本文的二位作者會引導大家完成整個過程。

從WebLogic Server的安裝目錄將xmlx.zip文件拷到/bea/weblogic81/server/ext/。我們需要上述壓縮文件中的xmlx-tags.jar文件,在命令行下將這個文件放到web程序的/WEB-INF/lib目錄中:

C:/white/work/Java/xmlweb/xmlweb_war/WEB-INF/lib>pkzipc -extract 
  C:/bea/weblogic81/server/ext/xmlx.zip xmlx-tags.jar
PKZIP(R)  Version 4.00  FAST! Compression Utility for Windows
Copyright 1989-2000 PKWARE Inc.  All Rights Reserved. Shareware Version
PKZIP Reg. U.S. Pat. and Tm. Off.  Patent No. 5,051,745

Masking file attributes: Read-Only, Hidden, System, Archive

Extracting files from .ZIP: C:/bea/weblogic81/server/ext/xmlx.zip
    Inflating: xmlx-tags.jar


最後在WEB-INF目錄中還需要一個web.xml文件,用<taglib>標籤引用xmlx-tags.jar文件,像這樣:

<web-app> 
  <taglib>  
        <taglib-uri>xmlx.tld</taglib-uri>  
        <taglib-location>/WEB-INF/lib/xmlx-tags.jar</taglib-location>
  </taglib>
</web-app>


你可以查看本文附帶的示例WAR程序瞭解完整的例子(譯註:xmlweb.war)。

編寫web程序
本 節的目標是將我們學到的關於在獨立程序裏產生XML的知識應用到web程序的構建中,另外還要將XML轉換爲HTML。首先大致看看這個web程序需要哪 些文件。將用到的文件包括:/WEB-INF/web.xml (前面已經提到)、html.xls(XSL轉換器用來產生HTML文件的樣式表)以及index.jsp (這個web程序的主頁)。
首先考察樣式表。html.xls文件用來將轉換XML文檔以輸出HTML文檔。

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<table width="60%" border="1" cellspacing="0" cellpadding="1">
<tr>
<td align="center"><b>Employer No.</b></td>
<td align="center"><b>Employer Name</b></td>
</tr>

<xsl:apply-templates select="EMPLOYERS"/>

</table>


</xsl:template>

<xsl:template match="PERSON">

<tr>
<td align="center"><xsl:value-of select="EMPNO"/></td>
<td align="center"><xsl:value-of select="ENAME"/></td>
</tr>

</xsl:template>

</xsl:stylesheet>


正如在上面看到的,這個樣式表匹配根元素,創建一個表格,每當與PERSON元素的模板匹配就插入一行。利用這個文件我們可以從新的XML文檔生成HTML文檔。

我 們這個web程序的主要文件是index.jsp,一個平常的JSP文件。現在看看用到的JSP標籤,其中的XSLT JSP標籤語法基於XML。JSP標籤由一個開始標記、一個可選的主幹和匹配的關閉標籤組成。以<xslt>標籤爲例,擁有可選的(特定的) 參數。比如xml,標明想轉換的XML文件的位置(相對於web程序的文檔根目錄);比如stylesheet,標明用於轉換XML文檔的樣式表達的位置 ——同樣是一個相對於web程序文檔根目錄的位置。要了解標籤和可選項的更多信息,可以參考在線文檔(Using the JSP Tag to Transfer XML Data)中的“XSLT JSP Tag Syntax”一節。現在來看JSP文件:

1. <%@ taglib uri="xmlx.tld" prefix="x"%>

2. <HTML>
3. <HEAD>
4. <TITLE>:: An XML bridge ::</TITLE>
5. </HEAD>
6. <BODY>

7. <%@page import="java.sql.*"%>
8. <%@page import="oracle.xml.sql.query.*"%>
9. <%@page import="oracle.jdbc.*"%>

10. <%

11.        String tableName = "emp";
12.        int maxRows = 3;

13.        Context ctx = new InitialContext ();
14.        DataSource ds = (DataSource) ctx.lookup ("MyOra");

15.        Connection conn = ds.getConnection ();

16.        OracleXMLQuery qu = new OracleXMLQuery
      (conn, "select EMPNO, ENAME from " + tableName);

17.        qu.setMaxRows (maxRows);
18.        qu.setRowsetTag ("EMPLOYERS");
19.        qu.setRowTag ("PERSON");

20.        String xmlString = qu.getXMLString ();

21.        conn.close ();
22. %>

23. <x:xslt stylesheet="html.xsl">  
24. <x:xml>        
25.        <%=xmlString%>
26. </x:xml>
27. </x:xslt>

28. </BODY>
29. </HTML>


第1 行將稍後23行要用到的xmlx標籤庫包含進來。7至22行是從常規Java代碼到JSP代碼的轉換(沒有進行異常處理)。這裏的語法有些小變化,此外沒 有別的。23到27行是實際顯示的XML代碼。23行配置XML輸出並設定樣式表爲html.xsl。24到26行將取自數據庫,等待轉換的XML包含進 來。正如你看到的,代碼很淺顯。

熟悉了代碼,就要準備編譯我們的web程序並部署到WebLogic Server上。一個這麼簡單的WAR程序只要手工編譯就可以了。下面是創建xmlweb.war程序以備發佈的步驟:

C:/white/work/Java/xmlweb/xmlweb_war>jar -cvf xmlweb.war .
added manifest
adding: html.xsl(in = 579) (out= 279)(deflated 51%)
adding: index.jsp(in = 935) (out= 486)(deflated 48%)
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/xmlparserv2.jar(in = 689990) (out= 645476)(deflated 6%)
adding: WEB-INF/lib/xmlx-tags.jar(in = 11106) (out= 9952)(deflated 10%)
adding: WEB-INF/lib/xsu12.jar(in = 456545) (out= 138160)(deflated 69%)
adding: WEB-INF/web.xml(in = 327) (out= 226)(deflated 30%)


現在,找到編譯好的web程序WAR文件並部署到WebLogic Server。這可以利用WebLogic控制檯做到。部署好後在web瀏覽器中打開下面這個地址查看結果:
http://localhost:7001/xmlweb/index.jsp

應該能看到類似圖5的情形。

image
圖5. 部署web程序


正如上圖展示的,從數據庫中以XML形式獲取的數據按漂亮的格式顯示了出來。現在我們可以在很多地方用到這種技術,從簡單的新聞聚合(news feed)到有模板和樣式表的複雜列表引擎。

結語
本教程爲讀者奉上了整合SQL查詢和XML轉換器的基礎知識,給出了一個可以用在你自己軟件中的特性。XML技術本身在web程序方面有許多用處,而與數據庫的整合使它成爲更強大的工具。

下載
本文中的獨立Java程序:xmlweb_src.zip:[下載文件]
文中的web程序:xmlweb.war:[下載文件]


作者介紹
Alexander Prokhorenko 是一位經過認證的專業人員,獲得Sun系統管理員認證和Sun Java程序員認證。他的興趣領域包括系統開發生命週期、IT項目管理、服務器和應用程序架構。
Olexiy Prokhorenko 是一位Sun認證企業架構師,同樣獲得了Sun Java程序員認證和Sun Web組件開發者認證。他的興趣領域包括Web軟件架構、高頻變更需求的軟件開發,以及異地外包團隊的管理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章