1. 程式人生 > 實用技巧 >02 Apache CXF框架介紹

02 Apache CXF框架介紹

一、關於Apache CXF

Apache CXF = Celtix + XFire,Apache CXF的前身叫Apache Celtixfire,現在正式更名為Apache CXF了,以下簡稱CXF。CXF繼承了Celtix和XFire兩大開源專案的精華,提供了對JAX-WS全面的支援,並且提供了多種Binding、DataBingding、Transport以及各種Format的支援,並且可以根據實際專案的需要,採用程式碼優先(Code First)或者WSDL優先(WSDL First)來輕鬆地實現Web Service的釋出和使用。目前它仍只是Apache的一個孵化專案。

CXF是一個開源的Service框架,CXF幫助您利用Frontend程式設計Api來構建和開發Service,像JAX-WS。這些Web Service可以支援多種協議,比如:SOAP、XML/HTTP、RESTfulHTTP或者CORBA,並且可以在多種傳輸協議上執行,比如:HTTP、JMS或者JBl,CXF大大簡化了Services的建立,同時它集成了XFire傳統,一樣可以無縫和Spring整合。

二、功能特性

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

1、支援Web Service標準:CXF支援多種Web Service標準,包含了SOAP、BasicProfile、WS-Addressing、WS-Policy、WS-ReliableMessaging和WS-Security

2、Frontends:CXF支援多種"Frontend"程式設計模型,CXF實現了JAX-WS API,它也包含一個"Simple Frontend"允許客戶端和EndPoint的建立,而不需要Annotion註解。CXF即支援WSDL優先開發,也支援從Java程式碼優先開發模式。

3、容易使用:CXF設計得更加直觀與容易使用。在大量簡單的API用來快速的程式碼有限的Services,各種Maven的外掛也使整合更加容易,支援JAX-WS API,支援Spring2.0更加簡單化的XML配置方式等等。

4、支援二進位制和遺留協議:CXF的設計是一種可插拔的框架,即可以支援XML,也支援HTTP

三、Apache CXF實現WebService(JAX-WS)

3.1 服務端

1、建立專案

2、新增cxf依賴

<dependencies>
    <!--    要進行jaxws服務開發-->
    <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>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
    </dependency>
</dependencies>
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

3、寫服務介面

package com.mars.service;

import javax.jws.WebService;

/**
 * 對外發布服務介面
 *
 * @author: Yizq
 * @date: 2020/12/5 16:32
 */
@WebService
public interface HelloService {

    /**
     *
     * @description: 對外發布服務的介面名稱
     * @param name
     * @return: {@link String}
     * @author: Yizq
     * @date: 2020/12/5 16:32
     */
    String sayHello(String name);

}

4、寫服務介面實現類

package com.mars.service.impl;

import com.mars.service.HelloService;

/**
 * 對外發布服務的介面實現類
 *
 * @author: Yizq
 * @date: 2020/12/5 16:34
 */
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return name+",Welcome to WebService";
    }
}

5、釋出服務

package com.mars;

import com.mars.service.impl.HelloServiceImpl;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/**
 * 釋出服務
 *
 * @author: Yizq
 * @date: 2020/12/5 16:35
 */
public class Server {
    public static void main(String[] args) {
        // 釋出服務的工廠
        JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
        // 設定服務地址
        factoryBean.setAddress("http://localhost:8000/ws/hello");
        // 設定服務類
        factoryBean.setServiceBean(new HelloServiceImpl());
        // 釋出服務
        factoryBean.create();
        System.out.println("釋出服務成功,埠8000");
    }
}

執行main方法,在控制檯中會出現輸出文字,則表示釋出成功

log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
釋出服務成功,埠8000

6、訪問wsdl說明書

3.2 客戶端

1、建立專案。省略

2、新增依賴。可以和服務端依賴保持一致

3、寫服務介面

package com.mars.service;

import javax.jws.WebService;

/**
 * 對外發布服務介面
 *
 * @author: Yizq
 * @date: 2020/12/5 16:32
 */
@WebService
public interface HelloService {

    /**
     *
     * @description: 對外發布服務的介面名稱
     * @param name
     * @return: {@link String}
     * @author: Yizq
     * @date: 2020/12/5 16:32
     */
    String sayHello(String name);

}

4、遠端訪問服務端

package com.mars;

import com.mars.service.HelloService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**
 * TODO
 *
 * @author: Yizq
 * @date: 2020/12/5 16:45
 */
public class Client {
    public static void main(String[] args) {

        // 建立cxf代理工廠
        JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
        // 設定遠端訪問服務端地址
        factoryBean.setAddress("http://localhost:8000/ws/hello");
        // 設定介面型別
        factoryBean.setServiceClass(HelloService.class);
        // 對介面生成代理物件
        HelloService helloService = factoryBean.create(HelloService.class);
        // 遠端訪問服務端方法
        String content = helloService.sayHello("Mars");
        System.out.println(content);
    }
}

進行執行測試,控制檯中輸出

log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Mars,Welcome to WebService

3.3 新增日誌攔截器

在服務端中新增log4j.properties檔案

log4j.rootCategory=info,CONSOLE,LOGFILE

log4j.logger.org.apache.axis.enterprise=FATAL,CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout

並修改服務端釋出的程式碼

package com.mars;

import com.mars.service.impl.HelloServiceImpl;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/**
 * 釋出服務
 *
 * @author: Yizq
 * @date: 2020/12/5 16:35
 */
public class Server {
    public static void main(String[] args) {
        // 釋出服務的工廠
        JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
        // 設定服務地址
        factoryBean.setAddress("http://localhost:8000/ws/hello");
        // 設定服務類
        factoryBean.setServiceBean(new HelloServiceImpl());
        // 新增日誌輸入、輸出攔截器,觀察soap請求、響應的內容
        factoryBean.getInInterceptors().add(new LoggingInInterceptor());
        factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
        // 釋出服務
        factoryBean.create();
        System.out.println("釋出服務成功,埠8000");
    }
}

在客戶端呼叫過程中,控制檯會輸出如下內容

2020-12-05 16:56:12,443 0      [           main] INFO  y.ReflectionServiceFactoryBean  - Creating Service {http://impl.service.mars.com/}HelloServiceImplService from class com.mars.service.HelloService
2020-12-05 16:56:12,726 283    [           main] INFO  apache.cxf.endpoint.ServerImpl  - Setting the server's publish address to be http://localhost:8000/ws/hello
2020-12-05 16:56:12,742 299    [           main] INFO  rg.eclipse.jetty.server.Server  - jetty-8.1.15.v20140411
2020-12-05 16:56:12,881 438    [           main] INFO  jetty.server.AbstractConnector  - Started SelectChannelConnector@localhost:8000
釋出服務成功,埠8000
2020-12-05 16:56:21,512 9069   [tp1565740893-17] INFO  loServiceImplPort.HelloService  - Inbound Message
----------------------------
ID: 1
Address: http://localhost:8000/ws/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[192], content-type=[text/xml; charset=UTF-8], Host=[localhost:8000], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 3.0.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://service.mars.com/"><arg0>Mars</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
2020-12-05 16:56:21,599 9156   [tp1565740893-17] INFO  loServiceImplPort.HelloService  - Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://service.mars.com/"><return>Mars,Welcome to WebService</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------

以上幾個引數需要解釋的是:

  • ID:表示當前服務被呼叫的次數,以1開始,依次+1
  • Address:伺服器釋出的地址
  • Encoding:編碼規則
  • Http-Method:請求的方式
  • Content-Type:上下文的內容格式
  • Headers:服務請求的內容
  • Response-Code:請求的結果,200為成功
  • Plyload:響應的內容