|
一、SOA和webservice SOA(service-Oriented Architecture)是面向服務(wù)的架構(gòu),是一個(gè)組件模型,它將應(yīng)用程序的不同功能單元(稱(chēng)為服務(wù))通過(guò)這些服務(wù)之間定義良好的接口和契約聯(lián)系起來(lái)。接口是采用中立的方式進(jìn)行定義的,它應(yīng)該獨(dú)立于實(shí)現(xiàn)服務(wù)的硬件平臺(tái)、操作系統(tǒng)和編程語(yǔ)言。這使得構(gòu)建在各種各樣的系統(tǒng)中的服務(wù)可以使用一種統(tǒng)一和通用的方式進(jìn)行交互。web service是一個(gè)平臺(tái)獨(dú)立的,低耦合的,自包含的、基于可編程的web的應(yīng)用程序,可使用開(kāi)放的XML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)子集)標(biāo)準(zhǔn)來(lái)描述、發(fā)布、發(fā)現(xiàn)、協(xié)調(diào)和配置這些應(yīng)用程序,用于開(kāi)發(fā)分布式的互操作的應(yīng)用程序。web service是實(shí)現(xiàn)SOA架構(gòu)的一種技術(shù),XML+XSD,SOAP和WSDL就是構(gòu)成WebService平臺(tái)的三大技術(shù)。 1、XML+XSD: XML是WebService平臺(tái)中表示數(shù)據(jù)的格式。 WebService采用HTTP協(xié)議傳輸數(shù)據(jù),采用XML格式封裝數(shù)據(jù)(即XML中說(shuō)明調(diào)用遠(yuǎn)程服務(wù)對(duì)象的哪個(gè)方法,傳遞的參數(shù)是什么,以及服務(wù)對(duì)象的返回結(jié)果是什么)除了易于建立和易于分析外,XML主要的優(yōu)點(diǎn)在于它既是平臺(tái)無(wú)關(guān)的,又是廠(chǎng)商無(wú)關(guān)的。 XSD(XML Schema)解決了數(shù)據(jù)數(shù)據(jù)類(lèi)型的問(wèn)題,例如,整形數(shù)到底代表什么?16位,32位,64位?它定義了一套標(biāo)準(zhǔn)的數(shù)據(jù)類(lèi)型,并給出了一種語(yǔ)言來(lái)擴(kuò)展這套數(shù)據(jù)類(lèi)型。WebService平臺(tái)就是用XSD來(lái)作為其數(shù)據(jù)類(lèi)型系統(tǒng)的。當(dāng)你用某種語(yǔ)言(如VB.NET或C#)來(lái)構(gòu)造一個(gè)Web service時(shí),為了符合WebService標(biāo)準(zhǔn),所有你使用的數(shù)據(jù)類(lèi)型都必須被轉(zhuǎn)換為XSD類(lèi)型。 2、SOAP SOAP即簡(jiǎn)單對(duì)象訪(fǎng)問(wèn)協(xié)議(Simple Object Access Protocol),它是用于交換XML。WebService通過(guò)HTTP協(xié)議發(fā)送請(qǐng)求和接收結(jié)果時(shí),發(fā)送的請(qǐng)求內(nèi)容和結(jié)果內(nèi)容都采用XML格式封裝,并增加了一些特定的HTTP消息頭,以說(shuō)明HTTP消息的內(nèi)容格式,這些特定的HTTP消息頭和XML內(nèi)容格式就是SOAP協(xié)議。SOAP提供了標(biāo)準(zhǔn)的RPC方法來(lái)調(diào)用Web Service。 SOAP協(xié)議 = HTTP協(xié)議 + XML數(shù)據(jù)格式。 3、WSDL WSDL是Web Service描述語(yǔ)言,用于描述Web Service及其函數(shù)、參數(shù)和返回值。它是WebService客戶(hù)端和服務(wù)器端都能理解的標(biāo)準(zhǔn)格式。因?yàn)槭腔赬ML的,所以WSDL既是機(jī)器可閱讀的,又是人可閱讀的,這將是一個(gè)很大的好處。一些最新的開(kāi)發(fā)工具既能根據(jù)你的Web service生成WSDL文檔,又能導(dǎo)入WSDL文檔,生成調(diào)用相應(yīng)WebService的代理類(lèi)代碼。WSDL文件保存在Web服務(wù)器上,通過(guò)一個(gè)url地址就可以訪(fǎng)問(wèn)到它??蛻?hù)端要調(diào)用一個(gè)WebService服務(wù)之前,要知道該服務(wù)的WSDL文件的地址。WebService服務(wù)提供商可以通過(guò)兩種方式來(lái)暴露它的WSDL文件地址:1.注冊(cè)到UDDI服務(wù)器,以便被人查找;2.直接告訴給客戶(hù)端調(diào)用者。 二、調(diào)用webservice的本質(zhì) 調(diào)用一次webservice的本質(zhì)如下: 1、客戶(hù)端把調(diào)用方法參數(shù)轉(zhuǎn)換生成XML文檔片段(SOAP消息),且該文檔必須符合WSDL定義的格式; 2、通過(guò)http協(xié)議把XML文檔片段傳給服務(wù)器; 3、服務(wù)器接受到XML文檔片段; 4、服務(wù)器解析XML文檔片段,提取其中的數(shù)據(jù); 5、服務(wù)器執(zhí)行方法; 6、服務(wù)器把執(zhí)行方法得到的返回值轉(zhuǎn)換成符合WSDL定義的XML文檔片段; 7、通過(guò)http協(xié)議把XML文檔片段傳輸給客戶(hù)端; 8、客戶(hù)端接受XML文檔片段; 9、客戶(hù)端解析XML文檔,提取其中的數(shù)據(jù)。 所以從本質(zhì)上來(lái)看,要支持webservice,必須支持XML文檔解析、生成以及支持網(wǎng)絡(luò)傳輸。 三、基于CXF的webservice開(kāi)發(fā) (1)基本開(kāi)發(fā)流程 1、服務(wù)器端 Ⅰ)開(kāi)發(fā)web service業(yè)務(wù)接口,該接口用@WebService修飾; Ⅱ)開(kāi)發(fā)web service業(yè)務(wù)接口的實(shí)現(xiàn)類(lèi),也要用@WebService修飾; Ⅲ)使用EndPoint類(lèi)的靜態(tài)方法publish()來(lái)發(fā)布web service。 2、客戶(hù)端 Ⅰ)調(diào)用CXF提供的wsdl2java工具,根據(jù)WSDL文檔生成相應(yīng)的Java代碼(任何語(yǔ)言實(shí)現(xiàn)web service都要暴露WSDL文檔); Ⅱ)找到wsdl2java所生成的類(lèi)中一個(gè)繼承了Service的類(lèi)(該類(lèi)的實(shí)例可當(dāng)工廠(chǎng)使用); Ⅲ)調(diào)用Service子類(lèi)的實(shí)例的getXXXPort()方法,返回給遠(yuǎn)程web service的代理。 (2)使用CXF開(kāi)發(fā)示例 1、下載CXF工具包apache-cxf-2.4.0,配置用戶(hù)變量PATH,如D:\myeclipse\apache-cxf-2.4.0\bin; 2、服務(wù)器端: 創(chuàng)建一個(gè)Java project,工程名如:WS_Server 導(dǎo)入CXF工具包lib目錄下的jar包 業(yè)務(wù)接口 package org.kfserver.ws; import javax.jws.WebService; @WebService public interface PlaceIntrod { public String getIntrod(String place); } 業(yè)務(wù)接口實(shí)現(xiàn) package org.kfserver.ws.impl; import javax.jws.WebService; import org.kfserver.ws.PlaceIntrod; @WebService(endpointInterface="org.kfserver.ws.PlaceIntrod",serviceName="PlaceIntrodImpl") public class PlaceIntrodImpl implements PlaceIntrod { public String getIntrod(String place) { return "旅游"+place+",人間天堂。"; } } 發(fā)布服務(wù) package kfs; import javax.xml.ws.Endpoint; import org.kfserver.ws.PlaceIntrod; import org.kfserver.ws.impl.PlaceIntrodImpl; public class ServerMain { public static void main(String[] args) { PlaceIntrod pi=new PlaceIntrodImpl(); Endpoint.publish("http://59.71.227.132/kfserver",pi); } } 2、客戶(hù)端: 創(chuàng)建一個(gè)Java project,工程名如:WS_Client 根據(jù)WSDL文檔生成相應(yīng)的Java代碼:cmd->你的工程目錄\src>wsdl2java http://59.71.227.132/kfserver?wsdl 通過(guò)wsdl2java生成的Service的子類(lèi)如下 package org.kfserver.ws.impl; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.WebEndpoint; import javax.xml.ws.WebServiceClient; import javax.xml.ws.WebServiceFeature; import javax.xml.ws.Service; import org.kfserver.ws.PlaceIntrod; @WebServiceClient(name = "PlaceIntrodImpl", wsdlLocation = "http://59.71.227.132/kfserver?wsdl", targetNamespace = "http://impl.ws./") public class PlaceIntrodImpl extends Service { public final static URL WSDL_LOCATION; public final static QName SERVICE = new QName("http://impl.ws./", "PlaceIntrodImpl"); public final static QName PlaceIntrodImplPort = new QName("http://impl.ws./", "PlaceIntrodImplPort"); static { URL url = null; try { url = new URL("http://59.71.227.132/kfserver?wsdl"); } catch (MalformedURLException e) { java.util.logging.Logger.getLogger(PlaceIntrodImpl.class.getName()) .log(java.util.logging.Level.INFO, "Can not initialize the default wsdl from {0}", "http://59.71.227.132/kfserver?wsdl"); } WSDL_LOCATION = url; } public PlaceIntrodImpl(URL wsdlLocation) { super(wsdlLocation, SERVICE); } public PlaceIntrodImpl(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } public PlaceIntrodImpl() { super(WSDL_LOCATION, SERVICE); } /** * * @return * returns PlaceIntrod */ @WebEndpoint(name = "PlaceIntrodImplPort") public PlaceIntrod getPlaceIntrodImplPort() { return super.getPort(PlaceIntrodImplPort, PlaceIntrod.class); } /** * * @param features * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values. * @return * returns PlaceIntrod */ @WebEndpoint(name = "PlaceIntrodImplPort") public PlaceIntrod getPlaceIntrodImplPort(WebServiceFeature... features) { return super.getPort(PlaceIntrodImplPort, PlaceIntrod.class, features); } } 客戶(hù)端調(diào)用服務(wù)(PlaceIntrod pi相當(dāng)于服務(wù)器端的代理) |
|
|
來(lái)自: 一本正經(jīng)地胡鬧 > 《待分類(lèi)》