Apache CXF入門

關於Apache CXF

Apache CXF = Celtix + XFire,開始叫 Apache CeltiXfire,後來更名爲 Apache CXF 了,以下簡稱爲 CXF。CXF 繼承了 Celtix 和 XFire 兩大開源項目的精華,提供了對 JAX-WS 全面的支持,並且提供了多種 Binding 、DataBinding、Transport 以及各種 Format 的支持,並且可以根據實際項目的需要,採用代碼優先(Code First)或者 WSDL 優先(WSDL First)來輕鬆地實現 Web Services 的發佈和使用。Apache CXF已經是一個正式的Apache頂級項目。

Apache CXF 是一個開源的 Services 框架,CXF 幫助您利用 Frontend 編程 API 來構建和開發 Services ,像 JAX-WS 。這些 Services 可以支持多種協議,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,並且可以在多種傳輸協議上運行,比如:HTTP、JMS 或者 JBI,CXF 大大簡化了 Services 的創建,同時它繼承了 XFire 傳統,一樣可以天然地和 Spring 進行無縫集成。

CXF開發環境

CXF的官方下載地址:http://cxf.apache.org/download.html,現在目前最新版本爲apache-cxf-3.1.11,集成spring4.x版本.本文案例中使用apache-cxf-2.7.18集成spring3.x以作說明.

下面是我下載下來的apache-cxf-3.1.11和apache-cxf-2.7.18版本:apache-cxf-3.1.11  apache-cxf-2.7.18

下載下來之後目錄文件如下:


配置CXF的環境變量:(確保你已經配置好了JDK的環境,這裏就不說明了)

新建CXF_HOME變量:G:\Tools\JAVA\cxf\apache-cxf-2.7.18

編輯classpath變量:加入%CXF_HOME%\lib;

編輯path變量:加入%CXF_HOME%\bin;

開發說明:

這裏稍微寫明一下本文案列的開發環境版本,由於版本的不一樣會稍有影響,比如tomcat7以下的會報cxf2.17.18中servlet的錯,所以這裏大家都注意一下吧.

TomCat8.0 JDK1.8 eclipse-inst-win64(server 和client) CXF2.7.18 

另外,案例代碼風格部分稍微有點C#風格,你們可以自己寫,不用和我的一樣.

入門教程案例:

1.HelloWorld

由於最簡單的入門案例,這裏就直接先貼上代碼,容易理解的東西,相信大家都看得明白.

server端:Eclipse新建一個Dynamic Web Project項目

新建IHelloService接口

package yzr.interfaces;

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

@WebService
public interface IHelloService {
	 String sayHello(@WebParam(name="name") String name);
}

實現IHelloService的實現類HelloService

package yzr.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import yzr.interfaces.IHelloService;

@WebService(targetNamespace = "http://localhost:9000/",
portName = "HelloServicePort",
serviceName = "HelloServiceService")
@SOAPBinding(style=Style.RPC)
public class HelloService implements IHelloService {
	
	@WebMethod(action = "sayHello")
	public String sayHello(@WebParam(name="name") String name){
		return "Hello, I'm "+name;
	}
}

測試發佈:

package yzr.main;
import javax.xml.ws.Endpoint;
import yzr.interfaces.IHelloService;
import yzr.service.HelloService;
public class run {
	public static void main(String[] args) {
		depolyService();
		System.out.println("Server Started.......");
	}
	public static void depolyService(){
		HelloService hs=new HelloService();
		String address="http://localhost:9000/HelloWorld";
		Endpoint.publish(address, hs);
	}
}

打開瀏覽器訪問:http://localhost:9000/HelloWorld?wsdl

client端:Eclipse新建一個java project

和server端一樣的接口:IHelloService

package yzr.interfaces;

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

@WebService
public interface IHelloService {
	 String sayHello(@WebParam(name="name") String name);
}
導入jar包:


測試獲取數據:

package yzr.main;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import yzr.interfaces.IHelloService;
import yzr.interfaces.IUserService;

public class app {

	public static void main(String[] args) {
		// 調用WebService
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
	
		factory.setServiceClass(IHelloService.class);
		factory.setAddress("http://localhost:9000/HelloWorld");
		IHelloService service = (IHelloService) factory.create();
		System.out.println("[result]" + service.sayHello("YZR"));
	}

}

總結:在這個例子中,server端並沒有用到cxf,所以server並不需要導入cxf依賴的jar包,僅僅只是使用JAX-WS規範發佈了服務,而在client端中使用CXF來獲取服務.

2.在server中使用CXF

此例與上面的HelloWorld不同的地方是在server中,client保持不變.

在server端中導入CXF依賴的jar包:


使用CXF發佈服務:

package yzr.main;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.phase.Phase;

import yzr.intercepter.LoginInIntercepter;
import yzr.intercepter.LoginOutIntercepter;
import yzr.service.HelloService;

public class app {

	public static void main(String[] args) {
		depolyService();
		System.out.println("服務已經發布.......");
	}

	public static void depolyService() {
		// 發佈WebService
		JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
		// 設置Service Class
		factory.setServiceClass(HelloService.class);
		factory.setAddress("http://localhost:9000/HelloWorld");
		// 設置ServiceBean對象
		factory.setServiceBean(new HelloService());
		factory.create();

		System.out.println("Server start ......");

	}

}

總結:使用CXF管理webservice最簡單的例子就是上面這個了,發佈以及獲取服務,除此之外,我們還可以在服務上添加攔截器Intercepter.

3.添加Intercepter攔截器

CXF提供了AbstractPhaseInterceptor<Message>攔截器父類,往服務添加的攔截器需要繼承它,重寫void handleMessage(Message message)這個方法即可以編寫邏輯代碼.

比如LoginInIntercepter

package yzr.intercepter;

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;

public class LoginInIntercepter extends AbstractPhaseInterceptor<Message> {
	//至少要一個帶參的構造函數
    public LoginInIntercepter(String phase) {
		super(phase);
	}

	@Override
	public void handleMessage(Message message) throws Fault {
		System.out.println("進入LoginInIntercepter");
		System.out.println(message);
		/*
		if (message.getDestination() != null) {
			System.out.println(message.getId() + "#" + message.getDestination().getMessageObserver());
		}
		if (message.getExchange() != null) {
			System.out.println(message.getExchange().getInMessage() + "#" + message.getExchange().getInFaultMessage());
			System.out.println(message.getExchange().getOutMessage() + "#" + message.getExchange().getOutFaultMessage());
		}
        */
	}
	
}

在發佈服務之前,往cxf的factory添加攔截器內容:

package yzr.main;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.phase.Phase;

import yzr.intercepter.LoginInIntercepter;
import yzr.intercepter.LoginOutIntercepter;
import yzr.service.HelloService;

public class app {

	public static void main(String[] args) {
		depolyService();
		System.out.println("服務已經發布.......");
	}

	public static void depolyService() {
		// 發佈WebService
		JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
		// 設置Service Class
		factory.setServiceClass(HelloService.class);
		factory.setAddress("http://localhost:9000/HelloWorld");
		// 設置ServiceBean對象
		factory.setServiceBean(new HelloService());

		// 添加請求和響應的攔截器,Phase.RECEIVE只對In有效,Phase.SEND只對Out有效
		factory.getInInterceptors().add(new LoginInIntercepter(Phase.RECEIVE));
		factory.getOutInterceptors().add(new LoginOutIntercepter(Phase.SEND));

		factory.create();

		System.out.println("Server start ......");

	}

}
總結:攔截器攔截有兩個方向,一個是進入服務之前和執行完服務之後.通過Phase.RECEIVE和Phase.SEND指定.

4.傳遞複雜對象

上面使用CXF發佈服務中,傳遞的都是字符串類型的數據,在此例中將演示CXF傳遞複雜對象,比如集合等類型的對象

在server端新建User對象:

package yzr.entity;

import java.io.Serializable;

public class User implements Serializable {
	private static final long serialVersionUID = -8645524298402587268L;
	
	public User(){}
	public User(String name){
		this.name=name;
	}
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
}

創建IUserService服務接口:

package yzr.interfaces;

import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebService;

import yzr.entity.User;

@WebService
public interface IUserService {
	@WebMethod(action = "getUser")
	User getUser();
	@WebMethod(action = "getUsers")
	List<User> getUsers();
}

實現IUserService服務接口:

package yzr.service;

import java.util.ArrayList;
import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import yzr.entity.User;
import yzr.interfaces.IUserService;
@WebService
@SOAPBinding(style=Style.RPC)
public class UserServiceImpl implements IUserService {

	@Override
	@WebMethod(action = "getUser")
	public User getUser() {
		return new User("YZR");
	}

	@Override
	@WebMethod(action = "getUsers")
	public List<User> getUsers() {
		List<User> list=new ArrayList<User>();
		list.add(new User("LYF"));
		list.add(new User("YZR"));
		return list;
	}
	
}

CXF發佈服務:

package yzr.main;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.phase.Phase;

import yzr.intercepter.LoginInIntercepter;
import yzr.intercepter.LoginOutIntercepter;
import yzr.service.UserServiceImpl;

public class deployUser {

	public static void main(String[] args) {
		// 發佈WebService
		JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
		// 設置Service Class
		factory.setServiceClass(UserServiceImpl.class);
		factory.setAddress("http://localhost:9000/User");
		// 設置ServiceBean對象
		factory.setServiceBean(new UserServiceImpl());

		// 添加請求和響應的攔截器,Phase.RECEIVE只對In有效,Phase.SEND只對Out有效
		factory.getInInterceptors().add(new LoginInIntercepter(Phase.RECEIVE));
		factory.getOutInterceptors().add(new LoginOutIntercepter(Phase.SEND));

		factory.create();

		System.out.println("Server start ......");

	}

}
在Client中需要User對象實體和IUserService服務接口,獲取服務信息:

package yzr.main;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import yzr.interfaces.IHelloService;
import yzr.interfaces.IUserService;

public class app {

	public static void main(String[] args) {
		// 調用WebService
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setServiceClass(IUserService.class);
		factory.setAddress("http://localhost:9000/User");
		IUserService service = (IUserService) factory.create();
		System.out.println("[result]" + service.getUser());
		System.out.println("[List]" + service.getUsers());
		/*
		factory.setServiceClass(IHelloService.class);
		factory.setAddress("http://localhost:9000/HelloWorld");
		IHelloService service = (IHelloService) factory.create();
		System.out.println("[result]" + service.sayHello("YZR"));
		*/
	}

}

5.CXF和Spring集成

導入依賴spring的jar包:


server端:編寫server-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:endpoint id="ProjectManager" implementor="yzr.service.UserServiceImpl"  address="http://localhost:9000/User">
	</jaxws:endpoint>
	
	
</beans>

CXF發佈服務:

package yzr.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class server {

	public static void main(String[] args) {
		new ClassPathXmlApplicationContext(new String[]{"/yzr/main/server-beans.xml"});
		
                System.out.println("Server Started Success....");
	}

}

Client端:有兩種方式接收服務信息,,首先還是導入依賴Spring的jar包.

第一種方式:client-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:client id="client" serviceClass="yzr.interfaces.IUserService" address="http://localhost:9000/User"></jaxws:client>
</beans>

第二種方式:CXFClient-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">
	<bean id="client" class="yzr.main.Client" factory-bean="clientFactory" factory-method="create" />
	<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
		<property name="serviceClass" value="yzr.interfaces.IUserService"></property>
		<property name="address" value="http://localhost:9000/User"></property>
	</bean>
</beans>

接收服務:

package yzr.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import yzr.interfaces.IUserService;

public class Client {

	public static void main(String[] args) {
		//JAX-WS規範方式
		ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"/yzr/main/client-beans.xml"});
		IUserService service1=(IUserService)context.getBean("client");
		System.out.println(service1.getUser());
		System.out.println(service1.getUsers());
		
		//CXF方式
		context=new ClassPathXmlApplicationContext(new String[]{"/yzr/main/CXFClient-beans.xml"});
		IUserService service2=(IUserService)context.getBean("client");
		System.out.println(service2.getUser());
		System.out.println(service2.getUsers());
	}

}


6.Servlet容器中的webservice實現

上面的例子中都是在main函數發佈服務,接下來將演示如何將服務在tomcat中運行起來

新建applicationContext-server.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">
	
	<jaxws:endpoint id="ProjectManager" implementor="yzr.service.UserServiceImpl"
		address="http://localhost:9000/User">
	</jaxws:endpoint>
	
	
</beans>
修改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>cxfService</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:applicationContext-server.xml</param-value>
	</context-param>
	
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- 
	<listener>
		<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
	</listener>
         -->
    

	<servlet>
		<servlet-name>CXFService</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFService</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
    
    
</web-app>

添加一個tomcat8.0(7以上)server,運行即可.

案例代碼下載:點擊















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章