WebService框架CXF的使用

一,WebService的簡介

Web service是一個平臺獨立的,低耦合的,自包含的、基於可編程的web的應用程序,可使用開放的XML(標準通用標記語言下的一個子集)標準來描述、發佈、發現、協調和配置這些應用程序,用於開發分佈式的互操作的應用程序。

簡單來說,很多個系統,進行分佈的部署,分佈的系統數據通信 解決技術就是WebService

目前比較主流的WebService開發框架主要有:Apache Axis1、Apache Axis2、Codehaus XFire、Apache CXF、Apache Wink、Jboss RESTEasy、sun JAX-WS(最簡單、方便)、阿里巴巴 Dubbo(除外)等。

目前三種主流的web服務實現方法:

REST(新型):表象化狀態轉變 (軟件架構風格)RESTEasy、Wink、CXF、Axis2…….(個人推薦使用)

SOAP(比較成熟):簡單對象訪問協議 Xfire、Axis2、CXF、Axis1

XML-RPC(淘汰):遠程過程調用協議(慢慢被soap 所取代)

二,CXF的下載和使用

官網下載:http://cxf.apache.org/

CXF WebService 開發,主要分爲兩種服務提供方式 JAX-WS,JAX-RS

在這裏插入圖片描述

JAX-WS 傳輸數據,就是 XML 格式,基於 SOAP 協議
JAX-RS 傳輸數據,傳輸 XML 格式或者 JSON 格式,基於 HTTP 協議(推薦使用)

1.JAX-WS(基於SOAP協議) 獨立服務使用

創建一個maven項目,在項目中導入 CXF jar 包支持
在這裏插入圖片描述

要提供 jaxws 服務,引入 jaxws 的 jar 包 , 要提供 jaxrs 服務,引入 jaxrs 的 jar 包(根據需要選擇導入)

在這裏插入圖片描述

在編寫服務層接口

在這裏插入圖片描述

出現上面的錯誤,是由於編譯插件jre的版本過低造成的

在這裏插入圖片描述
在pom.xml中添加編譯插件,並設置編譯版本,更新項目即可
在這裏插入圖片描述

package cn.xiaogui.cxf.service;

import java.util.List;

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

import cn.xiaogui.cxf.domain.Car;
import cn.xiaogui.cxf.domain.User;

@WebService  //標記類是WebService服務的提供對象
public interface IUserService {
	
	@WebMethod //標記方法是WebService服務的提供方法
	public String sayHello(String name);

	@WebMethod
	public List<Car> findCarsByUser(User user);
}

@WebService 使用類上面,標記類是 WebService 服務提供對象
@WebMethod 使用方法上面,標記方法 是 WebService 服務提供方法

編寫實現類

package cn.xiaogui.cxf.service.impl;

import java.util.List;

import javax.jws.WebService;

import cn.xiaogui.cxf.domain.Car;
import cn.xiaogui.cxf.domain.User;
import cn.xiaogui.cxf.service.IUserService;
//@WebService 註解設置 endPointInterface 接口服務完整類名, servicename 服務名稱
@WebService(endpointInterface="cn.xiaogui.cxf.service.IUserService",serviceName="IUserService")
public class UserServiceImpl implements IUserService {
	
	//簡單參數傳遞
	@Override
	public String sayHello(String name) {
		// TODO Auto-generated method stub
		return null;
	}
	
	//複雜參數傳遞
	@Override
	public List<Car> findCarsByUser(User user) {
		// TODO Auto-generated method stub
		return null;
	}

}

編寫CXF服務端,將 UserService 的服務方法,發佈到網絡上,給其它系統調用

package cn.xiaogui.cxf.ws.server;


import javax.xml.ws.Endpoint;

import cn.xiaogui.cxf.service.IUserService;
import cn.xiaogui.cxf.service.impl.UserServiceImpl;


public class WS_Server {
	public static void main(String[] args) {
		//使用CXF將userService服務註冊到網絡
		
		//1.創建服務實現類對象
		IUserService UserService = new UserServiceImpl();
		
		//2.發佈服務地址
		String address = "http://localhost:9999/userService";
		
		//3.發佈服務
		
		Endpoint.publish(address, UserService);
		
		System.out.println("服務發佈....");
		
		
	}
}

在瀏覽器輸入網址: http://localhost:9999/userService?wsdl 查看發佈的服務

編寫客戶端

package cn.xiaogui.cxf.ws.client;

import java.util.List;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import cn.xiaogui.cxf.domain.Car;
import cn.xiaogui.cxf.domain.User;
import cn.xiaogui.cxf.service.IUserService;
//客戶端應該編寫在另一個項目中,爲了方便測試,服務端和客戶端編寫在了同一個項目中
public class WS_Client {
	public static void main(String[] args) {
		//編寫客戶端,調用WebService服務
		
		JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
		
		//設置服務接口
		jaxWsProxyFactoryBean.setServiceClass(IUserService.class);
		
		//訪問服務發佈的地址
		jaxWsProxyFactoryBean.setAddress("http://localhost:9999/userService");
		
		//創建調用遠程服務代理對象
		IUserService proxy = (IUserService) jaxWsProxyFactoryBean.create();
		
		//調用代理對象的任意方法,都將通過網絡調用服務
//		System.out.println(proxy.sayHello("張三"));
		
		User user = new User();
		user.setUsername("xiaoming");
		List<Car> list = proxy.findCarsByUser(user);
		
		System.out.println(list);
	}
}

注意:服務端在開啓後,不要關閉,否則客戶端無法訪問。

2. JAX-WS 原理分析

在這裏插入圖片描述

客戶端創建一個服務接口IUserService的代理對象proxy,當調用服務接口中的方法時,會通過服務發佈的地址,來找到服務接口的實現類對象userService,然後去執行對應的方法。

3.JAX-WS 和 和 Spring 整合開發

注意:實體類和服務接口,實現類與上面的項目相同,不再演示。

創建一個maven web項目,基於 tomcat 發佈服務,導入相關的依賴

在這裏插入圖片描述

 <!-- CXF開發 -->
  	<dependency>
  		<groupId>org.apache.cxf</groupId>
  		<artifactId>cxf-rt-frontend-jaxws</artifactId>
  		<version>3.0.1</version>
  	</dependency>
  	
  	<!--  spring開發-->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-context</artifactId>
  		<version>4.3.8.RELEASE</version>
  	</dependency>
	<!-- spring Web集成 -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-web</artifactId>
  		<version>4.3.8.RELEASE</version>
  	</dependency>

	<!-- spring測試開發 -->
  	<dependency>
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>4.12</version>
  	</dependency>

  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-test</artifactId>
  		<version>4.3.8.RELEASE</version>
  	</dependency>


	<!-- 日誌實現 -->
  	<dependency>
  		<groupId>org.slf4j</groupId>
  		<artifactId>slf4j-log4j12</artifactId>
  		<version>1.7.12</version>
  	</dependency>

配置web.xml

Spring 配置文件加載、環境初始化

<!-- spring配置文件位置 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- spring核心監聽器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

CXF 基於 web 訪問 ****

<!--配置CXF基於web訪問  -->
	<servlet>
		<servlet-name>CXFService</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>CXFService</servlet-name>
		<url-pattern>/services/*</url-pattern>
	</servlet-mapping>

配置applicationContext.xml

引入名稱空間
xmlns:jaxws=“http://cxf.apache.org/jaxws
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd

配置服務

<!--
		address:服務發佈的地址
		serviceClass:服務接口的全類名
		jaxws:serviceBean:服務接口的實現類
	  -->

	<jaxws:server id="userService" address="/userService" serviceClass="cn.xiaogui.cxf.service.IUserService">
		<jaxws:serviceBean>
			<bean class="cn.xiaogui.cxf.service.impl.UserServiceImpl" />
		</jaxws:serviceBean>
	</jaxws:server>

配置啓動服務端口

在這裏插入圖片描述

訪問 :http://localhost:9998/services/userService?wsdl 查看發佈的服務

整合spring測試,編寫客戶端

   注意: 標準做法是新建一個項目來編寫客戶端,調用服務

客戶端applicationContext.xml的配置

<jaxws:client id="userServiceClient" 
				  serviceClass="cn.xiaogui.cxf.service.IUserService"
				  address="http://localhost:9998/services/userService">
				  <!--可選配置 -->
				  <!-- 來源消息攔截器   主要用於在控制檯查看請求的一些信息 -->
				  <jaxws:inInterceptors>
				  	<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
				  </jaxws:inInterceptors>
				 
				  <!--可選配置 -->
				  <!-- 輸出消息攔截器   主要用戶在控制檯查看響應客戶端的一些信息-->
				  <jaxws:outInterceptors>
				  	<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
				  </jaxws:outInterceptors>
	</jaxws:client>

客戶端測試代碼:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext-test.xml")
public class IUserServiceTest {

	@Autowired
	private IUserService proxy;
	
	@Test
	public void testSayHello() {
		System.out.println(proxy.sayHello("李四"));
	}

	@Test
	public void testFindCarsByUser() {
		User user = new User();
		user.setUsername("xiaoming");
		List<Car> users = proxy.findCarsByUser(user );
		
		System.out.println(users);
	}

}

測試結果:

在這裏插入圖片描述

注意:需要在項目中添加log4j.properties屬性文件,才能查看到控制檯上輸出的上面的信息。

4. JAX-RS(基於REST設計風格) 獨立服務使用

Restful風格:
在這裏插入圖片描述
在這裏插入圖片描述

Restful風格編程的好處:

基於這種風格架構,軟件編寫可以更簡潔
基於 HTTP 協議, 支持多種消息格式,比如 XML 、JSON
基於 HTTP 協議,更易於實現緩存機制 (第一次訪問資源 緩存,第二次訪問資源,返回 304 客戶端調用本地)

編寫 JAX-RS 獨立服務應用

創建maven java項目,導入依賴

 <dependencies>
  	<!-- CXF的RS開發 -->
  	<dependency>
  		<groupId>org.apache.cxf</groupId>
  		<artifactId>cxf-rt-frontend-jaxrs</artifactId>
  		<version>3.0.1</version>
  	</dependency>
	<!-- 內置jetty  web服務器   和tomcat差不多 由於這不是一個web項目,所以需要這個內置的服務器來發布服務 -->
  	<dependency>
  		<groupId>org.apache.cxf</groupId>
  		<artifactId>cxf-rt-transports-http-jetty</artifactId>
  		<version>3.0.1</version>
  	</dependency>

	<!-- 日誌實現 -->
  	<dependency>
  		<groupId>org.slf4j</groupId>
  		<artifactId>slf4j-log4j12</artifactId>
  		<version>1.7.12</version>
  	</dependency>
  </dependencies>

導入實體
在這裏插入圖片描述

在這裏插入圖片描述

@XmlRootElement 指定序列化(轉換 XML、JSON) 對象名字

編寫業務類接口

@Path("/userService")
public interface IUserService {
	@POST
	@Path("/user")
	@Consumes({ "application/xml", "application/json" })
	public void saveUser(User user);

	@PUT
	@Path("/user")
	@Consumes({ "application/xml", "application/json" })
	public void updateUser(User user);

	@GET
	@Path("/user")
	@Produces({ "application/xml", "application/json" })
	public List<User> findAllUsers();

	@GET
	@Path("/user/{id}")
	@Consumes("application/xml")
	public User finUserById(@PathParam("id") Integer id);

	@DELETE
	@Path("/user/{id}")
	@Consumes("application/xml")
	public void deleteUser(@PathParam("id") Integer id);
}

第一種 @Path 服務訪問資源路徑
如果訪問 saveUser 方法 /userService/user
第二種 @Produces 生成(方法返回值) @Consumes 消費 (方法參數)
@Consumes 指定能夠處理客戶端傳遞過來數據格式
@Produces 指定能否生成哪種格式數據返回給客戶端
第三種 @GET 查詢 @PUT 修改 @POST 保存(增加或修改) @DELETE 刪除

編寫業務接口實現類
在這裏插入圖片描述

編寫服務端

	//使用CXF將userService服務發佈到網絡
		
		//1.創建服務接口的實現類對象
		IUserService userService = new UserServiceImpl();
		
		//服務器JAXRSServerFactoryBean 創建服務
		JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
		
		//將哪些實體數據轉換成xml,json格式發送
		restServer.setResourceClasses(User.class, Car.class);
		
		//設置服務接口的實現類對象
		restServer.setServiceBean(userService);
		
		//服務發佈地址
		restServer.setAddress("http://localhost:8888");

		// 打印日誌
		restServer.getInInterceptors().add(new LoggingInInterceptor());
		restServer.getOutInterceptors().add(new LoggingOutInterceptor());
		
		//發佈服務
		restServer.create();

編寫客戶端

有兩種做法
1) 使用 http client 工具 ,需要自己對 HTTP 協議內容進行定製和解析
2) WebClient 工具類使用 (CXF 自帶)

在這裏插入圖片描述

		/**
		 * create:建立與調用服務資源路徑的連接
		 * type:發送給服務器的數據格式   -----@Consumes
		 * accept:接收服務器響應的數據格式  ---@produces
		 * 
		 * 採用Http協議哪種方式訪問服務器
		 */
		
		Collection<? extends User> collection = WebClient.create("http://localhost:8888/userService/user")
		.accept(MediaType.APPLICATION_XML)
		.getCollection(User.class);
		
		System.out.println(collection);
		
		User user = WebClient.create("http://localhost:8888/userService/user/1")
		.accept(MediaType.APPLICATION_XML)
		.get(User.class);
		
		System.out.println(user);

輸出結果

在這裏插入圖片描述

JAX-RS 如何傳輸 JSON 格式的數據

在pom.xml中添加依賴

在這裏插入圖片描述

客戶端編寫代碼

	User user = WebClient.create("http://localhost:8888/userService/user/1")
		.type(MediaType.APPLICATION_JSON)
		.accept(MediaType.APPLICATION_JSON)
		.get(User.class);
		
		System.out.println(user);

輸出結果
在這裏插入圖片描述

5.JAX-RS 和 和 Spring 整合開發(開發中推薦使用)

創建maven web項目,導入依賴

CXF的RS開發

<!-- CXF的RS開發 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>3.0.1</version>
		</dependency>
		
		<!-- rs客戶端 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-client</artifactId>
			<version>3.0.1</version>
		</dependency>
		
		<!-- CXF的擴展提供者,提供轉換json接口 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-extension-providers</artifactId>
			<version>3.0.1</version>
		</dependency>
		
		<!--CXF的擴展提供者轉換json 默認需求的工具包  -->
		<dependency>
			<groupId>org.codehaus.jettison</groupId>
			<artifactId>jettison</artifactId>
			<version>1.3.7</version>
		</dependency>

spring開發

<!-- spring開發 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		
		<!-- spring集成web開發 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		
		<!-- spring測試開發 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>

日誌實現

<!-- 日誌實現 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>

tomcat插件

<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.1</version>
				<configuration>
					<path>/</path>
					<port>6666</port>
				</configuration>
			</plugin>

配置服務

在applicationContext.xml中有引入名稱空間:
xmlns:jaxrs=“http://cxf.apache.org/jaxrs
xsi:schemaLocation="
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd"

<!-- 
		address:服務發佈的地址
		jaxrs:serviceBeans:服務接口的實現類
	 -->
	
	<jaxrs:server id="userService" address="/userService" >
		<jaxrs:serviceBeans>
			<bean class="cn.xiaogui.cxf.service.impl.UserServiceImpl" />
		</jaxrs:serviceBeans>
		
		<!-- 下面兩個可選配置 -->
		<!-- 請求來源消息攔截器 -->
		<jaxrs:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
		</jaxrs:inInterceptors>
		
		<!-- 輸出消息攔截器 -->
		<jaxrs:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
		</jaxrs:outInterceptors>
	</jaxrs:server>
	

編寫客戶端,進行服務調用

public class RS_client {
	
	@Test
	public void test1() {
		
		/**
		 * create:建立與調用服務資源路徑的連接
		 * type:發送給服務器的數據格式   -----@Consumes
		 * accept:接收服務器響應的數據格式  ---@produces
		 * 
		 * 採用Http協議哪種方式訪問服務器
		 */
		Collection<? extends User> collection = WebClient.create("http://localhost:6666/services/userService/user")
		.accept(MediaType.APPLICATION_JSON)
		.getCollection(User.class);
		
		System.out.println(collection);
		
	}
}

結果輸出

在這裏插入圖片描述

分享示例項目在碼雲上的地址:https://gitee.com/xiaoguixiaogege/CXF

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