年底Sun 公司發布了 Java Standard Edition (Java SE )的最終正式版代號 Mustang(野馬)跟 Tiger(Java SE )相比Mustang 在性能方面有了不錯的提升與 Tiger 在 API 庫方面的大幅度加強相比雖然 Mustang 在 API 庫方面的新特性顯得不太多但是也提供了許多實用和方便的功能在 腳本XML 和 Web 服務編譯器 API數據庫JMX網絡 和 Instrumentation 方面都有不錯的新特性和功能加強
本系列 文章主要介紹 Java SE 在 API 庫方面的部分新特性通過一些例子和講解幫助開發者在編程實踐當中更好的運用 Java SE 提高開發效率本文是系列文章的最後一篇主要介紹了 Java SE 中提供的 XML 處理框架以及在此框架之上結合注釋(Annotation) 技術所提供的強大的針對 Web 服務的支持
Java SE 做為一個開發平台針對不同的應用開發需求提供了各種各樣的技術框架XML 處理框架是 JDK 的重要組成部分之一它為應用程序開發人員提供了一個統一的 XML 處理 API這種框架結構有兩個作用一方面開發人員透過這些框架可以透明的替換不同廠商提供的 XML 處理服務另一方面服務提供商可以透過這些框架將自己的產品插入到 JDK 中這種框架一般被稱為 Service Provider 機制Java SE 的 XML 處理功能分為兩個部分XML 處理(JAXP)和 XML 綁定(JAXB)在 XML 處理框架之上Java SE 結合了注釋(Annotation)技術提供了強大的針對 Web 服務的支持
本文首先介紹 Service Provider 機制及其在 XML 框架中的應用然後介紹 Java SE 中 XML 框架的功能包括 SAXStAXDOM 三種機制最後介紹在此基礎之上構建 Web 服務的技術JAXB 和 Web 服務的開發關系緊密故 JAXB 的介紹也放在 Web 服務部分介紹本文內容基於 Java SE SDK
Service Provider 機制
對於同一個功能不同的廠家會提供不同的產品比如不同品牌的輪胎插頭等在軟件行業情況也是如此比如對於數據的加密解密不同的廠家使用不同的算 法提供強度各異的不同軟件包應用軟件根據不同的開發需求往往需要使用不同的軟件包每次更換不同的軟件包都會重復以下過程更改應用軟件代碼 > 重新編譯 > 測試 > 部署這種做法一般被稱為開發時綁定這其實是一種比較原始的做法缺乏靈活性和開放性於是應用運行時綁定服務提供者的做法流行開來具體做法是使用 配置文件指定然後在運行時載入具體實現Java SE 平台提供的 Service Provider 機制是折衷了開發時綁定和運行時綁定兩種方式很好的滿足了高效和開放兩個要求
構成一個 Service Provider 框架需要大致三個部分圖 給出了一個典型的 Service Provider 組件結構Java SE 平台的大部分 Service Provider 框架都提供了 個主要個組件面向開發者的 Application 接口面向服務提供商的 Service Provider 接口和真正的服務提供者
圖 Service Provider 的組件結構
這樣做的主要好處包括
提供了供應商的中立性應用代碼與服務提供商完全獨立互不依賴應用程序開發者針對 圖 中 Application 接口進行開發這個接口將不同提供商的接口差異性屏蔽掉了無論使用哪個廠商的服務應用程序都是針對一個穩定統一的接口開發業務邏輯和第三方組件之間有很強的獨立性如果有需要應用程序可以針對不同提供商重新部署清單 顯示某應用程序中的一段代碼
清單 通過統一應用程序接口獲得服務
SAXParserFactory factory = SAXParserFactorynewInstance();
Systemoutprintln(factorygetClass());
// Parse the input
SAXParser saxParser = factorynewSAXParser();
Systemoutprintln(saxParsergetClass());
Output: class orgapachexercesjaxpSAXParserFactoryImpl
Output: class orgapachexercesjaxpSAXParserImpl
本例中 saxParser 的類型被聲明為 SAXParser但實際類型如 清單 中顯示為 orgapachexercesjaxpSAXParserImpl實際類型是由 SAXParserFactory 的靜態方法 newInstance 查找配置文件並實例化得到的圖 展示了 Java SE 中 XML 包的 Service Provider 的交互細節請參考 Apache Harmony 項目的具體代碼(參見 參考資源)
圖 XML 包的 Service Provider 結構
提供了擴展性更多的服務可以加入開發平台為了便於不同的開發商開發各自的產品Java SE 平台同時為服務提供商設計了統一的接口只要提供者滿足這些接口定義(比如繼承某個接口或者擴展抽象類)服務提供者就能被添加到 Java SE 平台中來以 圖 給出的結構為例服務提供者需要繼承 SAXParserFactorySAXParser 等抽象類同時將類 VendorSaxParserFactoryImpl 的名字注冊到 jaxpproperties 文件中就可以被使用了
兼 顧了靈活性和效率通過這種方式一方面組件提供者和應用開發者開發時綁定到一個約定的接口上另一方面載入具體哪個組件則是在運行時動態決定的不同於 Web 服務等技術的完全動態綁定(通過運行時解析 WSDL 文件來決定調用的類型)也不是完全的編碼時綁定這種折衷的方式提供了松耦合高擴展性同時也保證了可接受的效率
XML 框架介紹
Java SE 平台提供的 XML 處理主要包括兩個功能XML 處理(JAXPJava Architecture XML Processing)和 XML 綁定(JAXBJava Architecture XML Binding)JAXP 包括 SAX 框架 —— 遍歷元素做出處理DOM 框架 —— 構造 XML 文件的樹形表示StAX 框架 —— 拖拽方式的解析XSLT 框架 —— 將 XML 數據轉換成其他格式JAXB 則是負責將 XML 文件和 Java 對象綁定在新版 JDK 中被大量的使用在 Web 服務技術中
SAX 框架(Simple API for XML)
SAX 全稱 Simple API for XML該框架使用了事件處理機制來處理 XML 文件圖 展示了這個過程
圖 SAX 框架處理 XML 文件的流程
SAXParser 將 XML 文件當作流讀入當 parser 遇到 Element_A就會產生一個事件然後將該事件發送給處理類SAX 框架的一大特點是對於節點的處理是上下文無關的比如 圖 中 SAXParser允許注冊一個處理類這個處理類對於所有節點並不加以區分對他們的處理過程都是一致的一般包括 startElement 和 endElement 等動作清單 給出了處理類的 startElement 動作的偽代碼
清單 處理類的 startElement 動作的偽代碼
CLASS Listener < DefaultListener
PROCEDURE StartElement(…)
IF ( node>Objname == Node )
// Do some calculation
FI
END
END
SAXParser>SetListener(new Listener)
使用 SAX 框架對於 Node 節點的處理並不會根據其前驅或者後綴節點的不同而有所區別偽代碼 行說明了這一點一旦發現節點名稱是 Node則進行預定的處理這個框架本身並不支持對節點進行上下文相關的處理除非開發者另外維護一些數據結構來記錄上下文狀態正是由於 SAX 框架不需要記錄的狀態信息所以運行時SAX 框架占用的內存(footprint)比較小解析的速度也比較快
DOM 框架(Document Object Model)
DOM 框架的全稱是 Document Object Model顧名思義這個框架會建立一個對象模型針對每個節點以及節點之間的關系在內存中生成一個樹形結構這個特點與 SAX 框架截然相反需要注意的是DOM 框架提供的對象樹模型與我們通常理解的 XML 文件結構樹模型是有一定的區別的圖 給出了一個 XML 文件的結構
圖 DOM 框架的對象模型
圖 中的 Element_B 具有 清單 這樣的結構
清單 Element_B 的 XML 結構
<Element_B>This is start of Element_B
<Node>…</Node>
This is end of Element_B
</Element_B>
按照 圖 和 清單 給出的結構一般的對象的觀點理解Element_B 包含子元素 Node而兩句話This is start of Element_B與This is end of Element_B是 Element_B 節點的內容而實際上當針對 Element_B 調用 ElementgetContent得到的是 Element_B 這個名字本身兩句文本同 Node 一樣也是作為子節點的可以這樣認為DOM 的對象模型在內存中模擬的是 XML 文件的物理存儲結構而不是節點間的邏輯關系DOM 中結點的類型也是通過 getContent 返回的節點名字符串區別的當客戶端識別節點類型時通常會形成以下的代碼片斷
清單 使用 DOM 框架的客戶端代碼
name = ElementgetContent
SWITCH name
CASE Element_A:
// Do something
BREAK
CASE Element_B:
// Do something
BREAK
DEFAULT:
END
這種方式是很明顯的早綁定 —— 編碼時 / 編譯時綁定而不是面向對象語言中使用的運行時綁定技術 —— 繼承帶來的虛擬函數特性這個問題的產生和 DOM 框架的設計目標有關DOM 的目標是一個編程語言無關的用來處理大段復雜 XML 文件的框架(參見 參考資源) 比如書籍和文章DOM 框架一個顯著的特征是善於處理節點與文本混合的 XML 文件(MixedContent Model)這種設計使得 XML 形成樹的過程是一個直接映射不需要進行概念上的轉換也就節省掉很多的處理細節一定程度上提高了效率這一點在處理大文件時比較明顯兼顧了效率和上 下文狀態問題另一方面由於編程語言無關的設計目標也決定了放棄虛函數機制是必要的
StAX 框架(Streaming API for XML)
SAX 框架的缺點是不能記錄正在處理元素的上下文但是優點是運行時占內存空間比較小效率高DOM 框架由於在處理 XML 時需要為其構造一棵樹所以特點正好相反StAX 框架出現於 Java SE 中它的設計目標就是要結合 SAX 框架和 DOM 框架的優點既要求運行時效率也要求保持元素的上下文狀態清單 是一段使用 StAX 框架處理 XML 文件的代碼
清單 使用 StAX 框架處理 XML 文件
import javaio*;
import javaxxmlstream*;
import javaxxmlstreamevents*;
public class StAXTest {
public static void main(String[] args) {
XMLInputFactory inputFactory = XMLInputFactorynewInstance();
InputStream input = new ByteArrayInputStream(
(<?xml version=\\ encoding=\UTF\?> +
<workcontactinfo> +
<Location>Shanghaishuion</Location> +
<Postal></Postal> +
<Tel><fix></fix><mobile></mobile></Tel> +
<Appellation>Mr Wang</Appellation> +
</workcontactinfo>)getBytes());
try {
XMLEventReader xmlEventReader = inputFactorycreateXMLEventReader(input);
while (xmlEventReaderhasNext()) {
XMLEvent event = xmlEventReadernextEvent();
if (eventisStartElement()) {
StartElement startElement = eventasStartElement();
Systemoutprintln(startElementgetName()toString());
}
if (eventisCharacters()) {
Characters text = eventasCharacters();
if (!textisWhiteSpace()) {
Systemoutprintln(\t + textgetData());
}
}
}
} catch (XMLStreamException e) {
eprintStackTrace();
}
}
}
觀察後可以發現 StAX 框架和 SAX 框架具有相似的地方StAX 有 EventisStartElement 方法SAX 有 DefaultHandlerstartElement 方法StAX 有 EventisCharacter 方法SAX 有 DefaultHandlercharacter 方法實際上這兩個框架處理 XML 文件的時候使用了相似的模型——將 XML 文件作為元素組成的流而不同於 DOM 的樹模型解析 XML 文件時應用程序調用 XMLEventReader 的 nextEvent 方法解析下一個元素(或者是解析同一個元素根據解析的不同階段產生不同元素)StAX 就會通過 XMLEventReader 產生一個事件比如針對同一個元素可能會產生 StartElement 和 EndElement 事件形象的說 XMLEventReader 就像是一根繩子拽一下解析一個元素產生一個事件於是這種技術也被稱為Pull Parser技術StAX 在處理 XML 文件時產生的所有事件是通過一個 Iterator(XMLEventReader 繼承了 Iterator)返回的應用程序通過這個 Iterator 能知道某個解析事件的前後分別是什麼這類信息就是一個元素的上下文信息
XSLT 數據轉換框架(The Extensible Stylesheet Language Transformations APIs)
一 般來說 XML 文件格式被認為是一種很好的數據交換格式於是 Java SE SDK 基於以上介紹的三種 XML 處理機制提供了一個 XML 轉換框架XSLT 框架負責進行轉換 —— 包括將 XML 文件轉換成其他形式如 HTML和將其他形式的文件轉換成 XML 文件更進一步說這個框架可以接受 DOM 作為其輸入和輸出可以接受 SAX 解析器作為輸入或者產生 SAX 事件作為輸出可以接受 I/O Stream 作為輸入和輸出當然也支持用戶自定義形式的輸入和輸出圖 顯示了這種依賴關系
圖 XSLT 框架的依賴關系
轉換框架的輸入輸出對象的類型並不要求是一一對應的比如使用 DOMSource 做為輸入可以使用 StreamResult 作為輸出清單 是一段偽代碼用來顯示 JDK 將不同 javaxxmltransformSource 轉換成不同 javaxxmltransformResult 子類型的過程
清單 JDK 轉換框架的轉換過程
// Construct input
factory = XMLParserDocumentFactory>NEW
parser = factory>NewParser
document = parser>Parse(File)
// Wrap input/output
source = Source>NEW( document )
sink = Result>NEW
// Construct transformer
tFactory = TransformerFactory>NEW
transformer = tFactory>NewTransformer
// Transform
transformer>Transfer( source sink)
通過這個過程的轉化一個 javaxxmltransformSource 可以轉化成為類型 javaxxmltransformResultJDK 提供了如 圖 所示的 種 Result 子類型用戶也可以定義自己的 Result 類型另一方面用戶自定義的數據解析器或者數據文件也可以作為 Transformer 的輸入下面一個例子針對一個數據文件首先生成了一棵 DOM 樹然後又根據這棵 DOM 樹提取了所有的聯系信息生成了一個文本文件清單 給出了這個數據文件
清單 地址信息文件
work contactinfo
Location Shanghaishuion
Postal
Tel
fix
mobile
Appellation Mr Wang
清單 為這個信息文件構造一個 DOM 樹並將其作為 transformer 的輸入
清單 構造 DOM 樹
import javaxxmlparsersDocumentBuilder;
import javaxxmlparsersDocumentBuilderFactory;
import javaxxmltransformTransformer;
import javaxxmltransformTransformerException;
import javaxxmltransformTransformerFactory;
import javaxxmltransformdomDOMSource;
import javaxxmltransformsaxSAXResult;
import orgwcdomDocument;
import orgwcdomElement;
import orgxmlsaxSAXException;
import orgxmlsaxhelpersDefaultHandler;
class ContentHandler extends DefaultHandler {
@Override
public void characters(char[] ch int start int length)
throws SAXException {
String name = new String(ch start length);
Systemoutprint(name + \t);
}
}
public class DOMTest {
/**
* @param args
* @throws TransformerException
*/
public static void main(String[] args) {
try {
DocumentBuilderFactory documentfactory = DocumentBuilderFactory
newInstance();
DocumentBuilder builder = documentfactorynewDocumentBuilder();
Document document = buildernewDocument();
Element root = documentcreateElement(workcontactinfo);
Element loca = documentcreateElement(Location);
locasetTextContent(Shanghaishuion);
rootappendChild(loca);
Element postal = documentcreateElement(Postal);
postalsetTextContent();
rootappendChild(postal);
Element tel = documentcreateElement(Tel);
rootappendChild(tel);
Element fix = documentcreateElement(fix);
fixsetTextContent();
telappendChild(fix);
Element mobile = documentcreateElement(mobile);
mobilesetTextContent();
telappendChild(mobile);
Element appellation = documentcreateElement(Appellation);
appellationsetTextContent(Mr Wang);
rootappendChild(appellation);
documentappendChild(root);
TransformerFactory tFactory = TransformerFactorynewInstance();
Transformer transformer;
transformer = tFactorynewTransformer();
SAXResult result = new SAXResult();
ContentHandler cHandler = new ContentHandler();
resultsetHandler(cHandler);
transformertransform(new DOMSource(document) result);
} catch (Exception e) {
eprintStackTrace();
}
}
}
Java SE SDK 提供了至少以上三種內置的處理 XML 文件的機制它們分別是 Simple API for XMLDocument Object Model 和 Streaming API for XML其中 SAX 和 StAX 采用了相似的模型 —— 將 XML 文件建模為元素流DOM 采用了樹形模型帶來的結果是 SAX 和 StAX 運行時空間相對 DOM 緊湊狀態保持能力則依次 SAX > StAX > DOM 變強特別值得一提的是 StAX 技術是最新引進的 XML 處理技術它結合了 SAX 和 DOM 的優點清單 給出了一個粗略度量 SAXStAXDOM 三個框架解析同一個 XML 文件的運行效率的代碼
清單 度量 XML 解析框架的運行時間
public class StAXTest {
public static void main(String[] args) {
final String xml = <?xml version=\\ encoding=\UTF\?> +
<workcontactinfo> +
<Location>Shanghaishuion</Location> +
<Postal></Postal> +
<Tel><fix></fix> +
<mobile></mobile></Tel> +
<Appellation>Mr Wang</Appellation> +
</workcontactinfo>;
for (int i = ; i < ; i++) {
StAX(xml);
}
for (int i = ; i < ; i++) {
SAX(xml);
}
for (int i = ; i < ; i++) {
DOM(xml);
}
long current = SystemcurrentTimeMillis();
for (int i = ; i < ; i++) {
StAX(xml);
}
current = SystemcurrentTimeMillis() current;
Systemoutprintln(current);
current = SystemcurrentTimeMillis();
for (int i = ; i < ; i++) {
SAX(xml);
}
current = SystemcurrentTimeMillis() current;
Systemoutprintln(current);
current = SystemcurrentTimeMillis();
for (int i = ; i < ; i++) {
DOM(xml);
}
current = SystemcurrentTimeMillis() current;
Systemoutprintln(current);
}
private static void StAX(final String xml) {
XMLInputFactory inputFactory = XMLInputFactorynewInstance();
InputStream input;
try {
input = new ByteArrayInputStream(xmlgetBytes());
XMLEventReader xmlEventReader = inputFactory
createXMLEventReader(input);
while (xmlEventReaderhasNext()) {
XMLEvent event = xmlEventReadernextEvent();
if (eventisStartElement()) {
StartElement startElement = eventasStartElement();
}
if (eventisCharacters()) {
Characters text = eventasCharacters();
if (!textisWhiteSpace()) {
}
}
}
} catch (XMLStreamException e) {
eprintStackTrace();
}
}
private static void SAX(final String xml) {
SAXParserFactory f = SAXParserFactorynewInstance();
InputStream input;
try {
SAXParser p = fnewSAXParser();
input = new ByteArrayInputStream(xmlgetBytes());
pparse(input new DefaultHandler());
} catch (Exception e) {
eprintStackTrace();
}
}
private static void DOM(final String xml) {
DocumentBuilderFactory f = DocumentBuilderFactorynewInstance();
InputStream input;
try {
DocumentBuilder p = fnewDocumentBuilder();
input = new ByteArrayInputStream(xmlgetBytes());
pparse(input);
} catch (Exception e) {
eprintStackTrace();
}
}
}
得出的數據如下
可以看出解析速度按 SAX > StAX > DOM 依次變慢這組數據從一個側面反映了這三種技術的特性SAX 處理小的簡單的 XML 文件更高效基於三種 XML 解析技術Java SE SDK 又提供了數據格式轉換框架 —— XSLT同時 XSLT 技術和其他很多的 JDK 框架一樣是一個開放框架它提供了一些抽象類和接口讓應用程序可以根據需求開發出不同的 XML 數據處理和轉換工具然後通過之前敘述的 Service Provider 機制將這些工具插入JDK 中表 羅列了 SAXStAXDOMXSLT 在 JDK 中的位置
表 SAXStAXDOMXSLT 在 JDK 中的位置
SAX |
StAX |
DOM |
XSLT |
javax
xml
parsers
javax
xml
stream
javax
xml
parsers
javax
xml
transform
javax
xml
stream
events
javax
xml
transform
dom
javax
xml
stream
util
javax
xml
transform
sax
javax
xml
transform
stax
javax
xml
transform
stream
Web 服務
基於XML的數據通常被作為 Web 服務之間互相調用的標准的數據傳輸文件格式Java SE SDK 中基於 XML 的解析技術也提供了 Web 服務的 API 支持和較早的 JDK 相比新版本的 JDK Web 服務功能更改了名稱 —— 從 JAXRPC 變成 JAXWSJDK 只支持基於 remoteprocedurecall 的 Web 服務JDK 在此基礎上還支持基於 SOAP message 的 Web 服務實現下面將給出一個例子基於 SOAP message實現一個簡單的 Web 服務
清單 給出了開發一個 Web services EndPoint 的代碼
清單 一個 Web serviceHello服務
package hello;
import javaxjwsWebService;
import javaxjwsWebMethod;
import javaxxmlwsEndpoint;
@WebService
public class Hello {
@WebMethod
public String hello(String name) {
return Hello + name + \n;
}
public static void main(String[] args) {
// create and publish an endpoint
Hello hello = new Hello();
Endpoint endpoint = Endpointpublish(//localhost:/hello hello);
}
}
使用 apt 編譯 Hellojava產生輔助文件
apt d sample example/Calculatorjava
運行完這條命令之後example 目錄下面多出了一個 jaxws 子目錄如 圖 所示Apt 工具在該目錄裡生成了發布 Hello Web service 所必需的兩個輔助文件
圖 example 目錄
發布 Hello Web service
java cp sample helloHello
將浏覽器指向//localhost:/hello?wsdl 會產生如 圖 所示頁面
圖 發布的 Hello Web service
Java SE SDK 內嵌了一個輕量級的 HTTP Server方便開發者驗證簡單的 Web service 功能通過以上三步一個 Web service Endpoint 就部署完成下面將開發一個調用 Hello 服務的客戶端
為 Web 服務的客戶端產生存根文件
wsimport p sample //localhost:/hello?wsdl
這將會在 sample 目錄下產生如 圖 所示的文件這一步實際是根據上面 URL 指向的 WSDL 文件通過 JAXB 技術生成了相應的 Java 對象
圖 wsimport 產生的文件
開發編譯運行 Web 服務客戶程序清單 給出了使用 Hello 服務的客戶程序
清單 使用 Hello 服務的客戶程序
package sample;
class HelloApp {
public static void main(String args[]) {
HelloService service = new HelloService();
Hello helloProxy = servicegetHelloPort();
String hello = helloProxyhello(developer works);
Systemoutprintln(hello);
}
}
圖 是編譯並運行該客戶程序產生的結果
圖 調用 Hello 服務
可以說在 Java SE SDK 中Web 服務的開發過程被大大簡化了原來開發中需要手工重復勞動產生的文件可以使用工具自動生成比如 WSDL 文件可以自動生成和 WSDL 綁定的 Java 對象也自動生成部署(本文僅指 JDK 提供的輕量 HTTP server 部署環境)也大大簡化這些全部歸功於 JDK 中引入的一些新的 JSR 實現即一些 API 和工具表 給出了 JDK 中為 Web 服務 API 提供支持的包
表 JDK 中提供 Web 服務 API 支持的包
JSR |
Package |
JSR
Java API for XMLBased Web Services
javax
xml
ws
javax
xml
ws
handler
javax
xml
ws
handler
soap
javax
xml
ws
http
javax
xml
ws
soap
javax
xml
ws
spi
JSR
Java Architecture for XML Binding (JAXB)
javax
xml
bind
javax
xml
bind
annotation
javax
xml
bind
annotation
adapters
javax
xml
bind
attachment
javax
xml
bind
helpers
javax
xml
bind
util
JSR
Web Services Metadata for the Java Platform
javax
jws
javax
jws
soap
除此之外 JDK 還提供了一些工具包括 wsgen wsimport 以及 Java 調用的輕量級 HTTP serverAPI 和工具聯合提供了一個簡單的 Web services IDE 開發環境可以簡化 Web 服務應用的開發
Java class 和 XML 文件的綁定
從上一段關於 Web 服務的敘述中我們能夠發現開發和部署 Web 服務的過程中存在多次 Java 對象和 XML 文件轉化的過程比如開發和部署服務的時候將一個 Web Service EndPoint 發布成為一個 WSDL或者使用服務的時候將一個 WSDL 文件轉換成一組 Java 對象所有的轉換都是通過工具自動完成的這裡存在一些問題Java 對象的類型轉換成 XML 元素是需要符合一定的標准還是隨意轉換呢?如果按照標准轉換那麼這個標准是什麼樣子的?比如 Java 中的 int 類型是應該變成 <int></int> 呢還是 <integer></integer>如 表 列出JSR Java Architecture for XML Binding (JAXB) 標准為這些問題給出了一個規范的解答
首先示范一個簡單的例子將根據一個 XML 文件的 schema轉換成 Java 對象還是以 清單 中的數據文件為依據構造一個 XML schema 文件如 清單 所示要運行這個例子首先需要下載一個 JAXB Reference Implementation jar(下載請參見 參考資源)並將該 jar 文件加入到 classpath 中
清單 用於綁定的 workcontactinfoxsd 文件
<xsd:schema xmlns:xsd=>
<xsd:element name=workcontactinfo type=workcontactinfo />
<xsd:complexType name=workcontactinfo>
<xsd:sequence>
<xsd:element ref=Location maxOccurs= minOccurs= />
<xsd:element ref=Postal maxOccurs= minOccurs= />
<xsd:element ref=tel maxOccurs= minOccurs= />
<xsd:element ref=Appellation maxOccurs= minOccurs= />
</xsd:sequence>
</xsd:complexType>
<xsd:element name=tel type=tel />
<xsd:complexType name=tel>
<xsd:sequence>
<xsd:element ref=fix maxOccurs= minOccurs= />
<xsd:element ref=mobile maxOccurs= minOccurs= />
</xsd:sequence>
</xsd:complexType>
<xsd:element name=Location type=xsd:string />
<xsd:element name=Postal type=xsd:string />
<xsd:element name=Appellation type=xsd:string />
<xsd:element name=fix type=xsd:string />
<xsd:element name=mobile type=xsd:string />
</xsd:schema>
運行命令 xjc workcontactinfoxsd將會在當前目錄下生成一個 generated 子目錄
運行命令 javac generated\*java編譯所有生成的 Java 文件
操作生成的 Java 對象清單 給出了一個操作生成的 java 對象的例子要注意一定要先將 JAXB Reference Implementation jar 放到 classpath 中
清單 調用生成的 Java 對象
import generated*;
import javaioFileOutputStream;
import javaxxmlbindJAXBContext;
import javaxxmlbindMarshaller;
public class JAXBTest {
public static void main(String[] args) {
try {
JAXBContext jContext = JAXBContextnewInstance(generated);
ObjectFactory factory = new ObjectFactory();
Workcontactinfo contactinfo = (Workcontactinfo) (factory
createWorkcontactinfo());
contactinfosetAppellation(Mr Wang);
contactinfosetLocation(Shanghaishuion);
contactinfosetPostal();
Tel tel = (Tel) (factorycreateTel());
telsetFix();
telsetMobile();
contactinfosetTel(tel);
Marshaller marshaller = jContextcreateMarshaller();
marshallersetProperty(MarshallerJAXB_FORMATTED_OUTPUT
BooleanTRUE);
marshallermarshal(contactinfo new FileOutputStream(
workcontactinfoxml));
Systemoutprintln(java tree converted into xml & filed);
} catch (Exception e) {
eprintStackTrace();
}
}
}
運行這個程序就能生成一個 XML 數據文件如 清單
清單 XML 數據文件
<?xml version= encoding=UTF standalone=yes?>
<workcontactinfo>
<Location>Shanghaishuion</Location>
<Postal></Postal>
<tel>
<fix></fix>
<mobile></mobile>
</tel>
<Appellation>Mr Wang</Appellation>
</workcontactinfo>
回顧一下 Web 服務的 WSDL 文件如 圖 所示是一個符合 WC XMLSchema 規范的 schema 文件以及整個過程中生成的 Java 類我們應該能更好的理解 Web 服務開發部署使用的全過程首先 JDK 提供的工具 apt 根據 Web Service EndPoint 中相關的注釋生成一些與 WSDL schema 綁定的 Java 類察看這些類可以發現它們與 JAXB 例子中 generated 目錄下生成的 Java 文件十分相似接著通過 HTTP 服務將這個 WSDL schema 文件發布出來然後通過 wsimport 工具生成一個 Web 服務的客戶運行時代理相當於 清單 的功能最終 Web 服務的用戶程序同運行時代理交互該代理生成並傳遞形式如 清單 的 XML 數據文件圖 結合 表 給出了 Web 服務開發到使用整個周期的工作流和涉及到的 JDK 包
圖 Web 服務開發部署流程中 XML 技術的應用
總結
比較前一個版本的 JDK新版本對 XML 處理技術進行了擴展包括新加入的 StAX 和 JAXB基於這些新的 XML 數據處理技術JDK 對 Web 服務的支持也得到了大大的增強這些增強體現在引入了一些注釋和 API增加了更多的工具可以自動化大部分開發和部署的工作對於 XML 應用開發者來說有更多更有力地技術可以選用對於 Web 服務提供者來說開發工具更為強大開發流程更為簡化工作效率得到提高而對於 Web 服務的使用者更多的底層細節被屏蔽可以說新版 JDK 在對 XML 相關應用開發上的支持較前一個版本有了很大提升
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19218.html