還記得我剛剛以一個實習生的身份進入一家給電信,聯通等做經營分析系統的中型公司之後的半個月後,經理突然對我說交給我一個大case,我嚇了一跳,在那僅僅留給我0.5秒思考的時間中我想到,第一,我剛剛來這個公司,業務什麼的都沒有了解,怎麼開始做項目,第二,經理直接到我跟前說這句話,是不是意味着只有我自己做,第三,雖然我在學校的時候做過很多的項目,但是都是一些小打小鬧,沒有什麼嚴格性可言,怎麼能在這麼短的時間內交給我這個艱鉅的任務呢....終於,0.5秒的思考之後,所有的一切被證實了,的確是我自己做,而且是一個不小的項目--給聯通公司做iphone版的經營分析系統的服務端,不過公司總部規定好了用webService組件來開發,經理說給我三天時間掌握webService,從而能迅速的進入項目開發。但這是我第一次聽到webService,以前做的所有的應用都用spring+struts+hibernate框架,於是我從這一刻開始,我進入了短暫了webService學習中...
正如學習英文單詞要了解它的意思一樣,首先要了解什麼是webService的概念:Web Services使我們能夠在網絡上建立分佈式系統,應用程序組件可以通過任何平臺、任何語言和任何方式訪問。無論應用程序如何開發,使用了什麼語言,以及運行在什麼操作系統平臺上,只要它作爲Web Service,並且爲協同解決問題而設計,那麼你的應用程序,以任何語言開發或在任何平臺上,都可以利用它的服務。這是Web Service的主要概念。
webService 標準中有關的主要技術:
---XML:在Web Services環境中各層之間進行傳遞的默認數據格式。
---SOAP:封裝和交換信息的默認協議。第一次被提出時,它是隻取Simple Object Access Protocol(簡單對象訪問協議)的首字母。但是現在SOAP更多被認爲是一個特定的名詞,以它自己而命名,同樣很多人認爲這是用詞不當:SOAP實際上不是用來訪問對象的。另外,它也不再簡單。
---WSDL(Web Services Description Language,Web Services描述語言):描述Web Services的語言。儘管基於XML並且可以被人理解,WSDL主要是由機器處理,由客戶端程序讀取和理解。
Provider是提供服務的應用程序組件,Requester是使用服務的客戶端程序。很多其他技術也會參與到交互中。
XFire是一個免費的開源SOAP框架,它不僅可以極大方便地實現這樣一個環境,並且可以提供許多Web Services規範中高級特徵,這些特徵在多數的商業或者開源工具都沒有提供。你要恰當的理解這些單詞:great ease and simplicity(非常輕鬆和簡單)。你將會看到使用XFire創建Web Services是多麼的簡單。
假如你的Web應用有一個Java類,並且你想把它的一個方法發佈爲Web Services,當使用XFire時,你不需要編寫一行額外的Java代碼。只需要編輯發佈描述符,然後你就會得到一個Web Services。是的,它相當地簡單。我們來看一個例子。就以我自己做的這個項目而言:
服務器是運行在J2SE1.4.2_07下的Apache Tomcat5.5.7。假定你已經瞭解如何使用Java編寫Web應用程序,並知道應該如何把它部署到Apache Tomcat服務器上,那麼我們假定這個應用很簡單,我只列舉其中一個方法,就是用戶的登陸方法。簡單吧!那先看這個class類
public class IphoneServiceImp implements IphoneService {
IphoneDao iphoneDao = new IphoneDao();
public String login(String username, String password,String flag) {
return flag+"?"+iphoneDao.login(username, password);
}
}
所有的查詢數據庫的任務都由iphoneDao來做,不過我這裏和數據庫交互所用到的技術是ibatis,畢竟使用它所編寫的sql要比hibernate靈活的太多!注意:這裏的IphoneServiceImp要有一個默認的構造方法,否則,XFire不能夠初始化這個類。因爲使用接口的設計是一個好的實踐,所以我這裏也使用了接口隔離原則,該IphoneService接口裏也有這個方法,
public interface IphoneService {
String login(String username, String password,String flag);
}
在實際實現中,這樣一個方法可能包括各種類型的複雜調用、查詢和處理操作。而且可以有很多個這些專做業務的方法,但是我們的示例代碼已經最小化了,以至於我們可以集中精力在主要目標上:把這個方法發佈爲Web Services。
你可以看到IphoneServiceImp 是一個普通的Java類,沒有任何代碼告訴我們它將會在Web Services中使用。好的,這裏我們不需要增加任何東西。我們所有的工作都在部署描述符裏完成。
Web應用的部署描述符
在Java中,Web應用程序通常需要至少一個部署描述符(叫做web.xml)對其進行配置。XFire本身是一個基於servlet的應用程序。因此,我們需要增加必要的引用到描述符文件中。然後我們還必須配置將要創建的Web Services。我們使用一個稱爲services.xml的新文件來完成這件事。
web.xml
首先,修改web.xml。我們需要增加下面的XFire servlet相關的條目:
<servlet>
<servlet-name>XFireServlet</servlet-name>
<display-name>XFire Servlet</display-name>
<servlet-class>org.codehaus.xfire.transport.http.XfireConfigurableServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</servlet>
services.xml
現在我們不得不說一下我們的Web Services的由什麼組成的了。這由一個叫做services.xml的文件完成,它存放在META-INF/xfire目錄下,而這整個目錄放在WEB-INF/classes文件夾中,它在Web應用程序的標準類路徑中。這裏是services.xml中的基本配置條目:
<beans xmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>IphoneService</name>
<namespace>services</namespace>
<serviceClass>bonc.com.cn.services.IphoneService</serviceClass>
<implementationClass>bonc.com.cn.services.IphoneServiceImp</implementationClass>
</service>
</beans>
讓我們看看這裏都包含了什麼內容。Web Services的定義包含在元素中,它還含有一些子元素。第一個子元素是,它可以是你提供任何的合法名字。這將會被客戶端程序和其它需要定位你的服務的組件用到。例如,在服務準備好以後,你將在瀏覽器上使用這個名字來查看WSDL。
下一個子元素是<namespace>。任何合法的XML名字都是可以的。<namespace>用來唯一標識你的服務的各個參數。
<serviceClass>元素包含了Java類的名字,它指定了方法簽名。在我們的例子中,它是接口IphoneService。如果Java類沒有實現任何接口,你就需要把類的名字放在這裏。在你的Java類或者接口中可能有幾個方法。只需要一個入口把它們全部發布爲Web Services。
<implementationClass>保存了實現方法的Java類名。這是一個可選元素。如果上一個元素<serviceClass>包含了一個接口,那麼相應的實現類必須在這裏指定。
就是這樣。我們的Web Services配置完成了。
XFire和其它類庫
現在是最後一步了,需要得到所有必需的類庫。我們怎樣得到它們呢?去XFire網站,下載xfire-distribution-1.0.zip,然後解壓到一個本地文件夾。複製下面的jar文件和它的庫文件夾到WEB-INF/lib中:
? activation-1.0.2.jar
? commons-codec-1.3.jar
? commons-httpclient-3.0.jar
? commons-logging-1.0.4.jar
? jaxen-1.1-beta-8.jar
? jdom-1.0.jar
? log4j-1.2.x.jar
? mail-1.3.3_01.jar
? spring-1.2.x.jar
? stax-api-1.0.jar
? wsdl4j-1.5.2.jar
? wstx-asl-2.9.jar
? xbean-2.1.0.jar
? xbean-spring-2.2.jar
? xfire-all-1.0.jar
? XmlSchema-1.0.jar
一切妥當。我們來部署和啓動應用程序。爲了部署示例應用,只需要複製iphoneService.war到Apache Tomcat的webapps文件夾中,再等待幾秒鐘。它將會自動啓動。這個應用的全部源代碼也包含在這個war文件中。我們的程序已經準備作爲一個Web Service了。我們如何知道Web Service正在工作呢?
爲了瞭解Web Service是否正在工作,我們需要測試。首先,我們測試來看WSDL是否可用。我們在瀏覽器中輸入URL。哪個URL?因爲我們的應用程序的war文件是websvc.war,並且在services.xml中給出的服務名是IphoneService,WSDL的URL應該是:http://localhost:8080/iphoneService/services/IphoneService?wsdl。
請注意:URL的第一部分,例如,http://localhost:8080,可能會根據你的應用服務器不同而不同。無論怎樣,當你輸入URL後,將會看到一個XML文檔,它的根元素是。這個文檔叫做服務的WSDL。如果你看到了,這就是你的應用作爲Web Service已經可用的第一個證明。
但是這個測試是不夠的。可能會發生這種情況,可以看到WSDL,但是從客戶端程序可能會訪問不到服務。因此爲了覈實服務是否可以訪問了,我們必須使用一個客戶端進行服務的實際調用來進行一個真正的測試。
開發一個客戶端(手動開發)
你可以使用任何的SOAP工具創建客戶端,例如,.Net或者Apache Axis,有很多種方法:使用從WSDL產生的stubs,使用動態代理,等等。在例子中,我們使用一個動態代理,以一個簡單的Servlet形式,叫做WsClient.java。爲了保持代碼兩最小,所有在屏幕顯示的元素都放在了doGet()方法中。對Web Service的實際調用由callWebService()方法完成,它相當地簡單。和下面的類似:
/* Call the Web service
*
*/
public String callWebService(
String username, String password,String flag)
throws MalformedURLException, Exception {
//Create a metadata of the service
Service serviceModel = new ObjectServiceFactory().create(IphoneServiceImp.class);
log.debug("callSoapServiceLocal(): got service model." );
//Create a proxy for the deployed service
XFire xfire = XFireFactory.newInstance().getXFire();
XFireProxyFactory factory = new XFireProxyFactory(xfire);
String serviceUrl = "http://localhost:8080/iphoneService/services/IphoneService";
IphoneService client = null;
try {
client = (IphoneService ) factory.create(serviceModel, serviceUrl);
} catch (MalformedURLException e) {
log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());
}
//Invoke the service
String serviceResponse = "";
try {
serviceResponse = client.login(username,password,flag);
} catch (Exception e){
log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());
serviceResponse = e.toString();
}
log.debug("WsClient.callWebService(): status=" + serviceResponse);
//Return the response
return serviceResponse;
}
這個代碼是如何工作的呢?我來解釋一下:首先,我們創建一個服務模型,它包含服務的說明——換句話說,就是服務的元數據。我們使用XFire的ObjectServiceFactory從IphoneServiceImp.class接口創建這個模型。
接着,爲XFire獲得一個代理工廠對象,它包含了常規的代碼,也相當地簡單和易懂。這一步中沒有任何特定應用的東西。從這個proxyFactory,使用服務模型和服務端點URL(用來獲得WSDL),我們可以得到一個服務的本地代理。就是它了。這個代理就是實際的客戶端。現在,我們可以調用它的login()方法來得到我們需要的Web Service。
一旦示例應用發佈並啓動,就可以嘗試servlet URL:
http://localhost:8080/iphoneService/ws。
這個Servlet使用默認參數來調用Web Service和顯示接收到的響應。頁面的最後兩行應該讀取:
Response Received
COMPLETED: CDN$ 500.00 was successfully transferred from A/C# 11111-01234 to A/C# 99999-05678
現在你可以確定Web Service已經發布並且在運行中了。
或者用第三方插件開發一個客戶端
步棸:先在myeclipse中安裝xfire的插件 地址是:http://dist.codehaus.org/xfire/update/
1,新建一個JavaProject的項目,名字暫時就叫做client。
2,在new時,找到xfire選項中的code generation from WSDL document
之後不言而喻,一路到底就可以自動安裝好,基於自己配置的wsdl地址下的webservice客戶端就安裝好了,是不是很方便?
基本的Web Services開發步驟清單
這個清單總結了將一個Java方法發佈爲Web Service所必須的步驟:
1、 檢查Java類的方法和默認構造函數確保爲public
2、 增加XFire servlet相關條目到web.xml中
3、 創建services.xml,把它放到WEB-INF/classes/META-INF/xfire目錄下
4、 增加XFire和第三方包到你的Web應用的WEB-INF/lib文件夾中
這就是所有需要的步驟,是的,相當簡單。
一些XFire的其他高級特性
XFire的使用可能比較簡單,但是在特性和功能性上,它卻佔據着領導者的位置。下面是它的高級特性:
---本地數據綁定支持POJOs(plain-old Java objects)、XMLBeans、JAXB(Java Architecture for XML Binding)、Castor等等。數據綁定說明了Web Services的XML請求和映射到Java對象的XML響應。
---使用StAX(Streaming API for XML)處理XML文檔。同DOM的基於樹和SAX的事件驅動的處理方式相比,StAX使用了拉(pull)機制,它使處理更快速,內存效率更高。
---支持多種傳輸協議,如HTTP、JMS(Java Message Service)和JVM內部傳輸。
---嵌入式,這是XFire的核心功能之一。你可以把這個SOAP引擎嵌入到你的應用中,完全隱藏所有XFire特定引用,同樣所有配置都是程序驅動。
---豐富的API,它使XFire可高度自定義,允許開發者在不同的階段截獲請求,並且對他們進行處理。
---兼容最新的標準例如SOAP1.1(沒有加密遠程工程調用,或者RPC)和1.2、WSDL1.1、the Web Services Interoperability Organization’s Basic Profile 1.0、Web Services Addressing和WS-Security。
最重要的是,XFire屬於新一代Web Services引擎。不僅僅是營銷用語,“新一代”有一些重要的意義。Apache Axis是第一代Java語言的Web Services引擎,已經成爲了所有後來工具的參考標準。在過去的幾年裏,Axis以及這些其它的工具已經在很多生產環境中進行了實地測試。從中得出的一個關鍵的問題就是Web Services並不最適合RPC類型的通信。對於性能和效率,面向文檔的消息形式是最好的方式。但是Apache Axis和很多其他的Web Services引擎都被設計成了面向RPC的(儘管它們支持文檔形式)。現在,整個行業正在開發新一代的SOAP引擎,設計爲面向文檔的。Apache已經宣佈結束舊版本的Axis引擎開發,現在專注於Axis2,現在它的預發佈版本是0.95。XFire在今年的2月份發佈了它的第一個產品版本(1.0)。它的下一個版本(1.1)僅僅在幾個星期之後就進行了發佈。性能
Web Services需要消耗很多資源,但是性能方面它們不是那麼引人注目。XFire打破了這種趨勢。它消耗更少的內存(部分因爲 StAX的使用),但是表現卻比多數可比較的SOAP引擎出色。你可以在資源中提供的鏈接中看到比較的結果。
此外,XFire還提供了各種方法來進一步優化性能。一個方法是使用JVM內置傳輸(in-JVM transport)。如果你知道Web Services和客戶端運行在同一個JVM上,你可以選擇使用本地傳輸,它可以大幅提升性能。在示例中的客戶端代碼,看以下指定服務端點URL的這行:
String serviceUrl = http://localhost:8080/iphoneService/services/IphoneService;
替換爲
String serviceUrl = "xfire.local://IphoneService";
你會看到性能上的明顯提高,因爲它繞過了整個網絡層。
侷限性
XFire有些重要的侷限性你應該清楚:
---開發Web Services的好的實踐是從WSDL開始。大部分的SOAP引擎提供了從WSDL生成服務stub的工具。XFire也提供了這樣一個工具。但是它是基於註釋(annotations-based)的,因此需要J2SE5.0。對於仍堅持使用J2SE1.4.x的人來說,它不是一個令人拍手叫好的工具,因爲我們有很多其他方式來編寫客戶端,一個就是文章中演示的方式。
---附件支持,它將會包含在未來發行的版本中。
---易於學習的用戶嚮導。XFire團隊在這個方面還有很多工作需要做。
結論
Java當前的趨勢是簡化技術的使用。因此,我們正看到一波基於POJO的開發成就。同時,面向服務架構(SOA,Services-oriented architecture)和Web Services已經變成了當前行業的熱點話題。XFire正是在這種情況下產生的。它能夠使POJO發佈爲最少的Web Services,而只需要付出最小化的努力。從而,它使希望使用這項技術的初級開發者的學習曲線變得平緩。同時,由於它兼容最新標準和提供了豐富的API,XFire爲高級用戶提供了更多的大好機會。