Java CXF介紹與例項

oscar999發表於2020-04-06

CXF簡介

CXF是一個Java 版的Web Service框架

CXF是由過去的Celtix和XFire兩個框架合併而來,CXF在java社群有廣泛的接受度是得益於它能很好的整合Spring。
CXF最突出的兩個優勢是:
1.對JAX-WS規範的完整實現。 作為java平臺上的WebService標準,過去既有的WebService產品必然會向這一標準靠攏,而JAX-WS標準本身大大地降低了開發WebService的工作量,對於開發人員來說,是非常受歡迎的。
2.對Spring的友好支援。 CXF從Xfire繼承而來,對Spring有著非常友好的支援。鑑於Spring的廣泛應用,對很多團隊來說這是非常有吸引力的一點。


官方網站:http://cxf.apache.org/


CXF VS Axis2

CXF和Axis2是目前java平臺上最主流的兩個框架,雖然兩個專案都隸屬ASF,但卻是基於不同思想和風格實現的,因此也各有所長。

1.CXF支援 WS-Addressing,WS-Policy, WS-RM, WS-Security和WS-I Basic Profile。Axis2不支援WS-Policy,但是承諾在下面的版本支援。 

2. CXF可以很好支援Spring。Axis2不能 

3. AXIS2支援更廣泛的資料並對,如XMLBeans,JiBX,JaxMe和JaxBRI和它自定義的資料繫結ADB。注意JaxME和JaxBRI都還是試驗性的。CXF只支援JAXB和Aegis。在CXF2.1 

4. Axis2支援多語言-除了Java,他還支援C/C++版本。 

如果你需要多語言的支援,你應該選擇AXIS2。如果你需要把你的實現側重JAVA並希望和Spring整合,CXF就是更好的選擇,特別是把你的Web Service嵌入其他的程式中

通過網路渠道的瞭解,目前CXF的效率要比AXIS2高出至少50%
另外有一個webService的工具metro的效率比CXF高出10%

效能比較:
https://www.ibm.com/developerworks/cn/java/j-jws14/

CXF開發


使用CXF可以進行Web Service 的服務端和客戶端的開發。

服務端就是使用Java釋出Web Service服務,(CXF框架會轉化為WSDL.)

客戶端則是使用Java呼叫Web Service服務,(CXF框架可以將WSDL轉化為java程式碼)。

所以在對WSDL不是很熟悉的情況下, 也可以也容易的進行Web Service的開發和呼叫。

客戶端的呼叫,相對簡單;這裡主要說一下CXF服務端的開發。

CXF服務端開發的方式主要有三種:

1. 不需要Web伺服器的開發。

一般我們的認知是Web Service需要部署在Web容器下才能生效和看到效果, 這個認知沒有錯。

只是CXF有自帶一個輕量的容器服務,在沒有Tomcat等Web伺服器的狀況下可以進行Web Service的釋出和測試。

所以用來開發的專案可以一個簡單的Java 專案。

2. 基於Web的開發

一個web 專案, 部署在伺服器中。

3. 結合Spring進行開發。

在Spring 中整合CXF.

好了, 接下來就介紹第1種服務端開發的方式和客戶端呼叫的例項, 基於Web的開發和Spring的整合部分會在另外一篇介紹。

不需要Web伺服器的開發

首先, 需要到官方網站獲取CXF. 這裡使用的版本是 3.2.4 

http://www.apache.org/dyn/closer.lua/cxf/3.2.4/apache-cxf-3.2.4.zip

將jar檔加入到專案的lib中;如果是使用Maven,則加入如下部分:

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf</artifactId>
			<version>3.2.4</version>
			<type>pom</type>
		</dependency>

接下來就開始實際的程式碼部分了

1. 定義介面. 

/**
 * @Title: MyWebServiceI.java
 * @Package com.oscar999
 * @Description: TODO
 * @author oscar999
 * @date May 23, 2018 11:34:39 AM
 * @version V1.0
 */

package com.oscar999.cxf;

import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * @ClassName: MyWebServiceI
 * @Description: TODO
 * @author oscar999
 */

@WebService
public interface MyWebServiceI {

	String sayHi(@WebParam(name = "text") String text);
}

2. 實現介面

/**
 * @Title: MyWebServiceImpl.java
 * @Package com.oscar999
 * @Description: TODO
 * @author oscar999
 * @date May 23, 2018 11:37:02 AM
 * @version V1.0
 */

package com.oscar999.cxf;

import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * @ClassName: MyWebServiceImpl
 * @Description: TODO
 * @author oscar999
 */

@WebService(endpointInterface = "com.oscar999.cxf.MyWebServiceI", serviceName = "Hello")
public class MyWebServiceImpl implements MyWebServiceI {

	public String sayHi(@WebParam(name = "text") String text) {
		return "Hello," + text;
	}
}

3. 釋出服務

/**
 * @Title: MyWebServiceServer.java
 * @Package com.oscar999
 * @Description: TODO
 * @author oscar999
 * @date May 23, 2018 1:12:27 PM
 * @version V1.0
 */

package com.oscar999.cxf;

import javax.xml.ws.Endpoint;

/**
 * @ClassName: MyWebServiceServer
 * @Description: TODO
 * @author oscar999
 */

public class MyWebServiceServer {

	/**
	 * @Title: main
	 * @Description: TODO
	 * @param args
	 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("web service start...");
		MyWebServiceImpl myWebService = new MyWebServiceImpl();
		String address = "http://localhost:8080/myWebService";
		Endpoint.publish(address, myWebService);
		System.out.println("web service started"); 
	}

}

以Java Application的方式執行這個程式,在瀏覽器輸入:

http://localhost:8080/myWebService?wsdl

接可以看到對應的WSDL了。

客戶端呼叫例項

客戶端呼叫需要匯入其他的一些lib 包, 使用maven的話,加入以下依賴配置:

<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>3.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>3.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.woodstox</groupId>
			<artifactId>stax2-api</artifactId>
			<version>4.1</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.woodstox</groupId>
			<artifactId>woodstox-core-asl</artifactId>
			<version>4.4.1</version>
		</dependency>

基於以上服務端的客戶端程式碼:

/**
 * @Title: MyWebServiceClient.java
 * @Package com.oscar999.cxf
 * @Description: TODO
 * @author oscar999
 * @date May 23, 2018 2:06:28 PM
 * @version V1.0
 */

package com.oscar999.cxf;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**
 * @ClassName: MyWebServiceClient
 * @Description: TODO
 * @author oscar999
 */

public class MyWebServiceClient {

	/**
	 * @Title: main
	 * @Description: TODO
	 * @param args
	 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JaxWsProxyFactoryBean jwpfb = new JaxWsProxyFactoryBean();
		jwpfb.setServiceClass(MyWebServiceI.class);
		jwpfb.setAddress("http://localhost:8080/myWebService");
		MyWebServiceI myWebService = (MyWebServiceI) jwpfb.create();
		System.out.println(myWebService.sayHi("Oscar999"));

	}

}
執行一下, 就可以看到效果了。

相關錯誤解決

如果在以上例項中出現相關錯誤,可參考:

1. 客戶端測試需要加上 cxf-rt-frontend-jaxws、 cxf-rt-transports-http 和 cxf-rt-transports-http-jetty。
如果出現如下異常還需要  woodstox-core-asl ,  
SEVERE: Cannot find any registered HttpDestinationFactory from the Bus

stax2-api預設會有 3.1.4 , 但是執行的時候報
java.lang.RuntimeException: Cannot create a secure XMLInputFactory 的錯誤
是stax2-api版本低了, 加上stax2-api的4.1 版本。


2.在使用cxf過程中經常出 Cannot find any registered HttpDestinationFactory from the Bus,一般是沒有引入cxf-rt-transports-http-jetty-xxx.jar。檢視apache.cxf.transport.http.HTTPTransportFactory.getDestination(HTTPTransportFactory.java:270)類,jettyFactory為null,也就是缺少http-jetty的實現。

解決辦法:
在pom.xml檔案中新增:
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>3.1.6</version>
</dependency>

3.cxf呼叫報錯Could not find conduit initiator for address:
SOAP的傳輸協議是基於http協議的,需要相關依賴
報錯解決方案:
新增依賴:
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.2.2</version>
</dependency>

相關文章