1. 程式人生 > >CXF WebService開發

CXF WebService開發

很多個系統,進行分佈的部署,分佈的系統資料通訊 解決技術就是 WebService。
CXF 是目前最主流 WebService 開發框架

CXF主要分為兩種服務

JAX-WS 傳輸資料,就是 XML 格式,基於 SOAP 協議
JAX-RS 傳輸資料,傳輸 XML 格式或者 JSON 格式,基於 HTTP 協議

JAX-WS獨立服務使用

匯入CXFjar包支援 Maven座標

   	<dependencies>
		<!-- 進行jaxes 服務開發 -->
		<dependency>
			<groupId>
org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.0.1</version> </dependency> <!-- 內建jetty 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>

編寫服務端的程式碼

  1. 實體類
    Car

    private Integer id;
    private String carName;
    private Double price;
    

    User

    private Integer id;
    private String carName;
    private Double price;
    
  2. 服務端程式
    IUserService介面

    @WebService
    //用來標記類是WebService服務提供物件
    public interface IUserService {
    @WebMethod
    //用來標記方法是WebService提供的方法
    public String sayHello(String name);
    
    @WebMethod
    public List<Car> findCarsByUser(User user);
    }
    

    UserServiceImpl

    @WebService(endpointInterface = "cn.lzh.cxf.service.IUserService", serviceName = 		"userService")
    //endpointInterface介面服務完整全類名
    //serviceName服務名稱
    public class UserServiceImpl implements IUserService {
    //簡單引數傳遞
    public String sayHello(String name) {
    	return "Hello," + name;
    }
    
    //複雜引數 傳遞
    public List<Car> findCarsByUser(User user) {
    	// 這裡本應該查詢資料庫的,為了演示,做一些假資料
    	if ("xiaoming".equals(user.getUsername())) {
    		List<Car> cars = new ArrayList<Car>();
    		Car car1 = new Car();
    		car1.setId(1);
    		car1.setCarName("大眾途觀");
    		car1.setPrice(200000d);
    		cars.add(car1);
    
    		Car car2 = new Car();
    		car2.setId(2);
    		car2.setCarName("現代ix35");
    		car2.setPrice(170000d);
    		cars.add(car2);
    
    		return cars;
    	} else {
    		return null;
    	}
    }
    }
    
  3. 將userService註冊到網上

    //將CXY 將 UserServer註冊到網路上
    	//1.服務實現物件
    	IUserService userService = new UserServiceImpl();
    	//2釋出服務地址
    	String address = "http://localhost:8888/userService";
    	//3釋出服務
    	Endpoint.publish(address, userService);
    	System.out.println("服務已經啟動...");
    

    成功介面
    在這裡插入圖片描述

  4. 客戶端

    //ws客戶端
    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();
    	//呼叫代理物件任何一個方法,都將網路呼叫web服務
    	System.out.println(proxy.sayHello("你好"));
    }
    }
    

    在這裡插入圖片描述
    服務啟動成功 可以用網路呼叫該服務
    注意
    可以通過
    jaxWsProxyFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
    jaxWsProxyFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
    開啟日誌資訊

JAX-WS和Spring整合開發WebService

匯入CXF_WS的Maven座標 與tomcat外掛

<dependencies>
  <!-- CSF WS開發核心 -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.0.1</version>
		</dependency>
	
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>

		<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>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>tomcat-maven-plugin</artifactId>
				<version>1.1</version>
				<configuration>
					<port>9800</port>
				</configuration>
			</plugin>
		</plugins>
	</build>

配置web.xml

	<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 WS基於web訪問的servlet -->
	<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>

application的配置

	<?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"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
	<!-- 
		address 客戶端訪問伺服器路徑
		serviceClass 配置介面
		serviceBean 配置實現
	 -->
	<jaxws:server id="userService" address="/userService" serviceClass="cn.lzh.cxf.service.IUserService">
		<jaxws:serviceBean>
			<bean class="cn.lzh.cxf.service.UserServiceImpl" />
		</jaxws:serviceBean>
	</jaxws:server>
	
</beans>

客戶端的測試
application-test的配置

<?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"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<!--
	 serviceClass :服務介面
	 address 服務訪問地址
	 -->
	<jaxws:client id="userServiceClient" serviceClass="cn.lzh.cxf.service.IUserService" 
		address="http://localhost:9800/cxf_ws_spring/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>
</beans>

測試程式碼:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class WS_spring_test {
	
	@Autowired
	private IUserService proxy;
	
	@Test
	public void testCXF(){
		System.out.println(proxy.sayHello("你好"));
	}

}

結果:
在這裡插入圖片描述
服務訪問成功

JAX-RS獨立使用

重點
要先了解restful風格:
在我認為restful是通過資源進行定位或進行操作的,不是什麼標準,也不是什麼協議,網際網路的任何事物都是

資源,比如說網路上有張圖片,我只需要知道那張圖片的名字,通過圖片名字的url來定位到這張圖片,
資源操作 我們用資料庫的crud 對應htpp方法,比如put修改 post儲存 get查詢,delete刪除,這樣我們能建立

統一的介面,減少程式碼的開發,提升開發效率 而且基於http協議,支援多種訊息格式,比如xml jason 更容

易實現快取機制,tomcat有快取機制,第一次訪問資源,第二次訪問資源,返回304客戶端呼叫本地

  1. 新增Maven依賴
<dependencies>
  <!-- 使用CXF RS開發 -->
  	<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>3.0.1</version>
		</dependency>
 <!-- 內建jetty 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>
  1. 編寫實體類
    car
	@XmlRootElement(name = "Car")
	//指定序列化時(轉換xml json)物件名字
public class Car {
	private Integer id;
	private String carName;
	private Double price;

	public Integer getId() {
		return id;
	}

注意要寫@XMLRootElement註解
User

	@XmlRootElement(name = "User")
public class User {
	private Integer id;
	private String username;
	private String city;

	private List<Car> cars = new ArrayList<Car>();

  1. 編寫服務端程式
    IUserService
	@Path("/userService")
//服務訪問資源路徑
@Produces("*/*")
//生成(返回值) 指定能夠生成哪種格式資料返回給客戶端
public interface IUserService {

	@POST
	//請求http協議的 增加
	@Path("/user")
	@Consumes({ "application/xml", "application/json" })
	//方法的引數 指定能夠處理客戶端傳遞過來的資料格式
	public void saveUser(User user);

	@PUT
	@Path("/user")
	//請求http協議的 修改
	@Consumes({ "application/xml", "application/json" })
	public void updateUser(User user);

	@GET
	@Path("/user")
	//請求http協議的 查詢
	@Produces({ "application/xml", "application/json" })
	
	public List<User> findAllUsers();
	//生成(返回值) 指定能夠生成哪種格式資料返回給客戶端
	@GET
	@Path("/user/{id}")
	@Consumes("application/xml")
	@Produces({ "application/xml", "application/json" })
	public User finUserById(@PathParam("id") Integer id);

	@DELETE
	@Path("/user/{id}")
	//請求http協議的 刪除
	@Consumes("application/xml")
	public void deleteUser(@PathParam("id") Integer id);
}

注意 如果要返回資料要加@Produces註解 引數為可以處理的資料格式
注意 如果要接受引數要加@Consumes註解 引數為可以處理的資料格式

將服務釋出到網路

	//建立業務介面實現類物件
		IUserService userService = new UserServiceImpl();
		//伺服器FactoryBean建立服務
		JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
		//將那些實體轉換成xml、json傳送
		restServer.setResourceClasses(User.class,Car.class);
		//設定服務的bean
		restServer.setServiceBean(userService);
		//設定地址
		restServer.setAddress("http://localhost:9999");
		
		//列印日誌
		restServer.getInInterceptors().add(new LoggingInInterceptor());
		restServer.getOutInterceptors().add(new LoggingOutInterceptor());
		//釋出服務
		restServer.create();

客戶端程式碼

首先要在maven新增WebClient依賴

<!-- 使用rs客戶端 裡面有個工具包為rs client -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-client</artifactId>
			<version>3.0.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-rs-extension-providers<