一、簡介
cxf是apache下的一個開源的,功能齊全的WebService框架。是由Celtix和XFire兩個開源框架組合而成。cxf可以幫助我們使用前端編程模型構建和開發服務,如JAX- WS和JAZ-RS。這些服務可以使用不同的協議,如SOAP,XML/HTTP,RESTFul HTTP或者CORBA和使用各種的數據傳輸協議,如HTTP,JMS 和JBI。除此之外cxf還有如下特性:
- 使用簡單,可與maven,spring等進行集成。
- 支持Web Service標准,包括soap,WS-I Basic Profile, WSDL, WS-Addressing, WS-Policy, WS-ReliableMessaging, WS-Security, WS-SecurityPolicy, WS-
- SecureConverstation, 和WS-Trust (partial)。
- 對二進制和遺留協議的支持,cxf設計並提供了一個可插拔的架構,不僅支持xml還支持非xml類型的綁定,如json,corba。可使用多種類型格式進行傳輸。
- 提供了多中工具生成代碼,如WSDL to JAVA, WSDL to JavaScript, Java to JavaScript等。
二、使用
cxf的下載地址如下:http://cxf.apache.org/download.html 。這里下載的是windows版本apache-cxf-3.0.3.zip。在c盤根目錄下解壓該文件,解壓后文件目錄結構如下:
其中bin目錄下的是為我們提供的相關轉換工具,docs目錄下的是相關文檔,lib目錄下是cxf的jar依賴;license目錄下的是許可,samples是為我們提供的例子。
新建一個java項目cxf_server,並將lib下的jar文件(不包括endorse,和integration目錄)添加到項目的依賴。
1、編寫MyService接口 代碼如下:
1 package com.cxf.testauto; 2 3 import javax.jws.WebService; 4 5 @WebService 6 public interface MyService { 7 8 public String sayHello(String username, String address, String school); 9 }
2、編寫MyService的實現類
package com.cxf.testauto; public class MyServiceImpl implements MyService { @Override public String sayHello(String username, String address, String school) { System.out.println("sayHello is invoked!"); String result = "hello: " + username + ", your info is: " + address + ", " + school; return result; } }
3、Server 服務的啟動類
package com.cxf.testauto; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; public class Server { public static void main(String[] args) { JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); factory.setAddress("http://localhost:9000/myservice"); factory.setServiceClass(MyServiceImpl.class); factory.getInInterceptors().add(new LoggingInInterceptor()); factory.getOutInterceptors().add(new LoggingOutInterceptor()); factory.create(); } }
主要:如果jdk版本比較低會報java.lang.LinkageError: JAXB 2.0 API jar is being loaded, but this RI (...) needs 2.2 API.類似的錯誤。此時需要在運行該類的時候指定運行參數,打開Run Configurations窗口,在VM arguments輸入如下參數:
-Djava.ext.dirs=C:\apache-cxf-3.0.3\lib\endorsed
表示指定jvm運行的時候,加載C:\apache-cxf-3.0.3\lib\endorsed目錄下的jar文件。如下圖所示
點擊Apply,運行即可。
4、運行Server類
啟動成功后,我們可以通過瀏覽器訪問wsdl文件,使用http://localhost:9000/myservice?wsdl 地址訪問即可。wsdl文件內容如下:
1 <?xml version='1.0' encoding='UTF-8'?> 2 <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" 3 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://testauto.cxf.com/" 4 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" 5 name="MyServiceImplService" targetNamespace="http://testauto.cxf.com/"> 6 <wsdl:types> 7 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 8 xmlns:tns="http://testauto.cxf.com/" elementFormDefault="unqualified" 9 targetNamespace="http://testauto.cxf.com/" version="1.0"> 10 11 <xs:element name="sayHello" type="tns:sayHello" /> 12 <xs:element name="sayHelloResponse" type="tns:sayHelloResponse" /> 13 14 <xs:complexType name="sayHello"> 15 <xs:sequence> 16 <xs:element minOccurs="0" name="arg0" type="xs:string" /> 17 <xs:element minOccurs="0" name="arg1" type="xs:string" /> 18 <xs:element minOccurs="0" name="arg2" type="xs:string" /> 19 </xs:sequence> 20 </xs:complexType> 21 22 <xs:complexType name="sayHelloResponse"> 23 <xs:sequence> 24 <xs:element minOccurs="0" name="return" type="xs:string" /> 25 </xs:sequence> 26 </xs:complexType> 27 28 </xs:schema> 29 </wsdl:types> 30 31 <wsdl:message name="sayHelloResponse"> 32 <wsdl:part element="tns:sayHelloResponse" name="parameters"> 33 </wsdl:part> 34 </wsdl:message> 35 <wsdl:message name="sayHello"> 36 <wsdl:part element="tns:sayHello" name="parameters"> 37 </wsdl:part> 38 </wsdl:message> 39 40 <wsdl:portType name="MyService"> 41 <wsdl:operation name="sayHello"> 42 <wsdl:input message="tns:sayHello" name="sayHello"> 43 </wsdl:input> 44 <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"> 45 </wsdl:output> 46 </wsdl:operation> 47 </wsdl:portType> 48 49 <wsdl:binding name="MyServiceImplServiceSoapBinding" type="tns:MyService"> 50 <soap:binding style="document" 51 transport="http://schemas.xmlsoap.org/soap/http" /> 52 <wsdl:operation name="sayHello"> 53 <soap:operation soapAction="" style="document" /> 54 <wsdl:input name="sayHello"> 55 <soap:body use="literal" /> 56 </wsdl:input> 57 <wsdl:output name="sayHelloResponse"> 58 <soap:body use="literal" /> 59 </wsdl:output> 60 </wsdl:operation> 61 </wsdl:binding> 62 63 <wsdl:service name="MyServiceImplService"> 64 <wsdl:port binding="tns:MyServiceImplServiceSoapBinding" 65 name="MyServiceImplPort"> 66 <soap:address location="http://localhost:9000/myservice" /> 67 </wsdl:port> 68 </wsdl:service> 69 </wsdl:definitions>
5、通過wsdl文件生成客戶端
將C:\apache-cxf-3.0.3\bin 添加進系統環境變量path中。
cmd進入c盤根目錄,運行命令
C:\>wsdl2java -client -encoding utf8 -frontend jaxws21 http://localhost:9000/myservice?wsdl
該命令根據wsdl生產調用的客戶端。-client表示生成客戶端;-encoding表示生成的java代碼的編碼格式;frontend表示參照jaxws21標准;ttp://localhost:9000/myservice?wsdl為wsdl的地址,也可以是磁盤上的某一個wsdl文件。
執行結果如下:
命令執行成功后將會在c盤根目錄下生成客戶端的調用代碼:生成的代碼結構如下
我們主要使用到的就是MyService_MyServiceImplPort_Client.java這個調用類。
6、進行調用,新建另一個java工程cxf_client,將生成的客戶端代碼拷貝到這個工程中。並對MyService_MyServiceImplPort_Client.java類進行修改。
MyService_MyServiceImplPort_Client.java修改后的內容如下:
package com.cxf.testauto; /** * Please modify this class to meet your needs * This class is not complete */ import java.io.File; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.ws.RequestWrapper; import javax.xml.ws.ResponseWrapper; /** * This class was generated by Apache CXF 3.0.3 * 2015-01-13T13:58:38.847+08:00 * Generated source version: 3.0.3 * */ public final class MyService_MyServiceImplPort_Client { private static final QName SERVICE_NAME = new QName("http://testauto.cxf.com/", "MyServiceImplService"); private MyService_MyServiceImplPort_Client() { } public static void main(String args[]) throws java.lang.Exception { URL wsdlURL = MyServiceImplService.WSDL_LOCATION; if (args.length > 0 && args[0] != null && !"".equals(args[0])) { File wsdlFile = new File(args[0]); try { if (wsdlFile.exists()) { wsdlURL = wsdlFile.toURI().toURL(); } else { wsdlURL = new URL(args[0]); } } catch (MalformedURLException e) { e.printStackTrace(); } } MyServiceImplService ss = new MyServiceImplService(wsdlURL, SERVICE_NAME); MyService port = ss.getMyServiceImplPort(); { System.out.println("Invoking sayHello..."); java.lang.String _sayHello_arg0 = "zhangsan"; java.lang.String _sayHello_arg1 = "beijing"; java.lang.String _sayHello_arg2 = "hello world"; java.lang.String _sayHello__return = port.sayHello(_sayHello_arg0, _sayHello_arg1, _sayHello_arg2);//對webservice 接口進行調用 System.out.println("sayHello.result=" + _sayHello__return); } System.exit(0); } }
運行該類,完成調用。
client端打印的結果如下:
server端打印的結果如下: