WebService技术详解CXF
WebService
WebService簡(jiǎn)介
Web Service技術(shù), 能使得運(yùn)行在不同機(jī)器上的不同應(yīng)用無須借助附加的、專門的第三方軟件或硬件, 就可相互交換數(shù)據(jù)或集成。依據(jù)Web Service規(guī)范實(shí)施的應(yīng)用之間, 無論它們所使用的語言、 平臺(tái)或內(nèi)部協(xié)議是什么, 都可以相互交換數(shù)據(jù)。
簡(jiǎn)單的說,WebService就是一種跨編程語言和跨操作系統(tǒng)平臺(tái)的遠(yuǎn)程調(diào)用技術(shù)。所謂跨編程語言和跨操作平臺(tái),就是說服務(wù)端程序采用java編寫,客戶端程序則可以采用其他編程語言編寫,反之亦然。跨操作系統(tǒng)平臺(tái)則是指服務(wù)端程序和客戶端程序可以在不同的操作系統(tǒng)上運(yùn)行。 遠(yuǎn)程調(diào)用,就是一臺(tái)計(jì)算機(jī)的應(yīng)用可以調(diào)用其他計(jì)算機(jī)上的應(yīng)用。例如:支付寶,支付寶并沒有銀行卡等數(shù)據(jù),它只是去調(diào)用銀行提供的接口來獲得數(shù)據(jù)。還有天氣預(yù)報(bào)等,也是氣象局把自己的系統(tǒng)服務(wù)以webservice服務(wù)的形式暴露出來,讓第三方網(wǎng)站和程序可以調(diào)用這些服務(wù)功能。
WebService原理
XML,SOAP和WSDL就是構(gòu)成WebService平臺(tái)的三大技術(shù) 。
- WebService采用Http協(xié)議來在客戶端和服務(wù)端之間傳輸數(shù)據(jù)。WebService使用XML來封裝數(shù)據(jù),XML主要的優(yōu)點(diǎn)在于它是跨平臺(tái)的。
- WebService通過HTTP協(xié)議發(fā)送請(qǐng)求和接收結(jié)果時(shí),發(fā)送的請(qǐng)求內(nèi)容和結(jié)果內(nèi)容都采用XML格式封裝,并增加了一些特定的HTTP消息頭,以說明HTTP消息的內(nèi)容格式,這些特定的HTTP消息頭和XML內(nèi)容格式就是SOAP協(xié)議規(guī)定的。
- WebService服務(wù)器端首先要通過一個(gè)WSDL文件來說明自己有什么服務(wù)可以對(duì)外調(diào)用。簡(jiǎn)單的說,WSDL就像是一個(gè)說明書,用于描述WebService及其方法、參數(shù)和返回值。 WSDL文件保存在Web服務(wù)器上,通過一個(gè)url地址就可以訪問到它。客戶端要調(diào)用一個(gè)WebService服務(wù)之前,要知道該服務(wù)的WSDL文件的地址。WebService服務(wù)提供商可以通過兩種方式來暴露它的WSDL文件地址:1.注冊(cè)到UDDI服務(wù)器,以便被人查找;2.直接告訴給客戶端調(diào)用者。
WebService交互的過程就是,WebService遵循SOAP協(xié)議通過XML封裝數(shù)據(jù),然后由Http協(xié)議來傳輸數(shù)據(jù)。
JAVA WebService規(guī)范
Java 中共有三種WebService 規(guī)范,分別是JAXM&SAAJ、JAX-WS(JAX-RPC)、JAX-RS。
(1)JAX-WS:
JAX-WS(Java API For XML-WebService)。早期的基于SOAP 的JAVA 的Web 服務(wù)規(guī)范JAX-RPC(java API For XML-Remote Procedure Call)目前已經(jīng)被JAX-WS 規(guī)范取代,JAX-WS 是JAX-RPC 的演進(jìn)版本,但JAX-WS 并不完全向后兼容JAX-RPC,二者最大的區(qū)別就是RPC/encoded 樣式的WSDL,JAX-WS 已經(jīng)不提供這種支持。JAX-RPC 的API 從JAVA EE5 開始已經(jīng)移除,如果你使用J2EE1.4,其API 位于javax.xml.rpc.*包。JAX-WS(JSR 224)規(guī)范的API 位于javax.xml.ws.*包,其中大部分都是注解,提供API 操作Web 服務(wù)(通常在客戶端使用的較多,由于客戶端可以借助SDK 生成,因此這個(gè)包中的API 我們較少會(huì)直接使用)。
(2)JAXM&SAAJ:
JAXM(JAVA API For XML Message)主要定義了包含了發(fā)送和接收消息所需的API,相當(dāng)于Web 服務(wù)的服務(wù)器端,其API 位于javax.messaging.*包,它是Java EE 的可選包,因此你需要單獨(dú)下載。
SAAJ(SOAP With Attachment API For Java,JSR 67)是與JAXM 搭配使用的API,為構(gòu)建SOAP 包和解析SOAP 包提供了重要的支持,支持附件傳輸,它在服務(wù)器端、客戶端都需要使用。這里還要提到的是SAAJ 規(guī)范,其API 位于javax.xml.soap.*包。
JAXM&SAAJ 與JAX-WS 都是基于SOAP 的Web 服務(wù),相比之下JAXM&SAAJ 暴漏了SOAP更多的底層細(xì)節(jié),編碼比較麻煩,而JAX-WS 更加抽象,隱藏了更多的細(xì)節(jié),更加面向?qū)ο?#xff0c;實(shí)現(xiàn)起來你基本上不需要關(guān)心SOAP 的任何細(xì)節(jié)。那么如果你想控制SOAP 消息的更多細(xì)節(jié),可以使用JAXM&SAAJ。
(3)JAX-RS:
JAX-RS 是JAVA 針對(duì)REST(Representation State Transfer)風(fēng)格制定的一套Web 服務(wù)規(guī)范,由于推出的較晚,該規(guī)范(JSR 311,目前JAX-RS 的版本為1.0)并未隨JDK1.6 一起發(fā)行。
WebService入門案例
服務(wù)端的實(shí)現(xiàn)
我們來實(shí)現(xiàn)一個(gè)天氣系統(tǒng)的案例,客戶端發(fā)送城市名稱,服務(wù)器端回應(yīng)相應(yīng)的天氣。
1. 編寫SEI(Service Endpoint Interface),SEI在webservice中稱為portType,在java中就是普通接口 public interface WeatherInterface {public String queryWeather(String cityName); } 2. 編寫SEI實(shí)現(xiàn)類,此類作為webservice提供服務(wù)類 @WebService //@WebService表示該類是一個(gè)服務(wù)類,需要發(fā)布其中的public的方法 public class WeatherInterfaceImpl implements WeatherInterface {@Overridepublic String queryWeather(String cityName) {System.out.println("獲取城市名"+cityName);String weather="暴雨"; return weather;}} 3. 第三步:發(fā)布服務(wù),Endpoint類發(fā)布服務(wù),publish方法,兩個(gè)參數(shù):1.服務(wù)地址;2.服務(wù)實(shí)現(xiàn)類 public class WeatherServer {public static void main(String[] args) {Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherInterfaceImpl());} } 4. 測(cè)試服務(wù)是否發(fā)布成功,通過閱讀wsdl,確定客戶端調(diào)用的接口、方法、參數(shù)和返回值存在,證明服務(wù)發(fā)布成功//我們?cè)跒g覽器輸入 http://127.0.0.1:12345/weather?wsdl 來獲取wsdl文件進(jìn)行閱讀//wsdl,是以XML文件形式來描述WebService的”說明書”,有了說明書,我們才可以知道如何使用或是調(diào)用這個(gè)服務(wù).//現(xiàn)在我們還不知道怎么去閱讀,后面我們會(huì)詳解,只要能獲取到,就能確定WebService服務(wù)發(fā)布成功 1234567客戶端的實(shí)現(xiàn)
//客戶端調(diào)用服務(wù)有很多種方法,我們先用工具生成客戶端代碼,后面會(huì)詳解 //wsimport是jdk自帶的webservice客戶端工具,可以根據(jù)wsdl文檔生成客戶端調(diào)用代碼(java代碼).當(dāng)然,無論服務(wù)器端的WebService是用什么語言寫的,都可以生成調(diào)用webservice的客戶端代碼。1.創(chuàng)建一個(gè)客戶端空項(xiàng)目,cmd命令行進(jìn)入此項(xiàng)目的src目錄使用以下命令生成客戶端代碼 wsimport -s . http://127.0.0.1:12345/weather?wsdl-s是指編譯出源代碼文件,后面的.(點(diǎn))指將代碼放到當(dāng)前目錄下.最后面的http….是指獲取wsdl說明書的地址 2.編寫客戶端 public class WeatherClient {public static void main(String[] args) {//創(chuàng)建服務(wù)視圖,視圖是從wsdl文件的service標(biāo)簽的name屬性獲取WeatherInterfaceImplService weatherInterfaceImplService=new WeatherInterfaceImplService(); //獲取服務(wù)實(shí)現(xiàn)類,實(shí)現(xiàn)類從wsdl文件的portType的name屬性獲取WeatherInterfaceImpl weatherInterfaceImpl=weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class); //獲取查詢方法,從portType的operation標(biāo)簽獲取String weather=weatherInterfaceImpl.queryWeather("北京");System.out.println(weather);}}至此,我們的客戶端就可以獲取遠(yuǎn)程服務(wù)端的數(shù)據(jù),接下來我們來詳解一下各個(gè)部分。
WSDL
WSDL(Web Services Description Language), web服務(wù)描述語言,他是webservice服務(wù)端使用說明書,說明服務(wù)端接口、方法、參數(shù)和返回值,WSDL是隨服務(wù)發(fā)布成功,自動(dòng)生成,無需編寫。
文檔結(jié)構(gòu)
Service:相關(guān)端口的集合,包括其關(guān)聯(lián)的接口、操作、消息等。
Binding:特定端口類型的具體協(xié)議和數(shù)據(jù)格式規(guī)范
portType: 服務(wù)端點(diǎn),描述 web service可被執(zhí)行的操作方法,以及相關(guān)的消息,通過binding指向portType
message: 定義一個(gè)操作(方法)的數(shù)據(jù)參數(shù)
types: 定義 web service 使用的全部數(shù)據(jù)類型
閱讀方式
WSDL文檔應(yīng)該從下往上閱讀。
1.先看service標(biāo)簽,看相應(yīng)port的binding屬性,然后通過值查找上面的binding標(biāo)簽。
2.通過binding標(biāo)簽可以獲得具體協(xié)議等信息,然后查看binding的type屬性
3.通過binding的type屬性,查找對(duì)應(yīng)的portType,可以獲得可操作的方法和參數(shù)、返回值等。
4.通過portType下的operation標(biāo)簽的message屬性,可以向上查找message獲取具體的數(shù)據(jù)參數(shù)信息。
SOAP
SOAP即簡(jiǎn)單對(duì)象訪問協(xié)議,他是使用http發(fā)送的XML格式的數(shù)據(jù),它可以跨平臺(tái),跨防火墻,SOAP不是webservice的專有協(xié)議。
SOAP=http+xml
SOAP結(jié)構(gòu)
必需的 Envelope 元素,可把此 XML 文檔標(biāo)識(shí)為一條 SOAP 消息 可選的 Header 元素,包含頭部信息 必需的 Body 元素,包含所有的調(diào)用和響應(yīng)信息 可選的 Fault 元素,提供有關(guān)在處理此消息所發(fā)生錯(cuò)誤的信息我們來看一下我們上面天氣程序發(fā)送的數(shù)據(jù)的格式,這需要一個(gè)工具TCP/IP Monitor ,Eclipse自帶的Debug工具之一,用于捕獲Http、TCP/IP協(xié)議包。原理是一個(gè)代理服務(wù),客戶端先把數(shù)據(jù)發(fā)送到代理服務(wù),然后代理服務(wù)再把數(shù)據(jù)發(fā)送到服務(wù)器,這樣就能獲取請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)。
第一步:打開這個(gè)工具,選擇other,然后輸入TCP/IP Monitor
第二步:設(shè)置要代理的服務(wù)器
第三步:詳細(xì)設(shè)置
第一個(gè)參數(shù)是代理服務(wù)器端口,我們?cè)O(shè)置為54321 第二個(gè)參數(shù)是被代理服務(wù)器的地址,第三個(gè)參數(shù)是被代理服務(wù)器的端口 第四個(gè)參數(shù)要選擇為TCP/IP第四步:檢測(cè)是否設(shè)置成功,我們?cè)L問代理服務(wù)器來獲得wsdl文件
第五步:設(shè)置成功后,我們需要改一下客戶端要連接的服務(wù)器,改成代理服務(wù)器的端口
將WeatherInterfaceImplService里的所有原來地址的端口改為54321第六步:我們啟動(dòng)我們的客戶端,獲取請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)
請(qǐng)求 //先發(fā)送get請(qǐng)求,去獲得wsdl文件,然后獲得方法、參數(shù)等信息 GET /weather?wsdl HTTP/1.1 User-Agent: Java/1.8.0_111 Host: 127.0.0.1:54321 Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive//發(fā)送數(shù)據(jù) POST /weather HTTP/1.1 Accept: text/xml, multipart/related Content-Type: text/xml; charset=utf-8 SOAPAction: "http://ws.cad.com/WeatherInterfaceImpl/queryWeatherRequest" User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e Host: 127.0.0.1:54321 Connection: keep-alive Content-Length: 203<?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:queryWeather xmlns:ns2="http://ws.cad.com/"> <arg0>北京</arg0> </ns2:queryWeather> </S:Body> </S:Envelope> 響應(yīng)數(shù)據(jù) HTTP/1.1 200 OK Date: Tue, 25 Jul 2017 05:05:58 GMT Transfer-encoding: chunked Content-type: text/xml;charset=utf-8//響應(yīng)wsdl內(nèi)容,來獲得方法、參數(shù)等信息 899 <?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws.cad.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.cad.com/" name="WeatherInterfaceImplService"> <types> <xsd:schema> <xsd:import namespace="http://ws.cad.com/" schemaLocation="http://127.0.0.1:54321/weather?xsd=1"></xsd:import> </xsd:schema> </types> <message name="queryWeather"> <part name="parameters" element="tns:queryWeather"></part> </message> <message name="queryWeatherResponse"> <part name="parameters" element="tns:queryWeatherResponse"></part> </message> <portType name="WeatherInterfaceImpl"> <operation name="queryWeather"> <input wsam:Action="http://ws.cad.com/WeatherInterfaceImpl/queryWeatherRequest" message="tns:queryWeather"></input> <output wsam:Action="http://ws.cad.com/WeatherInterfaceImpl/queryWeatherResponse" message="tns:queryWeatherResponse"></output> </operation> </portType> <binding name="WeatherInterfaceImplPortBinding" type="tns:WeatherInterfaceImpl"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding> <operation name="queryWeather"> <soap:operation soapAction=""></soap:operation> <input> <soap:body use="literal"></soap:body> </input> <output> <soap:body use="literal"></soap:body> </output> </operation> </binding> <service name="WeatherInterfaceImplService"> <port name="WeatherInterfaceImplPort" binding="tns:WeatherInterfaceImplPortBinding"> <soap:address location="http://127.0.0.1:54321/weather"></soap:address> </port> </service> </definitions> 0//響應(yīng)數(shù)據(jù) HTTP/1.1 200 OK Date: Tue, 25 Jul 2017 05:05:59 GMT Transfer-encoding: chunked Content-type: text/xml; charset=utf-8df <?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body><ns2:queryWeatherResponse xmlns:ns2="http://ws.cad.com/"><return>暴雨</return> </ns2:queryWeatherResponse> </S:Body> </S:Envelope> 0UDDI
UDDI 是一種目錄服務(wù),企業(yè)可以使用它對(duì) Web services 進(jìn)行注冊(cè)和搜索。
如果我們要使用一種服務(wù),但是不知道地址(wsdl等),我們就可以在UDDI中查找。
大部分情況下,我們都是知道服務(wù)地址的。
Webservice的客戶端調(diào)用方式
一:生成客戶端調(diào)用方式
wsimport是jdk自帶的webservice客戶端工具,可以根據(jù)wsdl文檔生成客戶端調(diào)用代碼(java代碼). wsimport.exe位于JAVA_HOME\bin目錄下 常用參數(shù)為:-d<目錄> - 將生成.class文件。默認(rèn)參數(shù)。-s<目錄> - 將生成.java文件。-p<生成的新包名> -將生成的類,放于指定的包下調(diào)用公網(wǎng)的手機(jī)歸屬地查詢服務(wù)
公網(wǎng)服務(wù)地址 (里面提供了很多免費(fèi)調(diào)用的服務(wù))
http://www.webxml.com.cn/zh_cn/index.aspx
還有天氣等服務(wù),自己可以去實(shí)現(xiàn)一下。
該種方式使用簡(jiǎn)單,但一些關(guān)鍵的元素在代碼生成時(shí)寫死在生成代碼中,不方便維護(hù),所以僅用于測(cè)試。
二:service編程調(diào)用方式
public class MobileClient2 {public static void main(String[] args) throws IOException {//創(chuàng)建WSDL文件的URLURL wsdlDocumentLocation=new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl"); //創(chuàng)建服務(wù)名稱//1.namespaceURI - 命名空間地址//2.localPart - 服務(wù)視圖名QName serviceName=new QName("http://WebXml.com.cn/","MobileCodeWS");Service service=Service.create(wsdlDocumentLocation, serviceName);//獲取服務(wù)實(shí)現(xiàn)類MobileCodeWSSoap mobileCodeWSSoap= service.getPort(MobileCodeWSSoap.class);//調(diào)用方法String message=mobileCodeWSSoap.getMobileCodeInfo("XXXXXXX", null);System.out.println(message);}}該種方式可以自定義命名空間,服務(wù)視圖名等元素,方便以后維護(hù),是一種標(biāo)準(zhǔn)的開發(fā)方式 。
三:HttpURLConnection調(diào)用方式
這種方式是由自己編寫客戶端,不再由工具生成,比較麻煩。
開發(fā)步驟: 第一步:創(chuàng)建服務(wù)地址第二步:打開一個(gè)通向服務(wù)地址的連接第三步:設(shè)置參數(shù)第四步:組織SOAP數(shù)據(jù),發(fā)送請(qǐng)求第五步:接收服務(wù)端響應(yīng) public class MobileClient2 {public static void main(String[] args) throws IOException {//第一步:創(chuàng)建服務(wù)地址,不是WSDL地址URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");//第二步:打開一個(gè)通向服務(wù)地址的連接HttpURLConnection connection = (HttpURLConnection) url.openConnection();//第三步:設(shè)置參數(shù)//3.1發(fā)送方式設(shè)置:POST必須大寫connection.setRequestMethod("POST");//3.2設(shè)置數(shù)據(jù)格式:content-typeconnection.setRequestProperty("content-type", "text/xml;charset=UTF-8");//3.3設(shè)置輸入輸出,因?yàn)槟J(rèn)新創(chuàng)建的connection沒有讀寫權(quán)限,connection.setDoInput(true);connection.setDoOutput(true);//第四步:組織SOAP數(shù)據(jù),發(fā)送請(qǐng)求String soapXML = getXML("XXXXXXX");OutputStream os = connection.getOutputStream();os.write(soapXML.getBytes());//第五步:接收服務(wù)端響應(yīng),打印int responseCode = connection.getResponseCode();if(200 == responseCode){//表示服務(wù)端響應(yīng)成功InputStream is = connection.getInputStream();//將字節(jié)流轉(zhuǎn)換為字符流InputStreamReader isr = new InputStreamReader(is,"utf-8");//使用緩存區(qū)BufferedReader br = new BufferedReader(isr);StringBuilder sb = new StringBuilder();String temp = null;while(null != (temp = br.readLine())){sb.append(temp);}System.out.println(sb.toString());is.close();isr.close();br.close();}os.close();}//組織數(shù)據(jù),將數(shù)據(jù)拼接一下public static String getXML(String phoneNum){String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"+"<soap:Body>"+"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"+"<mobileCode>"+phoneNum+"</mobileCode>"+"<userID></userID>"+"</getMobileCodeInfo>"+"</soap:Body>"+"</soap:Envelope>";return soapXML;} }使用注解修改WSDL內(nèi)容
作用:
通過注解,可以更加形像的描述Web服務(wù)。對(duì)自動(dòng)生成的wsdl文檔進(jìn)行修改,為使用者提供一個(gè)更加清晰的wsdl文檔
CXF
CXF簡(jiǎn)介
CXF是一個(gè)開源的WebService框架。Apache CXF = Celtix + XFire,開始叫 Apache CeltiXfire,后來更名為 Apache CXF 了,以下簡(jiǎn)稱為 CXF。CXF 繼承了 Celtix 和 XFire 兩大開源項(xiàng)目的精華,提供了對(duì) JAX-WS 全面的支持,并且提供了多種 Binding 、DataBinding、Transport 以及各種 Format 的支持,并且可以根據(jù)實(shí)際項(xiàng)目的需要,采用代碼優(yōu)先(Code First)或者 WSDL 優(yōu)先(WSDL First)來輕松地實(shí)現(xiàn) Web Services 的發(fā)布和使用。
支持多種標(biāo)準(zhǔn)
- 支持 JAX-WS、 JAX-WSA、JSR-181 和 SAAJ;
- 支持 SOAP 1.1、1.2、WS-I BasicProfile、WS-Security、WS-Addressing、WS-RM 和 WS-Policy;
- 支持 WSDL 1.1 、2.0;
- 支持 MTOM;
它支持多種協(xié)議,比如:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。CORBA(Common Object Request Broker Architecture公共對(duì)象請(qǐng)求代理體系結(jié)構(gòu),早期語言使用的WS。C,c++,C#)
Cxf是基于SOA總線結(jié)構(gòu),依靠spring完成模塊的集成,實(shí)現(xiàn)SOA方式。
靈活的部署:可以運(yùn)行有Tomcat,Jboss,Jetty(內(nèi)置),weblogic上面。
CXF入門案例
我們還以昨天的天氣服務(wù)為案例來看一下CXF的開發(fā)過程。
服務(wù)端的實(shí)現(xiàn)
1.創(chuàng)建一個(gè)空的java項(xiàng)目,創(chuàng)建一個(gè)lib目錄,將所有jar包放入lib目錄然后為工程引入jar包,選擇build path,然后Add JARS,只用選擇cxf-manifest.jar即可。 2.創(chuàng)建一個(gè)SEI接口,需要在接口上添加@WebService注解@WebService public interface WeatherInterface {public String queryWeather(String cityName); } 3.創(chuàng)建SEI接口實(shí)現(xiàn)類 public class WeatherInterfaceImpl implements WeatherInterface {public String queryWeather(String cityName) {if("河南".equals(cityName)) {return "熱爆炸";}else {return "冰雹";}} } 4.發(fā)布服務(wù) public class WeatherServer {public static void main(String[] args) {//創(chuàng)建服務(wù)工廠BeanJaxWsServerFactoryBean jaxWsServerFactoryBean=new JaxWsServerFactoryBean();//設(shè)置服務(wù)接口jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);//設(shè)置服務(wù)實(shí)現(xiàn)類jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl());//設(shè)置服務(wù)地址jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/weather");//創(chuàng)建服務(wù)jaxWsServerFactoryBean.create();}} 5.訪問服務(wù)的wsdl文件地址,看服務(wù)是否發(fā)布成功http://127.0.0.1:12345/weather?wsdl發(fā)布SOAP1.2的服務(wù)端
SOAP分為1.1版本和1.2版本。JDK1.6并不支持1.2,我們可以通過CXF來發(fā)布SOAP1.2的服務(wù)端。
只需要在接口上添加注解 @BindingType(SOAPBinding.SOAP12HTTP_BINDING)。然后重新發(fā)布服務(wù)即可
客戶端的實(shí)現(xiàn)
Wsdl2java命令是CXF提供的生成客戶端的工具,他和wsimport類似,可以根據(jù)WSDL生成客戶端代碼 Wsdl2java常用參數(shù): -d,指定輸出目錄 -p,指定包名,如果不指定該參數(shù),默認(rèn)包名是WSDL的命名空間的倒序 Wsdl2java支持SOAP1.1和SOAP1.2 1.我們先創(chuàng)建一個(gè)客戶端項(xiàng)目,然后引入jar包,和上面一樣,使用Add JARS選擇cxf-manifest.jar即可然后使用工具生成客戶端wsdl2java -p com.cad.cxf -d . http://127.0.0.1:12345/weather?wsdl 2.創(chuàng)建客戶端 public class WeatherClient {public static void main(String[] args) {JaxWsProxyFactoryBean jaxWsProxyFactoryBean=new JaxWsProxyFactoryBean();//設(shè)置服務(wù)接口jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class); //設(shè)置服務(wù)地址jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/weather");//獲取服務(wù)接口實(shí)例WeatherInterface weatherInterface=(WeatherInterface) jaxWsProxyFactoryBean.create();//調(diào)用方法String message=weatherInterface.queryWeather("河南");System.out.println(message);}}CXF+Spring整合發(fā)布SOAP模式的服務(wù)
服務(wù)端的實(shí)現(xiàn)
1.創(chuàng)建WEB項(xiàng)目,導(dǎo)入jar包 1 2.創(chuàng)建SEI接口 @WebService @BindingType(SOAPBinding.SOAP12HTTP_BINDING) public interface WeatherInterface {public String queryWeather(String cityName); } 3.創(chuàng)建SEI實(shí)現(xiàn)類 public class WeatherInterfaceImpl implements WeatherInterface {public String queryWeather(String cityName) {if("河南".equals(cityName)) {return "熱爆炸";}else {return "冰雹";}} } 4.配置spring配置文件,applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"><!--jaxws:server發(fā)布SOAP協(xié)議的服務(wù) ,對(duì)JaxWsServerFactoryBean類封裝--> <!--serviceClass屬性是服務(wù)接口,address代表地址,因?yàn)槲覀兪莣eb服務(wù),不需要輸入ip。serviceBean是服務(wù)實(shí)現(xiàn)類--> <jaxws:server serviceClass="com.cad.cxf.WeatherInterface" address="/weather"><jaxws:serviceBean><ref bean="weatherInterfaceImpl"/></jaxws:serviceBean> </jaxws:server> <bean name="weatherInterfaceImpl" class="com.cad.cxf.WeatherInterfaceImpl"></bean> </beans> 5.配置web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"><display-name>CXFSpringDemo</display-name>//配置Tomcat啟動(dòng)時(shí)加載Spring配置文件 <context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>//配置CXF提供的Servlet<servlet><servlet-name>CXF</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class></servlet><servlet-mapping><servlet-name>CXF</servlet-name><url-pattern>/ws/*</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list> </web-app> 6.部署到Tomcat下,發(fā)布服務(wù),并訪問 http://localhost:8080/CXFSpringDemo/ws/weather?wsdl客戶端的實(shí)現(xiàn)
1.創(chuàng)建項(xiàng)目,導(dǎo)入jar包,生成客戶端 wsdl2java -p com.cad.cxf -d . http://localhost:8080/CXFSpringDemo/ws/weather?wsdl 2.配置Spring文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"><!-- <jaxws:client實(shí)現(xiàn)客戶端 ,對(duì)JaxWsProxyFactoryBean類封裝--> <!-- address是服務(wù)地址,servicelass是服務(wù)接口,返回服務(wù)實(shí)現(xiàn)類--> <jaxws:client id="weatherClient" address="http://localhost:8080/CXFSpringDemo/ws/weather" serviceClass="com.cad.cxf.WeatherInterface"/> </beans> 3.通過Spring容器獲取服務(wù)實(shí)現(xiàn)類,調(diào)用方法 public class WeatherClient {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");WeatherInterface weatherInterface = (WeatherInterface) context.getBean("weatherClient");String message=weatherInterface.queryWeather("河南");System.out.println(message);}}CXF發(fā)布REST模式的服務(wù)
REST即表述性狀態(tài)傳遞(英文:Representational State Transfer,簡(jiǎn)稱REST),是一種軟件架構(gòu)風(fēng)格。
因?yàn)镽EST模式的Web服務(wù)與復(fù)雜的SOAP和XML-RPC對(duì)比來講明顯的更加簡(jiǎn)潔,越來越多的web服務(wù)開始采用REST風(fēng)格設(shè)計(jì)和實(shí)現(xiàn)rest服務(wù)采用HTTP 做傳輸協(xié)議,REST 對(duì)于HTTP 的利用實(shí)現(xiàn)精確的資源定位。
例如: 非rest方式:http://ip:port/queryUser.action?userType=student&id=001 Rest方式:http://ip:port/user/student/query/001 1.創(chuàng)建一個(gè)項(xiàng)目,導(dǎo)入CXF jar包 1 2.創(chuàng)建一個(gè)實(shí)體類 Student @XmlRootElement(name="student")可以實(shí)現(xiàn)XML和對(duì)象之間的轉(zhuǎn)換,name屬性指定根元素@XmlRootElement(name="student") public class Student {private int id;private String name;private Date birthday;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}} 3.創(chuàng)建SEI接口 @WebService //@Path("/student")就是指定訪問該接口的路徑 @Path("/Student") public interface StudentInterface {//指定請(qǐng)求方式,如果服務(wù)端發(fā)布的時(shí)候指定的是GET(POST),那么客戶端訪問時(shí)必須使用GET(POST@GET//指定服務(wù)數(shù)據(jù)類型,可以是XML,json等數(shù)據(jù)類型@Produces(MediaType.APPLICATION_XML)//@Path("/query/{id}")指定該方法的路徑,“{id}”指參數(shù),多個(gè)參數(shù),以“/”隔開,放到“{}”中@Path("/query/{id}")public Student queryStudent(@PathParam("id")int id);@GET@Produces(MediaType.APPLICATION_XML)@Path("/queryList/{name}")public List<Student> queryList(@PathParam("name")String name); } 4.創(chuàng)建SEI實(shí)現(xiàn)類 public class StudentInterfaceImpl implements StudentInterface {@Overridepublic Student queryStudent(int id) {Student s=new Student();s.setId(666);s.setName("張三");s.setBirthday(new Date());return s;}@Overridepublic List<Student> queryList(String name) {Student s=new Student();s.setId(666);s.setName("張三");s.setBirthday(new Date());Student s2=new Student();s2.setId(888);s2.setName("李四");s2.setBirthday(new Date());List<Student> l=new ArrayList<Student>();l.add(s);l.add(s2);return l;}} 5.發(fā)布服務(wù) public class StudentServer {public static void main(String[] args) {JAXRSServerFactoryBean jaxrsServerFactoryBean=new JAXRSServerFactoryBean();//設(shè)置服務(wù)實(shí)現(xiàn)類jaxrsServerFactoryBean.setServiceBean(new StudentInterfaceImpl());//設(shè)置資源類,如果有多個(gè)資源類,可以以“,”隔開,例如Student.class StudentInterface.class都是資源類,但是StudentInterfaceImpl里面已經(jīng)包含了Student.class StudentInterface.class,所以不用重復(fù)指定jaxrsServerFactoryBean.setResourceClasses(StudentInterfaceImpl.class); //設(shè)置服務(wù)地址jaxrsServerFactoryBean.setAddress("http://127.0.0.1:12345/Class");//發(fā)布服務(wù)jaxrsServerFactoryBean.create();}} 6.測(cè)試服務(wù) 訪問query方法 http://127.0.0.1:12345/Class/Student/query/001 訪問queryList方法 http://127.0.0.1:12345/Class/Student/queryList/xxx如果服務(wù)端發(fā)布時(shí)指定請(qǐng)求方式是GET(POST),客戶端必須使用GET(POST)訪問服務(wù)端,否則會(huì)報(bào)異常。
如果在同一方法上同時(shí)指定XML和JSON媒體類型,在GET請(qǐng)求下,默認(rèn)返回XML,在POST請(qǐng)求下,默認(rèn)返回JSON
CXF+Spring整合發(fā)布REST模式的服務(wù)
1.創(chuàng)建web項(xiàng)目,引入jar包1 2.創(chuàng)建一個(gè)實(shí)體類 Student @XmlRootElement(name="student")可以實(shí)現(xiàn)XML和對(duì)象之間的轉(zhuǎn)換,name屬性指定根元素@XmlRootElement(name="student") public class Student {private int id;private String name;private Date birthday;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}} 3.創(chuàng)建SEI接口 @WebService //@Path("/student")就是指定訪問該接口的路徑 @Path("/Student") public interface StudentInterface {//指定請(qǐng)求方式,如果服務(wù)端發(fā)布的時(shí)候指定的是GET(POST),那么客戶端訪問時(shí)必須使用GET(POST@GET//指定服務(wù)數(shù)據(jù)類型,可以是XML,json等數(shù)據(jù)類型@Produces(MediaType.APPLICATION_XML)//@Path("/query/{id}")指定該方法的路徑,“{id}”指參數(shù),多個(gè)參數(shù),以“/”隔開,放到“{}”中@Path("/query/{id}")public Student queryStudent(@PathParam("id")int id);@GET@Produces(MediaType.APPLICATION_XML)@Path("/queryList/{name}")public List<Student> queryList(@PathParam("name")String name); } 4.創(chuàng)建SEI實(shí)現(xiàn)類 public class StudentInterfaceImpl implements StudentInterface {@Overridepublic Student queryStudent(int id) {Student s=new Student();s.setId(666);s.setName("張三");s.setBirthday(new Date());return s;}@Overridepublic List<Student> queryList(String name) {Student s=new Student();s.setId(666);s.setName("張三");s.setBirthday(new Date());Student s2=new Student();s2.setId(888);s2.setName("李四");s2.setBirthday(new Date());List<Student> l=new ArrayList<Student>();l.add(s);l.add(s2);return l;}} 第五步:配置Spring配置文件,applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"><!-- <jaxrs:server發(fā)布REST的服務(wù) ,對(duì)JAXRSServerFactoryBean類封裝--> <jaxrs:server address="/user"><jaxrs:serviceBeans><ref bean="studentInterface"/></jaxrs:serviceBeans></jaxrs:server><!-- 配置服務(wù)實(shí)現(xiàn)類 --><bean name="studentInterface" class="com.cad.rest.StudentInterfaceImpl"/> </beans> 6.配置web.xml文件 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"><display-name>ws_2_cxf_spring_server</display-name><!-- 設(shè)置spring的環(huán)境 --><context-param><!--contextConfigLocation是不能修改的 --><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 配置CXF的Servlet --><servlet><servlet-name>CXF</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class></servlet><servlet-mapping><servlet-name>CXF</servlet-name><url-pattern>/ws/*</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list> </web-app> 7.部署到Tomcat中,發(fā)布服務(wù),測(cè)試一下 http://127.0.0.1:8080/CXFRestDemo/ws/user/Student/query/100綜合案例:手機(jī)歸屬地查詢
1.創(chuàng)建web項(xiàng)目,導(dǎo)入 CXF jar包 1 2.生成公網(wǎng)提供的手機(jī)歸屬地查詢的客戶端 wsdl2java -p com.cad.mobile -d . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 3.編寫我們自己的SEI接口 @WebService public interface MobileInterface {public String queryMobile(String phoneNum); } 4.編寫我們的SEI實(shí)現(xiàn)類 ,里面調(diào)用公網(wǎng)客戶端的查詢方法,我們?cè)?span id="ozvdkddzhkzd" class="token class-name">Spring配置客戶端,然后注入即可 public class MobileInterfaceImpl implements MobileInterface {//公網(wǎng)客戶端,提供set方法 以便注入private MobileCodeWSSoap mobileClient;//調(diào)用公網(wǎng)的查詢方法public String queryMobile(String phoneNum) {return mobileClient.getMobileCodeInfo(phoneNum, "");}public MobileCodeWSSoap getMobileClient() {return mobileClient;}public void setMobileClient(MobileCodeWSSoap mobileClient) {this.mobileClient = mobileClient;}} 5.配置Spring 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"><!-- 配置公網(wǎng)客戶端 --><jaxws:client id="mobileClient" address="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" serviceClass="com.cad.mobile.MobileCodeWSSoap"/> <!-- <jaxws:server發(fā)布我們的服務(wù)--> <jaxws:server address="/mobile" serviceClass="com.cad.server.MobileInterface"><jaxws:serviceBean><ref bean="mobileServer"/></jaxws:serviceBean></jaxws:server> <!-- 配置我們的服務(wù)實(shí)現(xiàn)類 --><bean name="mobileServer" class="com.cad.server.MobileInterfaceImpl"><property name="mobileClient" ref="mobileClient"/></bean> </beans> 6.創(chuàng)建查詢頁面 <body><form action="MobileServlet" method="post">手機(jī)號(hào)歸屬地查詢:<input type="text" name="phoneNum"><input type="submit" value="查詢"><br>查詢結(jié)果:${result}</form></body> 7.創(chuàng)建處理的Servlet@WebServlet("/MobileServlet") public class MobileServlet extends HttpServlet {private MobileInterface mobileServer;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//獲取頁面的電話號(hào)String phoneNum = request.getParameter("phoneNum");if(null != phoneNum && !"".equals(phoneNum)){//獲取Spring容器ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());//獲取我們的服務(wù)實(shí)現(xiàn)類mobileServer = (MobileInterface) context.getBean("mobileServer");//調(diào)用查詢方法String result = mobileServer.queryMobile(phoneNum);request.setAttribute("result", result);}//請(qǐng)求轉(zhuǎn)發(fā) request.getRequestDispatcher("/index.jsp").forward(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}} 8.配置web.xml<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><display-name>MobileDemo</display-name><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list><context-param><!--contextConfigLocation是不能修改的 --><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 配置CXF的Servlet --><servlet><servlet-name>CXF</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class></servlet><servlet-mapping><servlet-name>CXF</servlet-name><url-pattern>/ws/*</url-pattern></servlet-mapping></web-app> 9.部署Tomcat,訪問測(cè)試總結(jié)
以上是生活随笔為你收集整理的WebService技术详解CXF的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 趣学python3(40)--TCP服务
- 下一篇: ajax中return取不到值的问题