Java--詳解WebService技術
一、什么是 webservice
WebService是一種跨編程語言和跨操作系統平台的遠程調用技術。
所謂跨編程語言和跨操作平台,就是說服務端程序采用java編寫,客戶端程序則可以采用其他編程語言編寫,反之亦然!跨操作系統平台則是指服務端程序和客戶端程序可以在不同的操作系統上運行。
謂遠程調用,就是一台計算機a上的一個程序可以調用到另外一台計算機b上的一個對象的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬調用的轉賬方法的代碼其實是跑在銀行服務器上。再比如,amazon,天氣預報系統,淘寶網,校內網,百度等把自己的系統服務以webservice服務的形式暴露出來,讓第三方網站和程序可以調用這些服務功能,這樣擴展了自己系統的市場占有率,往大的概念上吹,就是所謂的SOA應用。
從表面上看,WebService就是一個應用程序向外界暴露出一個能通過Web進行調用的API,也就是說能用編程的方法通過Web來調用這個應用程序。我們把調用這個WebService的應用程序叫做客戶端,而把提供這個WebService的應用程序叫做服務端。從深層次看,WebService是建立可互操作的分布式應用程序的新平台,是一個平台,是一套標准。它定義了應用程序如何在Web上實現互操作性,你可以用任何你喜歡的語言,在任何你喜歡的平台上寫Web service ,只要我們可以通過Web service標准對這些服務進行查詢和訪問。
WebService平台需要一套協議來實現分布式應用程序的創建。任何平台都有它的數據表示方法和類型系統。要實現互操作性,WebService平台必須提供一套標准的類型系統,用於溝通不同平台、編程語言和組件模型中的不同類型系統。Web service平台必須提供一種標准來描述Web service,讓客戶可以得到足夠的信息來調用這個Web service。最后,我們還必須有一種方法來對這個Web service進行遠程調用,這種方法實際是一種遠程過程調用協議(RPC)。為了達到互操作性,這種RPC協議還必須與平台和編程語言無關。
二、webservice采用什么技術
WebService平台由XML+XSD,SOAP和WSDL三大技術構成。
1、XML+XSD(封裝數據):
WebService采用HTTP協議傳輸數據,采用XML格式封裝數據(即XML中說明調用遠程服務對象的哪個方法,傳遞的參數是什么,以及服務對象的返回結果是什么)。XML是WebService平台中表示數據的格式。除了易於建立和易於分析外,XML主要的優點在於它既是平台無關的,又是廠商無關的。無關性是比技術優越性更重要的:軟件廠商是不會選擇一個由競爭對手所發明的技術的。
XML解決了數據表示的問題,但它沒有定義一套標准的數據類型,更沒有說怎么去擴展這套數據類型。例如,整形數到底代表什么?16位,32位,64位?這些細節對實現互操作性很重要。XML Schema(XSD)就是專門解決這個問題的一套標准。它定義了一套標准的數據類型,並給出了一種語言來擴展這套數據類型。WebService平台就是用XSD來作為其數據類型系統的。當你用某種語言(如VB.NET或C#)來構造一個Web service時,為了符合WebService標准,所有你使用的數據類型都必須被轉換為XSD類型。你用的工具可能已經自動幫你完成了這個轉換,但你很可能會根據你的需要修改一下轉換過程。
2、SOAP(傳輸協議):
WebService通過HTTP協議發送請求和接收結果時,發送的請求內容和結果內容都采用XML格式封裝,並增加了一些特定的HTTP消息頭,以說明HTTP消息的內容格式,這些特定的HTTP消息頭和XML內容格式就是SOAP協議。SOAP提供了標准的RPC方法來調用Web Service。
SOAP協議 = HTTP協議 + XML數據格式
SOAP協議定義了SOAP消息的格式,SOAP協議是基於HTTP協議的,SOAP也是基於XML和XSD的,XML是SOAP的數據編碼方式。打個比喻:HTTP就是普通公路,XML就是中間的綠色隔離帶和兩邊的防護欄,SOAP就是普通公路經過加隔離帶和防護欄改造過的高速公路。
3、WSDL(描述Web Service的文檔格式):
好比我們去商店買東西,首先要知道商店里有什么東西可買,然后再來購買,商家的做法就是張貼廣告海報。 WebService也一樣,WebService客戶端要調用一個WebService服務,首先要有知道這個服務的地址在哪,以及這個服務里有什么方法可以調用,所以,WebService務器端首先要通過一個WSDL文件來說明自己家里有啥服務可以對外調用,服務是什么(服務中有哪些方法,方法接受的參數是什么,返回值是什么),服務的網絡地址用哪個url地址表示,服務通過什么方式來調用。
WSDL(Web Services Description Language)就是這樣一個基於XML的語言,用於描述Web Service及其函數、參數和返回值。它是WebService客戶端和服務器端都能理解的標准格式。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。一些最新的開發工具既能根據你的Web service生成WSDL文檔,又能導入WSDL文檔,生成調用相應WebService的代理類代碼。
WSDL文件保存在Web服務器上,通過一個url地址就可以訪問到它。客戶端要調用一個WebService服務之前,要知道該服務的WSDL文件的地址。WebService服務提供商可以通過兩種方式來暴露它的WSDL文件地址:1.注冊到UDDI服務器,以便被人查找;2.直接告訴給客戶端調用者。
三、webservice開發的兩種形式
WebService開發可以分為服務器端開發和客戶端開發兩個方面:
服務端開發:把公司內部系統的業務方法發布成WebService服務,供遠程合作單位和個人調用。(借助一些WebService框 架可以很輕松地把自己的業務對象發布成WebService服務,Java方面的典型WebService框架包括:axis,xfire,cxf等,java ee服務器通常也支持發布WebService服務,例如JBoss。)
客戶端開發:調用別人發布的WebService服務,大多數人從事的開發都屬於這個方面,例如,調用天氣預報WebService服務。(使用廠商的WSDL2Java之類的工具生成靜態調用的代理類代碼;使用廠商提供的客戶端編程API類;使用SUN公司早期標准的jax-rpc開發包;使用SUN公司最新標准的jax-ws開發包。當然SUN已被ORACLE收購)
WebService的工作調用原理:對客戶端而言,我們給這各類WebService客戶端API傳遞wsdl文件的url地址,這些API就會創建出底層的代理類,我調用這些代理,就可以訪問到webservice服務。代理類把客戶端的方法調用變成soap格式的請求數據再通過HTTP協議發出去,並把接收到的soap數據變成返回值返回。對服務端而言,各類WebService框架的本質就是一個大大的Servlet,當遠程調用客戶端給它通過http協議發送過來soap格式的請求數據時,它分析這個數據,就知道要調用哪個java類的哪個方法,於是去查找或創建這個對象,並調用其方法,再把方法返回的結果包裝成soap格式的數據,通過http響應消息回給客戶端。
四、webservice開發步驟
- 客戶端接口開發步驟:
1、xml轉java的jar包生成:
本接口采用xmlbeans-2.5.0轉換接口中的xml為java對象。(xmlbeans-2.5.0在項目tool文件夾下),解壓然后在xmlbeans-2.5.0文件夾下新增
sxzy\gys\src三個文件夾
根據接口內容xml編寫xsd文件。參考gys.xsd的編寫(xsd編寫時候去掉xml的Item標簽)。放在sxzy\gys下。
>cd xmlbeans-2.5.0/bin
>scomp -src ..\sxzy\gys\src -out ..\sxzy\gys\gysinterface.jar ..\sxzy\gys\gys.xsd ..\sxzy\gys\gys.xsdconfig -compiler "C:\jdk142_04\bin\javac.exe"
gys.xsdconfig是對生成jar的類文件包的定義。里面內容如下:
<xb:config xmlns:xb=http://xml.apache.org/xmlbeans/2004/02/xbean/config>
<xb:namespace uri=http://www.gys.com/> (http://www.gys.com/)此處根據xsd頭定義的targetNamespace。
<xb:package>com.nb.adv.webservice.gys</xb:package>
</xb:namespace>
</xb:config>
2、將生成的jar包和xsd放在項目的interface下並將jar報添加到編譯路徑。
下面介紹具體供應商接口的開發。
與寫Action類似。只需要編寫控制層即可。
在nb.adv.result包下新增供應商接口的控制層類:GysControl.java (需要繼承抽象類 PIAbstractService)。
具體代碼參考GysControl。(其中的回調接口代碼基本上不用變)
3、根據接口文檔規范。供應商對應的我們這邊的項目業務定義為W8000MDM001,將其對應關系維護進pi.properties即可完成開發。
- 服務器端接口開發步驟:
1、數據准備:需要對方的wsdl文件或者WSDL地址(創建webservice,得到接口類),xml接收格式,表數據結構(為了將數據用xmlbeans封裝成xml文件);
2、xml轉java的jar包生成:
本接口采用xmlbeans-2.5.0轉換接口中的xml為java對象。(xmlbeans-2.5.0在項目tool文件夾下),解壓然后在xmlbeans-2.5.0文件夾下新增
sxzy\gys\src三個文件夾
根據接口內容xml編寫xsd文件(注意大小寫與xml一致)。參考gys.xsd的編寫(xsd編寫時候去掉xml的Item標簽)。放在sxzy\gys下。
>cd xmlbeans-2.5.0/bin
>scomp -src E:\opt\wl\src -out E:\opt\wl\interface\boxinventoryinterface.jar E:\opt\wl\interface\boxinventory.xsd E:\opt\wl\interface\boxinventory.xsdconfig -compiler "D:\Java\jdk1.6.0_21\bin\javac.exe"
gys.xsdconfig是對生成jar的類文件包的定義。里面內容如下:
<xb:config xmlns:xb=http://xml.apache.org/xmlbeans/2004/02/xbean/config> <xb:namespace uri=http://www.gys.com/> (http://www.gys.com/)此處根據xsd頭定義的targetNamespace。 <xb:package>com.nb.adv.webservice.gys</xb:package> </xb:namespace> </xb:config>
可以不必生成xsdconfig文件;
3、將生成的jar包和xsd放在項目的interface下並將jar報添加到編譯路徑。
在Java中對數據進行封裝成xml文件,實例如下:
CallHelper helper = initializeCallHelper("l_boxInventoryInterfaceList", form, request, false); helper.setParam("date1", request.getParameter("year")); helper.setParam("date2", request.getParameter("month")); helper.setParam("boxid", request.getParameter("boxid")); helper.setParam("personid", getPersonId(request)); helper.execute(); List<BasicDynaBean> list = helper.getResult("results"); //封裝成xml文件 com.nb.adv.webservice.boxinventory.InputDocument input = com.nb.adv.webservice.boxinventory.InputDocument.Factory.newInstance(); TAPSSmokeboxType delivery = input.addNewInput().addNewTAPSSmokebox(); for (BasicDynaBean bean : list) { com.nb.adv.webservice.boxinventory.ItemType item = delivery.addNewItem(); item.setFPlant(bean.get("from_id").toString()); item.setFPlantName(bean.get("from_name").toString()); item.setFMaterialNum(bean.get("brand").toString()); item.setFMaterialNumName(bean.get("matkx").toString()); item.setFYear(bean.get("year").toString()); item.setFMonth(bean.get("month").toString()); item.setFFactoryStock(bean.get("startinvent_num").toString()); item.setFMaterialFactoryStock(bean.get("startinvent_num1").toString()); item.setFReserved1(""); item.setFReserved2(""); item.setFReserved3(""); } Map<String,String> map = new HashMap<String,String>(); map.put("","http://www.boxinventory.com/"); XmlOptions options = new XmlOptions(); options.setUseDefaultNamespace(); options.setSaveImplicitNamespaces(map); options.setSavePrettyPrint();
4、將xml文件發送出去,通過wsdl生成Java類;
第一種方法:使用MyEclipse自動生成webservice客戶端(步驟參考word文件);
第二種方法:對於接口有復雜自定義類型返回的,最好根據wsdl生成java類
1. 建立一個web工程wsdl,將axis的包拷貝到lib下(共8個)
2. 點擊run新建一個java applation,選擇WSDL2JAVA.
3. 選擇第二個選項”Arguments”,在Program arguments:中輸入wsdl地址;
4. 點擊apply----Run即生成相應類;
實例代碼如下所示:
SIDNInfoOutbAsynService service = new SIDNInfoOutbAsynService(); SIDNInfoOutbAsyn out = service.getHTTPSPort(); DTDNInfo msg = new DTDNInfo(); msg.setBIZTYPE("TMS002");//此處固定不變 msg.setSOURCE("W-8000-TMS");//此處固定不變 msg.setMSGID(OptionUtil.getNo(5));//此處固定不變 msg.setTIME(OptionUtil.getSystemDateFormate("HHmmss"));//此處固定不變 msg.setDATE(OptionUtil.getSystemDateFormate("yyyyMMdd"));//此處固定不變 msg.setMSGCODE("A1-201");//此處固定不變 msg.setRETRYCOUNT("0");//此處固定不變 msg.setBACKUP1(""); msg.setBACKUP2(""); msg.setBACKUP3(""); msg.setDestination("N8000TMS006");///此處為 目標系統編碼+業務編碼 msg.setSXmlString(input.xmlText(options));//此處固定不變 out.siDNInfoOutbAsyn(msg);
下面介紹具體供應商接口的開發。
與寫Action類似。只需要編寫控制層即可。
在nb.adv.result包下新增供應商接口的控制層類:GysControl.java (需要繼承抽象類 PIAbstractService)。
具體代碼參考GysControl。(其中的回調接口代碼基本上不用變)
4、根據接口文檔規范。供應商對應的我們這邊的項目業務定義為W8000MDM001,將其對應關系維護進pi.properties即可完成開發。