1. 程式人生 > >CXF非同步WebService釋出和呼叫

CXF非同步WebService釋出和呼叫

最近工作需要接觸CXF非同步webservice的釋出和呼叫,在網上Google並搗鼓了好一陣子,總算成功了。畢竟這方面的資料比較少,自己總結一下寫下這篇博文。本文將描述如何利用CXF來發布和呼叫非同步的webservice,通過一個示例,帶大家一步一步開發基於CXF的非同步webservice及客戶端呼叫程式。

【參考】

1.非同步webservice簡介

非同步webservice可以讓客戶端呼叫執行緒在呼叫webservice的時候不必阻塞等待服務端返回結果,在呼叫請求後快速返回,然後做其他想做的事情。

1.1 客戶端非同步呼叫方式

(1) Callback

客戶端通過實現javax.xml.ws.AsyncHandler

,從而讓服務端在做完操作後回撥AsyncHandler的handleResponse方法進行非同步處理。

(2) Polling

客戶端拿到javax.xml.ws.Response型別的返回結果,然後不斷輪詢Response的isDone方法來判斷是否呼叫已經完成。

1.2 服務端非同步呼叫的實現

CXF提供了兩種方法來響應客戶端的非同步webservice請求,包括:

(1) Continuations

CXF提供了API供開發者來建立並使用Continuation,關於continuation的詳細介紹請檢視以下連結:

(2) @UseAsyncMethod annotation

通過@UseAsyncMethod註解同步方法,讓同步方法在滿足非同步呼叫條件下呼叫其對應的非同步方法

@UseAsyncMethod
public String sayHello(String username) {
    return "hello " + username;
}

public Future<String> sayHelloAsync(String username,    AsyncHandler<String> asyncHandler) {
    // ...
    return null;
}

public Response<String> sayHelloAsync
(String username) { // ... return null; }

如上所示,sayHello方法註解了@UseAsyncMethod,如果web容器支援非同步呼叫,將會呼叫其對應的sayHelloAsync方法,如果不支援非同步呼叫,那麼將會呼叫同步的sayHello方法。

【注意】

CXF依賴於Web容器來發布webservice,必須確保Web容器支援非同步機制才能使CXF釋出的webservice成功處理來自客戶端的非同步請求。eg:通過Tomcat配置CXF釋出webservice必須確保配置在web.xml的CXFServlet配置了async-supported為true

2. 示例

通過釋出一個HelloService非同步webservice以及開發HelloClient來向大家說明基於CXF如何開發和呼叫非同步的webservice。示例程式碼可以在我的github拉取:CXFTutorial

2.1 環境說明

【軟體環境】

  • JDK 6+
  • STS(Eclipse)
  • Tomcat7

【依賴庫】

  • aopalliance-1.0.jar
  • asm-3.3.1.jar
  • commons-logging-1.1.1.jar
  • cxf-bundle-2.7.15.jar
  • httpasyncclient-4.0-beta3.jar
  • httpclient-4.2.5.jar
  • httpcore-4.2.4.jar
  • httpcore-nio-4.2.4.jar
  • neethi-3.0.3.jar
  • spring-aop-3.0.7.RELEASE.jar
  • spring-asm-3.0.7.RELEASE.jar
  • spring-beans-3.0.7.RELEASE.jar
  • spring-context-3.0.7.RELEASE.jar
  • spring-core-3.0.7.RELEASE.jar
  • spring-expression-3.0.7.RELEASE.jar
  • spring-web-3.0.7.RELEASE.jar
  • stax2-api-3.1.4.jar
  • woodstox-core-asl-4.4.1.jar
  • wsdl4j-1.6.3.jar
  • xmlschema-core-2.1.0.jar

2.2 開發webservice介面及實現類

2.2.1 開發HelloService介面

package com.hello;

import java.util.concurrent.Future;

import javax.jws.WebService;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
import javax.xml.ws.ResponseWrapper;

@WebService(name = "helloService")
public interface HelloService {

    @ResponseWrapper(localName = "sayHelloResponse", className = "java.lang.String")
    public String sayHello(String username);

    @ResponseWrapper(localName = "sayHelloResponse", className = "java.lang.String")
    public Future<String> sayHelloAsync(String username, AsyncHandler<String> asyncHandler);

    public Response<String> sayHelloAsync(String username);

}

2.2.2 實現HelloServiceImpl

package com.hello;

import java.util.concurrent.Future;

import javax.jws.WebService;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

import org.apache.cxf.annotations.UseAsyncMethod;
import org.apache.cxf.jaxws.ServerAsyncResponse;

@WebService(endpointInterface="com.hello.HelloService")
public class HelloServiceImpl implements HelloService {

    @Override
    @UseAsyncMethod
    public String sayHello(String username) {
        System.out.println("execute sayHello method");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello " + username;
    }

    @Override
    public Future<String> sayHelloAsync(String username,
            AsyncHandler<String> asyncHandler) {
        System.out.println("execute sayHelloAsync method");
        final ServerAsyncResponse<String> asyncResponse = new ServerAsyncResponse<String>();
        new Thread() {
            public void run() {
                String result = sayHello(username);
                asyncResponse.set(result);
                System.out.println("Responding on background thread\n");
                asyncHandler.handleResponse(asyncResponse);
            }
        }.start();
        return asyncResponse;
    }

    @Override
    public Response<String> sayHelloAsync(String username) {
        // TODO Auto-generated method stub
        return null;
    }

}

2.3 釋出webservice

2.3.1 配置cxf.xml

通過Spring配置CXF釋出webservice的埠及地址

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

    <jaxws:endpoint id="helloService" implementor="com.hello.HelloServiceImpl" address="/helloService"></jaxws:endpoint>

</beans>

【注意】 cxf.xml檔案放置在/WEB-INF/目錄下,即與web.xml處於同個目錄

2.3.2 配置web.xml

在web.xml裡面配置CXFServlet來發布webservice

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee           
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/cxf.xml</param-value>
    </context-param>

    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
    </servlet>

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

2.3.3 使用Tomcat載入應用

![show cxf publish services]({{ site.url }}/assets/image/async-webservice-using-cxf/show_cxf_publish_services.png)

2.4 開發webservice客戶端呼叫

package com.hello.client;

import java.util.concurrent.Future;


import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.hello.HelloService;


public final class HelloClient2 {

    public static void main(String args[]) throws Exception {

    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

    factory.setServiceClass(HelloService.class);
    factory.setAddress("http://192.168.16.52:8080/CXFTutorial/services/helloService?wsdl");
    factory.getInInterceptors().add(new LoggingInInterceptor());
    factory.getOutInterceptors().add(new LoggingOutInterceptor());
    HelloService client = (HelloService) factory.create();


    // callback method
    TestAsyncHandler testAsyncHandler = new TestAsyncHandler();
    System.out.println("Invoking changeStudentAsync using callback object...");
    Future<?> response = client.sayHelloAsync(
        "CrazyPig", testAsyncHandler);
    while (!response.isDone()) {
        Thread.sleep(100);
    }

    String resp = testAsyncHandler.getResponse();
    System.out.println("Server responded through callback with: " + resp);

    System.exit(0);
    }
}

通過實現了AsyncHandler介面的TestAsyncHandler來處理webservice響應結果,handleResponse方法會在服務端處理完結果後被呼叫,即所謂的回撥機制。

使用response.isDone()來判斷並休眠是為了防止main函式過快退出。實際上可以替換成你想做的其他事情。

當然,如果你需要根據webservice返回結果來進行你的下一步邏輯,也可以直接呼叫response.get(),這個方法會阻塞到呼叫結果成功返回。(實際上這樣跟呼叫同步方法沒什麼區別了)

package com.hello.client;

import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

public class TestAsyncHandler implements AsyncHandler<String> {

    private String reply;

    public void handleResponse(Response<String> response) {
    try {
        System.out.println("handleResponse called");
        reply = response.get();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    }

    public String getResponse() {
    return reply;
    }

}

相關推薦

CXF非同步WebService釋出呼叫

最近工作需要接觸CXF非同步webservice的釋出和呼叫,在網上Google並搗鼓了好一陣子,總算成功了。畢竟這方面的資料比較少,自己總結一下寫下這篇博文。本文將描述如何利用CXF來發布和呼叫非同步的webservice,通過一個示例,帶大家一步一步開發基於

WebServiceCXF整合Spring實現介面釋出呼叫過程

CXF整合Spring實現介面釋出 釋出過程如下: 1、引入jar包(基於maven管理) <dependency> <groupId>org.apache.cxf</groupId> <artifactId>

webService總結(一)——使用CXF釋出呼叫webService(不使用Spring)

 CXF和Axis2是兩個比較流行的webService框架,接下來我會寫幾篇部落格簡單介紹如何使用這兩種框架。首先,先簡單介紹一下CXF的使用。 CXF釋出webService有多種方法,這裡我介

CXF開發webservice需要的最少jar包,CXF釋出呼叫客戶端程式碼

簡單介紹一下cxf開發客戶端和服務端的程式碼塊 釋出服務端程式碼: Java程式碼   @WebService publicinterface ApprovalService {       /**       * 3.1.10.  審批結果回撥介面       * @param status

使用Axis2實現WebService釋出呼叫

一、Axis2簡介: Axis2是一套嶄新的WebService引擎,該版本是對Axis1.x重新設計的產物。Axis2不僅支援SOAP1.1和SOAP1.2,還集成了非常流行的REST WebService,同時還支援Spring、JSON等技術。在本文中主要介紹瞭如何使

springboot2.0+dubbo整合分散式服務釋出呼叫

       最近專案上要對以前的老專案做分散式的整改,因此我專門花了點時間研究下當前比較熱門的dubbo和springboot結合使用,以前使用過dubbo,但是沒有與springboot結合過,在網上查了點資料,感覺要麼是springboot版本過低,要麼是dubb

dubbo釋出呼叫服務

1.釋出服務    <!-- 宣告需要暴露的服務介面 -->     <dubbo:protocol  name="dubbo" port="9092"/>     <dubbo:service interface="IConfigReadSe

SpringBoot整合cxf釋出WebService服務客戶端呼叫WebService服務

最近在做公司專案的一個功能需要寫WebSerice介面,為了系統得學習WebService,決定寫一個測試介面的例子。 測試專案中使用的是SpringBoot(spring整合cxf需新增cxf-rt-frontend-jaxws,cxf-rt-transpo

SpringBoot | CXF釋出WebService服務客戶端呼叫WebService服務

一、引入maven依賴 <!-- cxf支援 --> <dependency> <groupId>org.apache.cxf</groupId> <art

webservice服務端釋出客戶端呼叫

1.服務端和客戶端增加Maven依賴包,如下 <!-- cxf方式webservice服務 --> <dependency>             <group

IOS 呼叫WebService 同步非同步

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

webservice服務端釋出呼叫 JAX-WS cxf axis2

之前專案中需要用到webservice的釋出最後做出了幾個例子如下: 1 基礎 JAX-WS例項 介面釋出: package com.test; import javax.jws.WebMethod; import javax.jws.WebSer

Maven+SpringMVC+CXF整合實現webservice服務的釋出呼叫

今天有時間把之前遺留的內容給寫一下,一直想把webservice服務的釋出整合說一下,但是總是忘記了,最近有做了一些關於這一塊的東西,就總結下,來記錄一下。 簡述: WebService開源框架的選擇, 目前主流的Web Service框架主要有3種: Axis 2, CX

webservice(三) 使用JDK的EndPointcxf框架分別釋出webservice服務

在JDK1.6中JAX-WS規範定義瞭如何釋出一個webService服務。     JAX-WS是指Java Api for XML – WebService. 與web服務相關的是EndPoint類,此類為端點服務類,它提供一個publish方法用於將一個已經添加了@W

CXF實現WebService對物件XML檔案的釋出

搭建工程前文以及介紹 1..........................建立POJO類User.java package ObjectInterface; public class User { private String username; private S

解決cxf+spring釋出webservice缺少標籤的問題

最近學習cxf+spring釋出webservice服務,但是遇到服務釋出成功,檢視其wsdl檔案的時候卻缺少<wsdl:import>和<wsdl:message>標籤,檢視

ajax呼叫cxf webservice介面跨域

1.配置webservice (可以參考部落格上cxf  webservice的配置http://blog.csdn.net/zhshchilss/article/details/43763271) 按照上述配置,就可以使用java客戶端呼叫介面了 ajax的呼叫 1.額

WebService概述CXF入門小程序

定義 clas zhang 目的 配置 service組件 ott code 方式 一. 什麽是WedService? WebService不是框架, 甚至不是一種技術, 而是一種跨平臺,跨語言的規範, WebService的出現是為了解決這種需求場景: 不同平臺,

使用cxf+javax開發WebService介面及呼叫

1、jar包:cxf-2.5.3.jar   neethi-3.0.2.jar    wsdl4j-1.6.2.jar    xmlschema-core-2.0.2.jar 2、配置檔案:<---cxf.xml---> <

C# 建立、部署呼叫WebService的簡單示例

webservice 可以用於分散式應用程式之間的互動,和不同程式之間的互動。 概念性的東西就不說太多,下面開始建立一個簡單的webservice的例子。這裡我用的是Visual Studio 2015開發工具。 首先建立一個空的Web應用程式。 然後滑鼠右