一、SOA和webservice SOA(service-Oriented Architecture)是面向服務的架構(gòu),是一個組件模型,它將應用程序的不同功能單元(稱為服務)通過這些服務之間定義良好的接口和契約聯(lián)系起來。接口是采用中立的方式進行定義的,它應該獨立于實現(xiàn)服務的硬件平臺、操作系統(tǒng)和編程語言。這使得構(gòu)建在各種各樣的系統(tǒng)中的服務可以使用一種統(tǒng)一和通用的方式進行交互。web service是一個平臺獨立的,低耦合的,自包含的、基于可編程的web的應用程序,可使用開放的XML(標準通用標記語言下的一個子集)標準來描述、發(fā)布、發(fā)現(xiàn)、協(xié)調(diào)和配置這些應用程序,用于開發(fā)分布式的互操作的應用程序。web service是實現(xiàn)SOA架構(gòu)的一種技術(shù),XML+XSD,SOAP和WSDL就是構(gòu)成WebService平臺的三大技術(shù)。 1、XML+XSD: XML是WebService平臺中表示數(shù)據(jù)的格式。 WebService采用HTTP協(xié)議傳輸數(shù)據(jù),采用XML格式封裝數(shù)據(jù)(即XML中說明調(diào)用遠程服務對象的哪個方法,傳遞的參數(shù)是什么,以及服務對象的返回結(jié)果是什么)除了易于建立和易于分析外,XML主要的優(yōu)點在于它既是平臺無關(guān)的,又是廠商無關(guān)的。 XSD(XML Schema)解決了數(shù)據(jù)數(shù)據(jù)類型的問題,例如,整形數(shù)到底代表什么?16位,32位,64位?它定義了一套標準的數(shù)據(jù)類型,并給出了一種語言來擴展這套數(shù)據(jù)類型。WebService平臺就是用XSD來作為其數(shù)據(jù)類型系統(tǒng)的。當你用某種語言(如VB.NET或C#)來構(gòu)造一個Web service時,為了符合WebService標準,所有你使用的數(shù)據(jù)類型都必須被轉(zhuǎn)換為XSD類型。 2、SOAP SOAP即簡單對象訪問協(xié)議(Simple Object Access Protocol),它是用于交換XML。WebService通過HTTP協(xié)議發(fā)送請求和接收結(jié)果時,發(fā)送的請求內(nèi)容和結(jié)果內(nèi)容都采用XML格式封裝,并增加了一些特定的HTTP消息頭,以說明HTTP消息的內(nèi)容格式,這些特定的HTTP消息頭和XML內(nèi)容格式就是SOAP協(xié)議。SOAP提供了標準的RPC方法來調(diào)用Web Service。 SOAP協(xié)議 = HTTP協(xié)議 + XML數(shù)據(jù)格式。 3、WSDL WSDL是Web Service描述語言,用于描述Web Service及其函數(shù)、參數(shù)和返回值。它是WebService客戶端和服務器端都能理解的標準格式。因為是基于XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。一些最新的開發(fā)工具既能根據(jù)你的Web service生成WSDL文檔,又能導入WSDL文檔,生成調(diào)用相應WebService的代理類代碼。WSDL文件保存在Web服務器上,通過一個url地址就可以訪問到它??蛻舳艘{(diào)用一個WebService服務之前,要知道該服務的WSDL文件的地址。WebService服務提供商可以通過兩種方式來暴露它的WSDL文件地址:1.注冊到UDDI服務器,以便被人查找;2.直接告訴給客戶端調(diào)用者。 二、調(diào)用webservice的本質(zhì) 調(diào)用一次webservice的本質(zhì)如下: 1、客戶端把調(diào)用方法參數(shù)轉(zhuǎn)換生成XML文檔片段(SOAP消息),且該文檔必須符合WSDL定義的格式; 2、通過http協(xié)議把XML文檔片段傳給服務器; 3、服務器接受到XML文檔片段; 4、服務器解析XML文檔片段,提取其中的數(shù)據(jù); 5、服務器執(zhí)行方法; 6、服務器把執(zhí)行方法得到的返回值轉(zhuǎn)換成符合WSDL定義的XML文檔片段; 7、通過http協(xié)議把XML文檔片段傳輸給客戶端; 8、客戶端接受XML文檔片段; 9、客戶端解析XML文檔,提取其中的數(shù)據(jù)。 所以從本質(zhì)上來看,要支持webservice,必須支持XML文檔解析、生成以及支持網(wǎng)絡傳輸。 三、基于CXF的webservice開發(fā) (1)基本開發(fā)流程 1、服務器端 Ⅰ)開發(fā)web service業(yè)務接口,該接口用@WebService修飾; Ⅱ)開發(fā)web service業(yè)務接口的實現(xiàn)類,也要用@WebService修飾; Ⅲ)使用EndPoint類的靜態(tài)方法publish()來發(fā)布web service。 2、客戶端 Ⅰ)調(diào)用CXF提供的wsdl2java工具,根據(jù)WSDL文檔生成相應的Java代碼(任何語言實現(xiàn)web service都要暴露WSDL文檔); Ⅱ)找到wsdl2java所生成的類中一個繼承了Service的類(該類的實例可當工廠使用); Ⅲ)調(diào)用Service子類的實例的getXXXPort()方法,返回給遠程web service的代理。 (2)使用CXF開發(fā)示例 1、下載CXF工具包apache-cxf-2.4.0,配置用戶變量PATH,如D:\myeclipse\apache-cxf-2.4.0\bin; 2、服務器端: 創(chuàng)建一個Java project,工程名如:WS_Server 導入CXF工具包lib目錄下的jar包 業(yè)務接口 package org.kfserver.ws; import javax.jws.WebService; @WebService public interface PlaceIntrod { public String getIntrod(String place); } 業(yè)務接口實現(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ā)布服務 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、客戶端: 創(chuàng)建一個Java project,工程名如:WS_Client 根據(jù)WSDL文檔生成相應的Java代碼:cmd->你的工程目錄\src>wsdl2java http://59.71.227.132/kfserver?wsdl 通過wsdl2java生成的Service的子類如下 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); } } 客戶端調(diào)用服務(PlaceIntrod pi相當于服務器端的代理) |
|
來自: 一本正經(jīng)地胡鬧 > 《待分類》