Apache CXF 入門詳解


以前沒有接觸過CXF,項目需要學習,從網上各種找資料加上項目的實踐,不斷壘字。

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

 

功能特性

CXF 包含了大量的功能特性,但是主要集中在以下幾個方面:

  1. 支持 Web Services 標准:CXF 支持多種 Web Services 標准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。
  2. Frontends:CXF 支持多種“Frontend”編程模型,CXF 實現了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),它也包含一個“simple frontend”允許客戶端和 EndPoint 的創建,而不需要 Annotation 注解。CXF 既支持 WSDL 優先開發,也支持從 Java 的代碼優先開發模式。
  3. 容易使用: CXF 設計得更加直觀與容易使用。有大量簡單的 API 用來快速地構建代碼優先的 Services,各種 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加簡化的 XML 配置方式,等等。
  4. 支持二進制和遺留協議:CXF 的設計是一種可插撥的架構,既可以支持 XML ,也可以支持非 XML 的類型綁定,比如:JSON 和 CORBA。

支持多種標准

  • 支持 JAX-WS、 JAX-WSA、JSR-181 和 SAAJ;
  • 支持 SOAP 1.1、1.2、WS-I BasicProfile、WS-Security、WS-Addressing、WS-RM 和 WS-Policy;
  • 支持 WSDL 1.1 、2.0;
  • 支持 MTOM;

多種傳輸方式、Bindings、Data Bindings 和 Format

  • Bindings:SOAP、REST/HTTP;
  • Data Bndings:目前支持 JAXB 2.0、Aegis 兩種,默認是 JAXB 2.0。XMLBeans、Castor 和 JiBX 數據綁定方式將在 CXF 2.1 版本中得到支持;
  • 格式(Format):XML、JSON;
  • 傳輸方式:HTTP、Servlet、JMS 和 Jabber;
  • 可擴展的 API 允許為 CXF 增加其它的 Bindings,以能夠支持其它的消息格式,比如:CSV 和固定記錄長度。

靈活部署

  • 輕量級容器:可在 Tomcat 或基於 Spring 的容器中部署 Services;
  • 集成 JBI:可以在如 ServiceMix, OpenESB or Petals 等等的 JBI 容器中將它部署為一個服務引擎;
  • 集成 SCA:可以部署在如 Tuscany 之類的 SCA 容器中;
  • 集成 J2EE:可以在 J2EE 應用服務器中部署 Services,比如:Geronimo、JOnAS、JBoss、WebSphere Application Server 和 WebLogic Application Server,以及 Jetty 和 Tomcat;
  • 獨立的 Java 客戶端/服務器。

支持多種編程語言

  • 全面支持 JAX-WS 2.0 客戶端/服務器編程模型;
  • 支持 JAX-WS 2.0 synchronous、asynchronous 和 one-way API's;
  • 支持 JAX-WS 2.0 Dynamic Invocation Interface (DII) API;
  • 支持 wrapped and non-wrapped 風格;
  • 支持 XML messaging API;
  • 支持 JavaScript 和 ECMAScript 4 XML (E4X) ,客戶端與服務端均支持;
  • 通過 Yoko 支持 CORBA;
  • 通過 Tuscany 支持 SCA;
  • 通過 ServiceMix 支持 JBI ;

代碼生成

  • Java to WSDL;
  • WSDL to Java;
  • XSD to WSDL;
  • WSDL to XML;
  • WSDL to SOAP;
  • WSDL to Service;

 代碼簡單分析

通過查看 Server.java 及 Client.java 的代碼,來了解一下 CXF 的運作過程。Server.java 中主要的代碼片斷如下,它利用 ServerFactoryBean 來進行 Web Services 的發布,實例化一個實現類 HelloWorldImpl,設置將要進行發布的地址 address,最后通過 ServerFactoryBean 的 create() 方法就成功地發布了 Web Services,如此簡單而已,只有六行代碼:

1 HelloWorldImpl helloworldImpl = new HelloWorldImpl();
2  ServerFactoryBean svrFactory = new ServerFactoryBean();
3  svrFactory.setServiceClass(HelloWorld.class);
4  svrFactory.setAddress("http://localhost:9000/Hello");
5  svrFactory.setServiceBean(helloworldImpl);
6  svrFactory.create();

Client.java 中的主要代碼片斷如下,通過 ClientProxyFactoryBean 代理工廠類來創建一個服務,綁定到 endPointAddress 地址,就可以 create 並得到服務,並進行服務消費了:

1  ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
2  factory.setServiceClass(HelloWorld.class);
3  factory.setAddress("http://localhost:9000/Hello");
4  HelloWorld client = (HelloWorld)factory.create();
5  System.out.println("Invoke sayHi()....");
6  System.out.println(client.sayHi("user"));

CXF 應用開發

下面就將開始我們的 CXF Web Services 的開發之旅!首先,要有一個基於 Eclipse 的開發環境;然后,我們將利用這個開發環境開發一個簡單的“調查投票”示例,同時我們將解釋一些 CXF 在開發中進行配置的基本方法。

接口類創建

在項目的 src 目錄中新建一個 ws.cxf 包,並在里面創建接口類 ISurveyService.java,為了簡單示示例起見,我們僅創建一個方法 public String vote(String username,int point); 這里要注意的是我們在接口上用 @WebService 注解標明這是一個即將暴露為 Web Service 的接口,並將里面的方法都暴露出去。完整的接口代碼清單如下:

package ws.cxf;

import javax.jws.WebService;

@WebService
public interface ISurveyService
{
    /**
     * @param username 名字
     * @param point 分數
     * @return
     */
    public String vote(String username,int point);
}

接下來,我們根據接口的定義,來實現它。

具體類實現

針對接口的定義,我們創建一個相應的實現類,並將其定義在 sw.cxf.impl 包中,完整的代碼清單如下:

package ws.cxf.impl;

import javax.jws.WebService;
import ws.cxf.ISurveyService;

@WebService
public class SurveyService implements ISurveyService
{
    private String excludeName = "Michael";
    private int leastPonit = 5;

    public String vote(String username,int point)
    {
        String result = "";
        if(excludeName.equals(username))
        {
            result = " 您不能重復進行投票!";
        }
        else
        {
            result = " 謝謝您的投票!";
            if(point < leastPonit)
            {
                result += " 您的投票分數太低!";
            }
            else
            {
                result += " 您的投票分數通過審核!";
            }
        }
        return result;
    }

    // For IoC
    public String getExcludeName()
    {
        return excludeName;
    }

    public void setExcludeName(String excludeName)
    {
        this.excludeName = excludeName;
    }

    public int getLeastPonit()
    {
        return leastPonit;
    }

    public void setLeastPonit(int leastPonit)
    {
        this.leastPonit = leastPonit;
    }
}

接口定義與具體的實現就這樣簡單完成了,接下來就是相關的配置工作了,首先進行 Spring 的 Bean 配置。

Spring 配置

在 src 目錄中創建 beanRefServer.xml 文件,用來定義 Spring 的 Bean 的配置,CXF 支持 Spring 2.0 Schema 標簽配置方式,並且提供快捷暴露 Web Services 的標簽。

首先,我們需要引入 Spring 與 CXF 的命名空間(namespace),如下:

<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-2.0.xsd
        http://cxf.apache.org/jaxws 
        http://cxf.apache.org/schemas/jaxws.xsd">

這樣,我們可以使用 Spring 與 CXF 的標簽配置了。接着,我們需要引入我們所需要的 CXF 的 Bean 定義文件,如下:

<!-- Import Apache CXF Bean Definition -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

接着定義我們具體實現的 Bean ,這個 Bean 的定義與 Spring 普通的 Bean 定義是一樣的:

1 <!-- SurveyService -->
2     <bean id="surveyService" class="ws.cxf.impl.SurveyService">
3         <property name="excludeName" value="Michael"/>
4         <property name="leastPonit" value="10"/>
5     </bean>

最后,將定義的 Bean 暴露出去成為 Web Service 服務,通過 CXF 提供的 Schema 標簽配置 <jaxws:server> ,這樣定義的配置顯得更加簡潔與方便,定義如下:

 <!-- Expose SurveyWebService -->
    <jaxws:server id="surveyWebService" 
        serviceClass="ws.cxf.ISurveyService" 
        address="/SurveyWebService">
        <jaxws:serviceBean>
            <ref bean="surveyService"/> <!-- 要暴露的 bean 的引用 -->
            </jaxws:serviceBean>
    </jaxws:server>

在配置中,serviceClass 的值是我們的接口類的名稱,address 為將要暴露出去的 Web Service 訪問地址。比如:/SurveyWebService,那么客戶端消費 Web Service 的地址就會成為 http://host:port/WebAPPName/SurveyWebService ,與之相應的 WSDL 地址則為: http://host:port/WebAPPName/SurveyWebService?wsdl 。

 

Web 應用配置

由於我們的示例是需要通過 Servlet 容器進行服務暴露,因此需要配置相對應的 web.xml 文件,首先是增加 Spring 的配置文件加載 Listener,如下:

 1  <!-- Spring Config Location -->
 2     <context-param>
 3         <param-name>contextConfigLocation</param-name>
 4         <param-value>/WEB-INF/classes/beanRefServer.xml</param-value>
 5     </context-param>
 6     <!-- Spring ContextLoaderListener -->
 7     <listener>
 8         <listener-class>
 9             org.springframework.web.context.ContextLoaderListener
10         </listener-class>
11     </listener>

接下來配置 CXF Servlet 的定義,以及它的映射,如下:

<!-- Apache CXFServlet -->
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <display-name>CXF Servlet</display-name>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- CXFServlet Mapping -->
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

我們將之映射為 /* 。這樣,服務端的代碼與配置就全部完成了,接下來就是將應用程序部署到 Web 容器中去,並驗證服務是否正常發布。

 

服務器端寫完接下來就可以利用客戶端進行消費了:

消費服務

回到 Eclipse 開發平台,開始編寫消費服務相關的代碼,首先通過 Spring 與 CXF 的配置來定義 Web Service 的客戶端 Bean,在 src 目錄下創建 beanRefClient.xml 配置文件,同樣,我們也需要引入 Spring 與 CXF 命名空間的聲明,並引入 CXF 的 Bean 的定義文件,最后通過與服務端配置相對的 CXF 標簽 <jaxws:client> 來定義客戶端訪問服務的聲明,完整的定義內容如下:

<?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-2.0.xsd
        http://cxf.apache.org/jaxws 
        http://cxf.apache.org/schemas/jaxws.xsd">
    <!-- Import Apache CXF Bean Definition -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

    <!-- SurveyWebService Client -->
    <jaxws:client id="surveyServiceClient" 
        serviceClass="ws.cxf.ISurveyService" 
        address="http://localhost:8080/CXF_Spring_Survey/SurveyWebService"/>
</beans>

定義說明:id 為 Spring 定義的 id,用來在程序里進行獲取它的標識,serviceClass 仍是為服務端定義的接口類,address 為完整的 Web Service 地址,這個與服務端的定義不一樣。

定義完配置文件,接下來我們編寫訪問的具體代碼,在 test 目錄下創建 ws.cxf.client 包,然后創建 SurveyServiceClient.java,完整的代碼如下:

 1 package ws.cxf.client;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 import ws.cxf.ISurveyService;
 6 
 7 public class SurveyServiceClient
 8 {
 9     public static void main(String[] args)
10     {
11         // 加載客戶端的配置定義
12         ApplicationContext context = new 
13                 ClassPathXmlApplicationContext("beanRefClient.xml");
14         // 獲取定義的 Web Service Bean
15         ISurveyService surveyService = 
16             (ISurveyService)context.getBean("surveyServiceClient");
17         // 1、定義調查投票的變量與內容,用來發送給服務
18         String username = "Test";
19         int point = 88;
20         // 調用方法進行服務消費
21         String result = surveyService.vote(username,point);
22         System.out.println("Result:" + result);
23         // 2、傳遞不一樣的調查投票內容
24         username = "Michael";
25         point = 100;
26         // 再次調用方法進行服務消費,得到不一樣的結果
27         result = surveyService.vote(username,point);
28         System.out.println("Result:" + result);
29         // 3、第三次傳遞與調用
30         username = "Jordan";
31         point = 9;
32         result = surveyService.vote(username,point);
33         System.out.println("Result:" + result);
34     }
35 }

 

 

references:

https://www.ibm.com/developerworks/cn/education/java/j-cxf/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM