1. 目的
提供一種服務,能支持任何平臺、任何語言和任何方式訪問,使它們可以在不同平臺,不同語言間進行通信。
利用Eclipse推薦使用的插件XFire 來快速開發WebService, XFire是一個免費的開源SOAP框架, 當使用XFire時,你不需要編寫一行額外的Java代碼。隻需要編輯發佈描述符,然後你就會得到一個Web Services。有利於減少錯誤,提高開發效率,快速提供對外接口,以供客戶端使用。
2. 范圍
利用Eclipse推薦使用的插件XFire 來快速開發WebService,支持任何平臺、任何語言和任何方式訪問。服務采用xfire方式,客戶端有axis、xfire方式兩種。
3. 技術術語
XFire是一個免費的開源SOAP框架,它不僅可以極大方便地實現這樣一個環境,並且可以提供許多Web Services規范中高級特征,這些特征在多數的商業或者開源工具都沒有提供。
lWeb Service:使我們能夠在網絡上建立分佈式系統,應用程序組件可以通過任何平臺、任何語言和任何方式訪問。無論應用程序如何開發,使用瞭什麼語言,以及運行在什麼操作系統平臺上,隻要它作為Web Service,並且為協同解決問題而設計,那麼你的應用程序,以任何語言開發或在任何平臺上,都可以利用它的服務。
XML: 在Web Services環境中各層之間進行傳遞的默認數據格式。所以使用XML是因為它的獨立於編程語言,良好的可擴展性以及強大的工業支持。
SOAP: 封裝和交換信息的默認協議。Simple Object Access Protocol(簡單對象訪問協議)的首字母。SOAP是XML文檔形式的調用商業方法的規范,它可以支持不同的底層接口,象HTTP(S)或者SMTP。SOAP的強大是因為它簡單。SOAP是一種輕量級的,非常容易理解的技術,並且很容易實現。它有工業支持,可以從各主要的電子商務平臺供應商那裡獲得。從技術角度來看,SOAP詳細指明瞭如何響應不同的請求以及如何對參數編碼。一個SOAP封裝瞭可選的頭信息和正文,並且通常使用HTTP POST方法來傳送到一個HTTP 服務器,當然其他方法也是可以的,例如SMTP。SOAP同時支持消息傳送和遠程過程調用。
基本流程如圖
Webservice 的概念是使用一個標準的輸出接口來定義代碼提供的功能,以便讓外界可以通過這個標準的輸出接口來調用,而所謂的標準輸出接口就是wsdl,wsdl是一個xml組成的文件,描述瞭實現程序對外提供函數的原型,客戶端可以通過wsdl來調用實現程序提供的服務代碼。
UDDI (Universal Description, Discovery, and Integration) 是一個主要針對Web服務供應商和使用者的新項目。UDDI 項目中的成員可以通過UDDI Business Registry (UBR) 來操作Web服務的調用,UBR是一個全球性的服務。Web服務供應商可以在UBR中描述並且註冊他們的服務。 用戶可以在UBR中查找並定位那些他們需要的服務。UDDI是一種根據描述文檔來引導系統查找相應服務的機制。
WSDL
對於商業用戶來說,要找到一個自己需要使用的服務,他必須知道如何來調用。WSDL (Web Services Description Language) 規范是一個描述接口,語義以及Web服務為瞭響應請求需要經常處理的工作的XML文檔。這將使簡單地服務方便,快速地被描述和記錄。
WSDL文檔可以分為兩部分。頂部分由抽象定義組成,而底部分則由具體描述組成。抽象部分以獨立於平臺和語言的方式定義SOAP消息,它們並不包含任何隨機器或語言而變的元素。這就定義瞭一系列服務,截然不同的網站都可以實現。隨網站而異的東西如序列化便歸入底部分,因為它包含具體的定義。
l. 抽象定義
Types 獨立與機器和語言的類型定義
Messages 包括函數參數(輸入與輸出分開)或文檔描述
PortTypes 引用消息部分中消息定義來描述函數簽名(操作名、輸入參數、輸出參數)
2. 具體定義
Bindings PortTypes部分的每一操作在此綁定實現
Services 確定每一綁定的端口地址
各Messages欄使用Types欄的定義,PortTypes欄使用Messages欄的定義;Bindings欄引用瞭PortTypes欄,Services欄引用Bindings欄,PortTypes和Bindings欄包含瞭operation元素,而Services欄包含瞭port元素。PortTypes欄裡的operation元素由Bindings欄裡的operation元素進一步修改或描述。
註意:文檔之中可能隻有一個Types欄,或根本沒有。所有其他的欄可以隻有零元素、單元素或是多元素。WSDL的列表要求所有的欄以固定的順序出現:import, types, message, portType, binding, service。所有的抽象可以是單獨存在於別的文件中,也可以從主文檔中導入。
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="FooSample" targetNamespace="http://tempuri.org/wsdl/"
xmlns:wsdlns="http://tempuri.org/wsdl/" xmlns:typens="http://tempuri.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://tempuri.org/xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" elementFormDefault="qualified" >
</schema>
</types>
<message name="Simple.foo"> <part name="arg" type="xsd:int"/> </message>
<message name="Simple.fooResponse"><part name="result" type="xsd:int"/></message>
<portType name="SimplePortType">
<operation name="foo" parameterOrder="arg" >
<input message="wsdlns:Simple.foo"/>
<output message="wsdlns:Simple.fooResponse"/>
</operation>
</portType>
<binding name="SimpleBinding" type="wsdlns:SimplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/Simple.foo"/>
<input>
<soap:body use="encoded" namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
<service name="FOOSAMPLEService">
<port name="SimplePort" binding="wsdlns:SimpleBinding">
<soap:address location="http://carlos:8080/FooSample/FooSample.asp"/>
</port>
</service>
</definitions>
第一行申明該文檔是XML。盡管這並不是必需的,但它有助於XML解析器決定是否解析WSDL文件或隻是報錯。
第二行是WSDL文檔的根元素:<definitions>。一些屬性附屬於根元素,就像<schema>子元素對於<types>元素。
<types>元素包含瞭Types欄。如果沒有需要聲明的數據類型,這欄可以缺省。在WSDL范例中,沒有應用程序特定的types聲明,但我仍然使用瞭Types欄,隻是為瞭聲明schema namespaces。
<message>元素包含瞭Messages欄。如果我們把操作看作函數,<message>元素定義瞭那個函數的參數。<message>元素中的每個<part>子元素都和某個參數相符。輸入參數在<message>元素中定義,與輸出參數相隔離–輸出參數有自己的<message>元素。兼作輸入、輸出的參數在輸入輸出的<message>元素中有它們相應的<part>元素。輸出<message>元素以"Response"結尾,就像以前所用的"fooResponse"。每個<part>元素都有名字和類型屬性,就像函數的參數有參數名和參數類型。
一個PortTypes欄中,可以有零個、單個或多個<portType>元素。由於抽象PortType定義可以放置在分開的文件中,在某個WSDL文件中沒有<portType>元素是可能的。上面的例子裡隻是用瞭一個<portType>元素。而一個<portType>元素可在<operation>元素中定義一個或是多個操作。示例僅使用瞭一個名為"foo"的<operation>元素。這和某個函數名相同。<operation>元素可以有一個、兩個、三個子元素:<input>, <output> 和<fault>元素。每個<input>和<output>元素中的消息都引用Message欄中的相關的<message>元素。
Bindings欄可以有零個、一個或者多個<binding>元素。它的意圖是制定每個<operation>通過網絡調用和回應。Services欄同樣可以有零個、一個、多個<service>元素。它還包含瞭<port>元素,每個<port>元素引用一個Bindings欄裡的<binding>元素。Bindings和Services欄都包含WSDL文檔。
4. 準備工作
操作系統:winxp或win2k
開發工具:jdk 1.4以上版本,tomcat5.0以上版本+eclipsea3.2
Myeclipse5.1(可選)
註意:當使用jdk1.5 與tomcat5.0 全出異常。
異常信息為:provider org.apache.xalan.processor.T。
錯誤原因:
是由於jdk1.5 與tomcat5.0之間的關於TransformerFactoryImpl 類的沖突造成的。
解決方式:將會在異常處理中有詳述。
5. 服務器編寫
服務采用xfire方式,客戶端有axis、xfire方式兩種。
5.1 第一步: 新建web Service 工程項目
點擊 【Next】 進入下一步個操作。
點擊 【Next】 進入下一步個操作。
點擊 【Next】 進入下一步個操作。
此步驟中Xfire 1.2 HTTP Client Libraries 中可選項。
點擊 【Finish】 完成項目創建工作。
web.xml中配置XFire的Servlet及其配置
5.2 第二步: 提供服務接口
服務端接口定義如下 :
package com.smt.service;
/******************************************************
*
* 功能描述: WebService Xfire 對象提供服務接口類</br></br>
*
* 作者:chenab </br></br>
*
* 創建時間:2011-7-14 上午11:22:26</br></br>
*
* 版本號:V1.0 </br></br>
*****************************************************/
public interface IBankingService {
public String transferFunds(String fromAccount);
}
5.3 第三步: 提供服務接口實現類
服務接口實現類如下:
package com.smt.service;
/*****************************************************
*
* 功能描述: webService XFire 服務接口實現類</br></br>
*
* 作者:chenab</br></br>
*
* 創建時間:2011-7-14 上午11:28:47</br></br>
*
* 版本號:V1.0 </br></br>
*******************************************************/
public class BankingService implements IBankingService {
public BankingService() {
}// 空構造不可少
public String transferFunds(String fromAccount) {
String str=" 恭喜, 服務端測試成功! "+fromAccount;
System.out.println(str);
return str;
}
}
Web Servivce 的發佈的—–services.xml的配置(此步也可手動修改)
生成後的的項目工程結構圖, 如下圖所示:
5.4 第四步: 發佈服務
將項目發佈到Tomcat 服務器,並運行Tomcat ,服務啟動後,在地址欄中輸入如下信息,如果有XML信息生成,則表示Web服務成功。
5.5 第五步: 測試
當服務啟動後,打開Eclipse 。
第一步:在eclipse 工具欄上選擇者Web Service Exploer 如下圖1所示。
第二步:在打開的標簽窗口中,選擇WSDL如下圖2所示。
第三步:選擇左側[WSDL Main],在右側將會出現如下圖3所示,在地址欄中輸入“服務地址”。
然後點擊[Go],將在彈出如下圖所示信息,在窗口中輸入 參數信息,然後點擊[Go],如下圖所示,要下欄出現如下圖信息。
6. 異常處理
6.1 第一種:JDK 與Tomcat 版本不匹配
異常信息:provider org.apache.xalan.processor .TransformerFactoryImpl
原因:由於jdk1.5 與tomcat5.0之間的關於TransformerFactoryImpl 類的沖突造成的。tomcat-5.0.28\common\endorsed下有兩個jar包:xercesImpl.jar和xml-apis.jar,其中的類javax.xml.transform.TransformerFactory與jdk1.5中的類org.apache.xalan.processor.TransformerFactoryImpl其實是同一個類。
解決辦法一:
將xml-apis.jar移出endorsed文件夾。
用xalan系列jar包替換原來的xercesImpl.jar和xml-apis.jar。
xalan系列jar包:serializer.jar、xalan.jar、xercesImpl.jar和xml-apis.jar。
For other application, just check this file or dom3-xml-apis.jar in your class path.
解決辦法二:
使用1.4的JDK和tomcat5.0 或者JDK1.5 tomcat5.5 這2種類型才是匹配。
6.2 第二種:JDK低版本無法執行高版本編譯的類文件
異常信息:java.lang.UnsupportedClassVersionError
原因:因為我們使用高版本的JDK編譯的Java class文件試圖在較低版本的JVM上運行,所報的錯誤。錯誤尤其在JDK5與JDK5之前的版本上表現明顯。因為,JDK5在Java語法上作瞭不少增強,引入瞭一些新的.class文件的元素,導致舊版本的JVM無法解釋、執行.class文件。即使這個類並沒有使用任何JDK5的新元素,但是JDK5生成的.class文件,JDK1.4及其以前的JVM都無法辨認!
解決辦法:
右鍵點擊工程文件,選擇屬性(properties),
在屬性窗口中選擇Build–>Java,在右邊的選項中有四個下拉框,就可以看到編譯選項瞭,
其中Compiler和Debug Option可以不用管,隻在Languege features和Target VM中選擇相應的JDK版本就可以瞭,然後確定,一切OK。
6.3 第三種:Jboss 與Tomcat 間存在共同包沖突
異常信息:The method getJspApplicationContext(ServletContext) is undefined for the type
原因:服務器環境Jboss,Java程由Tomcat5.5工程目錄直接拷貝,由於WEB-INF/lib下存在jsp-api.jar、servlet-api.jar,與Jboss自帶的jar包沖突造成。
解決辦法:刪除WEB工程Lib目錄中的jsp-api.jar、servlet-api.jar,重新啟動Jboss服務問題解決。
在創建工程時,jsp-api.jar、servlet-api.jar這兩個jar包都無需手工加入到web工程中,tomcat與jboss都已包含。
本文出自 “吹牛皮拉潛艇推火車日飛機” 博客