使用 Apache cxf 實現 WebService 客戶端

ws-client-demo

客戶端調用遠程服務html

http://localhost:8280/services/HelloWorld?wsdljava

spring + cfx 配置

maven

添加依賴包git

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-frontend-jaxws</artifactId>
  <version>3.2.3</version>
</dependency>
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-transports-http</artifactId>
  <version>3.2.3</version>
</dependency>

wsdl2java

把 HelloWorld.wsdl 下載到 resources 當中github

使用 maven 插件 cxf-codegen-plugin 生成代碼web

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>3.2.2</version>
    <executions>
      <execution>
        <id>generate-sources</id>
        <phase>generate-sources</phase>
        <configuration>
          <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
          <wsdlOptions>
            <wsdlOption>
              <wsdl>${basedir}/src/main/resources/HelloWorld.wsdl</wsdl>
            </wsdlOption>
          </wsdlOptions>
        </configuration>
        <goals>
          <goal>wsdl2java</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

maven compile 任務完成以後在target\generated\cxf\com\example\demo\ws 下會有不少文件spring

CurrentDate.java
    CurrentDateResponse.java
    HelloWorld.java
    HelloWorldImplService.java
    ObjectFactory.java
    package-info.java
    SayHi.java
    SayHiResponse.java

調用 WebService

使用 spring

把 HelloWorld.java 複製到 srcmainjavacomexampledemows 目錄下apache

同時 HelloWorld.java 裏面 @XmlSeeAlso({ObjectFactory.class})這行代碼刪掉app

<?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:client id="helloClient"
                  serviceClass="com.example.demo.ws.service.HelloWorld"
                  address="http://localhost:8280/services/HelloWorld" />
</beans>
package com.example.demo;

import com.example.demo.ws.service.HelloWorld;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.xml.datatype.XMLGregorianCalendar;

public class Main {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloWorld client = (HelloWorld) context.getBean("helloClient");

        String resp1 = client.sayHi("小明");
        System.out.println(resp1);
        XMLGregorianCalendar resp2 = client.currentDate();
        System.out.println(resp2.toString());
    }
}

不使用 spring

package com.example.demo;

import com.example.demo.ws.service.HelloWorld;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URL;

public class WithoutSpring {
    public static void main(String[] args) throws MalformedURLException {
        URL wsdlURL = new URL("http://localhost:8280/services/HelloWorld?wsdl");
        QName SERVICE_NAME = new QName("http://service.ws.demo.example.com/", "HelloWorldImplService");
        Service service = Service.create(wsdlURL, SERVICE_NAME);
        HelloWorld client = service.getPort(HelloWorld.class);
        String result = client.sayHi("小紅");
        System.out.println(result);
    }
}

能夠直接運行的demofrontend

GitHub https://github.com/openmartin...maven

其餘配置

demo 中是比較簡單的狀況,可是實際的狀況會更復雜,下面介紹一下經常使用的配置

SSL Certificate and Proxy

參考 https://cxf.apache.org/docs/c...

在 applicationContext.xml 能夠爲web service client 配置proxy 和 ssl cert,徹底不用寫代碼。

ssl 證書有兩種形式 pkcs十二、jks, 指定路徑有三種形式 url、file、resource

<?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:sec="http://cxf.apache.org/configuration/security"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       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/configuration/security
       http://cxf.apache.org/schemas/configuration/security.xsd
       http://cxf.apache.org/transports/http/configuration
       http://cxf.apache.org/schemas/configuration/http-conf.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd">

    <http:conduit name="{http://service.ws.demo.example.com/}HelloWorldImplService.http-conduit">

        <http:tlsClientParameters>
            <sec:keyManagers keyPassword="PASSWORD">
                <sec:keyStore type="pkcs12" password="PASSWORD"
                              resource="classpath:DLWSCert.p12"/>
            </sec:keyManagers>
            <sec:trustManagers>
            <sec:keyStore type="JKS" password="PASSWORD"
                      file="my/file/dir/Truststore.jks"/>
            </sec:trustManagers>
            <sec:cipherSuitesFilter>
                <!-- these filters ensure that a ciphersuite with
                     export-suitable or null encryption is used,
                     but exclude anonymous Diffie-Hellman key change as
                     this is vulnerable to man-in-the-middle attacks -->
                <sec:include>.*_EXPORT_.*</sec:include>
                <sec:include>.*_EXPORT1024_.*</sec:include>
                <sec:include>.*_WITH_DES_.*</sec:include>
                <sec:include>.*_WITH_AES_.*</sec:include>
                <sec:include>.*_WITH_NULL_.*</sec:include>
                <sec:exclude>.*_DH_anon_.*</sec:exclude>
            </sec:cipherSuitesFilter>
        </http:tlsClientParameters>
        <http:client AutoRedirect="true" Connection="Keep-Alive" ProxyServer="192.168.1.100" ProxyServerPort="8080"/>

    </http:conduit>
    
    <jaxws:client id="helloClient" serviceClass="com.example.demo.ws.service.HelloWorld"
    address="https://localhost:8280/services/HelloWorld"/>

</beans>

cxf-codegen-plugin

cxf 的 maven 插件能夠指定參數來解決一下常見的問題(<extraargs>下的<extraarg>能夠選擇所需的wsdl2java命令參數使用)

參考 http://cxf.apache.org/docs/ws...

  • 添加-autoNameResolution 解決wsdl中命名衝突
  • 添加-p packagename 指定自動生成的包名
<plugin>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-codegen-plugin</artifactId>
        <version>3.2.2</version>
        <executions>
          <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
              <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
              <wsdlOptions>
                <wsdlOption>
                  <wsdl>${basedir}/src/main/resources/HelloWorld.wsdl</wsdl>
                  <extraargs>
                    <extraarg>-autoNameResolution</extraarg>
                    <extraarg>-verbose</extraarg>
                    <extraarg>-p</extraarg>
                    <extraarg>com.example.demo.ws</extraarg>
                  </extraargs>
                </wsdlOption>
              </wsdlOptions>
            </configuration>
            <goals>
              <goal>wsdl2java</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
相關文章
相關標籤/搜索