摘 要: 介紹了JAXM結構,并利用其特點構建了不使用消息接發提供者的Web服務應用,分析了基于JAXM設計的體系結構和設計模式。
關鍵詞: JAXM規范 SAAJ包 SOAP規范 Web服務
JAXM(Java API for XML Messaging)是基于SOAP1.1規范并帶有Attachments的SOAP規范,它定義了一個能夠與XML消息交換的基本框架。JAXM提供了一種能夠在Java平臺上通過Internet發送XML文檔的標準方法,使得開發者可以使用Java平臺進行XML消息收發。而大多數的Web服務都是由簡單的消息交換組成,對于有些Web服務,直接在低級別的消息層編程通常是很有用的。JAXM提供了使XML數據能夠在二個應用之間互操作的框架,允許在二個獨立的Web服務之間完成全部XML文件的傳輸,而SOAP提供了在二個應用之間傳輸消息的底層格式。
1 JAXM相關概念
完整的JAXM API存在于javax.xml.soap和javax.xml.messaging二個包中。javax.xml.soap是用于接發SOAP消息的基本包,主要包含了發送帶有附件的SOAP消息的API(SOAP with Attachments API for Java,SAAJ)。這個包包含所有發送請求-響應消息所必需的API。javax.xml.messaging包含了使用消息接發提供者必須的API,因此能夠發送單向消息。現在SAAJ不再依賴于javax.xml.messaging包,可以獨立使用。在JAXM1.1規范中定義的javax.xml.messaging包保持了對java.xml.soap包的依賴。
JAXM消息遵循SOAP標準,規定了消息的格式。通過JAXM API可以方便地創建遵從SOAP規范的XML消息。有二類SOAP消息,一類是帶有附件的消息,另一類是沒有附件的消息。SOAP消息都是通過連接進行接發的,有二種類型的連接,分別由JAXM API提供的類和接口來表示。javax.xml.soap.SOAPConnection表示了消息發送者到接收者的直接連接,這種類型的連接是點對點的,即使不在Servlet或者J2EE容器里也能使用。這種類型的消息接發又稱為請求-響應消息接發。javax.xml.messaging.ProviderConnection表示了到消息接發提供者的連接,這種連接方式需要消息發送者和消息使用者通過消息提供者來交互。
2 使用JAXM建立Web服務消息接發
JAXM客戶端可以使用消息接發提供者,也可以不用。沒有使用消息接發提供者的應用程序被限制只能承擔客戶端的角色,只能發送請求-響應消息。下面介紹建立不使用消息接發提供者的Web服務消息接發,即點對點的請求-響應消息接發。
(1)獲得連接。任何一個JAXM客戶端需要完成的第一件事是獲得連接。當前客戶端使用SOAPConnection對象創建連接,使用SoapConnection對象發送的消息直接從發送者到發送者指定的URL,示例如下:
SOAPConnectionFactory scf=SOAPConnectionFactory.
newInstance( );
SOAPConnection con=scf.createConnection( );
(2)創建消息。生成消息可以使用SAAJ API提供的MessageFactory類的默認實現。
MessageFactory mf=MessageFactory.newInstance( );
SOAPMessage msg=mf.createMessage( );
由messageFactory創建的所有SOAPMessage對象都是基本SOAP消息,這意味著它們沒有預定義的頭部。JAXM所具有的靈活性之一就是它允許SOAP頭部有特殊的用途。例如,像ebXML這樣的一些協議可以建立在SOAP消息發送協議之上,以便提供附加頭部的實現,這樣就獲得了附加的功能。
(3)向消息添加內容。可以向SOAPPart對象以及一個或多個AttachmentPart對象添加內容,也可以向消息的這二個部分都添加內容。為了向消息體添加內容,需創建一個SOAPBodyElement對象并添加一個使用SOAPElement.addTextNode方法建立的XML元素。
(4)發送消息。一旦填充了一個SOAPMessage對象,就可以發送此對象了。單獨客戶端使用SOAPConnection的call方法來發送消息。該方法發送完消息之后就將自己阻塞起來,直到收到響應為止。傳給call方法的參數中,一個是要發送的消息,還有一個是URL對象,該對象包含了接收者端點的URL。
(5)從響應消息中檢索內容。客戶端使用onMessage方法檢索消息內容。客戶端通過消息得到envelope,再通過envelope得到body,從而訪問SOAPBody對象。
3 使用JAXM構建Web服務應用
下面使用JAXM 構建對外提供話費查詢的Web服務。由于客戶端是Web服務的消費者,所以JAXM客戶端不需要消息接發提供者,使用點對點的請求-響應消息接發即可。話費查詢服務系統體系結構如圖1所示。
客戶端可以是一般的Java GUI程序(當然也可以是JSP、Servlet等),客戶端通過SOAP消息與Servlet容器中運行的JAXM Servlet進行交互。JAXM Servlet是服務提供者,EJB容器里運行的是業務組件,為JAXM Servlet提供服務。

系統為客戶端提供了三種查詢服務:每月匯總查詢、話費詳單查詢、即時詳單查詢。這三種服務分別對應服務端的三個JAXM Servlet實現:TotalMonth,每月匯總查詢;DetailMonth,話費詳單查詢;PrestentDetail,即時詳單查詢。
(1)數據模型。在數據庫中保存每個用戶的話費信息。為了便于傳輸數據,減少遠程調用的次數,特別設計了值對象TelExpVA來代表話費信息。值對象設計模式在J2EE模式中大量使用。JAXM Servlet和EJB組件之間傳遞數據就是通過對象來傳遞的。這個對象是包含有TelExpVA實例的java.util.Collection。但是JAXM和客戶端是通過SOAP消息來傳遞的(也可以使用序列化的對象作為附件發送)。為了傳輸話費信息,還需要定義相對應的DTD或者schema。
(2)業務邏輯。業務層是EJB組件,使用了二個EJB組件,一個是TelExpServiceFacadeEJB,它是一個有狀態會話Bean;另一個是TelExpEntityEJB,它是一個實體Bean,代表了持久數據。TelExpServiceFacadeEJB是會話門面,JAXM Servlet通過它來和TelExpEntityEJB交互。
(3)JAXM服務端。JAXM服務端Servlet處理消息的步驟是:獲得消息(onMessage),讀取消息中需要的參數,利用參數調用對應的業務處理,構建響應SOAP消息,返回處理后的消息。
在JAXM 服務端設計了三個服務JAXM Servlet,分別對應三個查詢用例,其關系如圖2所示。

由于使用了點對點的消息模型,服務端需要實現javax.xml.messaging.ReqRespListener接口,并且需要繼承javax.xml.messaging.JAXMServlet類。onMessage方法就是當Servlet接收到SOAPMessage時激發的方法,通過此方法對外界提供服務。每個JAXM Servlet都有一個onMessage方法。
(4)客戶端。最終客戶端是一個叫TelExpClientGUI的圖形界面程序,它并不直接與SOAP消息打交道,而是通過JAXMDelegate類與服務端JAXM Servlet進行交互。另外,還設計了一個BookBusiness接口。JAXMDelegate實現了BookBusiness接口,BookClientGUI持有BookBusiness的實例,它通過這個實例獲得信息。BookBusiness返回的信息都是java.util.Collection,它是BookClientGUI和JAXMDelegate通信的橋梁。
(5)使用XML業務代表的模式。用JAXM進行Web服務開發還不普遍,相應的設計模式的探討還較少,它的設計模式和J2EE平臺其他組件的設計模式基本一致。但它有自己的特點,如客戶端和服務端是通過SOAP消息進行通信,這與J2EE平臺的其他組件之間的通信不同。在JAXM編程中,為了實現數據(這里是SOAP消息)的一致返回,可以使用XML業務代表的模式。用JAXM進行編程時,數據傳遞的特點如圖3所示。

客戶端最終要使用的數據是Java對象或者Java的基本數據類型,而客戶端和服務端的通信是通過SOAP消息格式來傳輸,而在服務端要調用業務邏輯,必須使用Java對象或者是Java基本數據類型,這使數據的傳輸和數據的使用出現矛盾。為解決矛盾,可以使用數據轉換器來轉換數據,以降低層之間的耦合度,使數據易于處理。當客戶端要發送數據時,使用數據轉換器把請求數據轉換為SOAP消息格式。當在服務端調用業務邏輯后,為使數據能在internet上傳輸,使用數據轉換器把調用結果封裝為SOAP消息。
在客戶端,通過使用JAXM業務代表,可以降低最終客戶和SOAP消息的耦合度。系統的結構如圖4所示。

當客戶端發出請求時,它調用JAXMDelegate對應的方法;JAXMDelegate根據請求構造對應的SOAP消息,然后把消息發送到服務端;服務端根據客戶的請求做出對應的處理,并把處理結果返回到JAXMDelegate;JAXMDelegate使用數據轉換器把返回的SOAP Message轉化成Java對象(如值Bean),最后返回給客戶端;客戶端再把獲得的數據進行處理后顯示。JAXM業務代表使用數據轉換器來轉換數據,業務代表直接和Web服務進行交互,屏蔽了Web服務請求的復雜過程,為客戶端提供易于使用的接口。
服務端的模式和客戶端的模式基本一樣,只是處理過程相反。服務端從客戶端接收到SOAP消息后,讀取參數,調用對應的業務方法,然后使用數據轉換器把調用的結果轉換成SOAP消息返回。
4 結束語
JAXM作為輕量級的API,抽象了底層的消息基礎結構。因此,開發時利用SOAP包裝的JAXM消息是容易的。需要強調的是,如果使用點對點的消息發送模型,則服務端Servlet必須實現ReqRespListener接口,onMessage( )方法將是開發服務端Servlet的重點任務。本文通過使用適當的設計模式和接口,減少了各層之間的耦合。數據轉換在設計中占有很大的分量,業務代表模式在以上數據轉換和業務處理中起著重要的作用。
參考文獻
1 Sun Microsystems Inc.The Java Web Services Tutorial. http://java.sun.com/webservices/docs/1.0/tutorial/index.html.
2 Kao J.Developer′s Guide to Building XML-based Web Services with the Java 2 Platform,Enterprise Edition (J2EE). http://www.middleware-company.com.
