杰瑞科技汇

Java如何访问WebService?

  1. JAX-WS (Java API for XML Web Services):Java 官方标准,用于创建和消费 SOAP WebService,最简单,适合调用已经存在的、基于 SOAP 的服务。
  2. Apache CXF:一个功能强大的开源框架,既支持 SOAP 也支持 RESTful (JAX-RS),它比 JAX-WS 更灵活,功能更丰富,是企业级开发中的常用选择。
  3. Spring Boot + RestTemplate / WebClient:现代 Java 开发的主流方式,如果你的 WebService 是 RESTful 风格(返回 JSON/XML 数据),这是最推荐的方式,因为它与 Spring 生态系统无缝集成。

场景设定

为了方便演示,我们假设有一个简单的 WebService,它提供以下功能:

Java如何访问WebService?-图1
(图片来源网络,侵删)
  • 地址: http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl
  • 功能: 查询 QQ 号码是否在线。
  • 操作: qqCheckOnline
  • 参数: qqCode (字符串)
  • 返回值: 一个字符串,如 "Y" (在线) 或 "N" (离线)

这个服务是公开的,非常适合用来做示例。


使用 JAX-WS (最简单、最直接)

JAX-WS 是 Java 标准库的一部分(从 JDK 1.6 开始),所以你不需要额外添加依赖(除了可能需要一些运行时库)。

步骤 1: 获取 WSDL 文件并生成客户端代码

你需要使用 JDK 自带的 wsimport 工具,根据 WSDL 文件生成一系列 Java 类(客户端存根),这些类封装了与服务器通信的细节。

打开你的命令行(CMD 或 PowerShell),执行以下命令:

Java如何访问WebService?-图2
(图片来源网络,侵删)
# -keep: 生成源代码文件
# -d: 指定编译后的 .class 文件存放目录
# -p: 指定生成的包名
wsimport -keep -d D:\temp -p com.example.webservice.client http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl

执行成功后,你会在 D:\temp\com\example\webservice\client 目录下看到一堆 .java.class 文件,其中最重要的是 QQOnlineWebServiceQQOnlineWebServiceService

步骤 2: 在项目中使用生成的客户端代码

  1. 将生成的 .class 文件(或整个 com.example.webservice.client 包)添加到你的 Java 项目的 classpath 中。
  2. 编写调用代码。
import com.example.webservice.client.QQOnlineWebService;
import com.example.webservice.client.QQOnlineWebServiceService;
public class JaxWsClientExample {
    public static void main(String[] args) {
        // 1. 创建服务视图 (Service)
        // QQOnlineWebServiceService 是 wsimport 生成的工厂类
        QQOnlineWebServiceService service = new QQOnlineWebServiceService();
        // 2. 获取服务端点 (Port)
        // getQQOnlineWebServicePort() 方法返回一个代理对象,它实现了服务接口
        QQOnlineWebService port = service.getQQOnlineWebServicePort();
        // 3. 调用 WebService 方法
        String qqNumber = "12345678"; // 你想查询的QQ号
        String result = port.qqCheckOnline(qqNumber);
        // 4. 处理结果
        System.out.println("QQ号码 " + qqNumber + " 的在线状态是: " + result);
    }
}

优点:

  • 简单,是 Java 标准,无需额外依赖。
  • IDE(如 IntelliJ IDEA、Eclipse)通常可以自动完成 wsimport 的过程,更方便。

缺点:

  • 主要用于 SOAP 协议,不够灵活。
  • 生成的代码有时会很冗长,难以调试。

使用 Apache CXF (功能强大、灵活)

CXF 是一个更全面的框架,它支持 SOAP 和 REST,使用 CXF 调用 JAX-WS 服务同样非常简单,并且提供了更多高级特性。

步骤 1: 添加 Maven 依赖

在你的 pom.xml 文件中添加 CXF 的核心依赖:

<dependencies>
    <!-- CXF 核心依赖 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.4.5</version> <!-- 使用最新稳定版 -->
    </dependency>
    <!-- CXF 的运行时依赖,包含 Jetty 服务器等 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.4.5</version>
    </dependency>
</dependencies>

注意: CXF 也内置了 wsdl2java 工具,功能和 JDK 的 wsimport 类似,但更强大,你可以通过 Maven 插件或命令行使用它,但为了保持与 JAX-WS 示例的一致性,我们这里复用 JAX-WS 生成的客户端代码,只是用 CXF 的方式去调用它。

步骤 2: 使用 CXF 的 JAX-WS 前端调用服务

CXF 实现了 JAX-WS 规范,所以你可以用和标准 JAX-WS 几乎一样的方式调用,CXF 的优势在于你不需要关心底层实现,并且可以轻松添加拦截器、日志等功能。

import com.example.webservice.client.QQOnlineWebService;
import com.example.webservice.client.QQOnlineWebServiceService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class CxfClientExample {
    public static void main(String[] args) {
        // 1. 创建 JaxWsProxyFactoryBean
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 2. 设置服务接口 (WSDL 中定义的 portType)
        factory.setServiceClass(QQOnlineWebService.class);
        // 3. 设置 WebService 的地址 (WSDL 中的 location)
        factory.setAddress("http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx");
        // 4. 创建客户端代理对象
        QQOnlineWebService service = factory.create(QQOnlineWebService.class);
        // 5. 调用方法
        String qqNumber = "87654321";
        String result = service.qqCheckOnline(qqNumber);
        // 6. 处理结果
        System.out.println("使用 CXF 调用,QQ号码 " + qqNumber + " 的在线状态是: " + result);
    }
}

优点:

  • 功能强大,支持 SOAP 和 REST。
  • 拥有丰富的插件机制(如日志、加密、WS-Security 等)。
  • 社区活跃,文档完善。

缺点:

  • 相比标准 JAX-WS,需要引入额外的框架依赖。

使用 Spring Boot + RestTemplate (现代 RESTful 服务首选)

如果你的 WebService 是 RESTful 风格(通常返回 JSON 或 XML),而不是 SOAP,那么这是最现代、最推荐的方式,我们以一个返回 JSON 的公共 API 为例。

场景设定:

  • 地址: http://api.exchangerate.host/latest?access_key=YOUR_KEY&base=USD&symbols=CNY
  • 功能: 获取美元对人民币的汇率。
  • 返回格式: JSON

步骤 1: 创建 Spring Boot 项目并添加依赖

使用 Spring Initializr 创建项目,并添加 Spring Web 依赖。

步骤 2: 创建一个用于映射 JSON 的 Java 类 (POJO)

我们需要一个类来和返回的 JSON 结构对应。

// RateResponse.java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略 JSON 中存在但 Java 类中没有的属性
public class RateResponse {
    private String success;
    private String base;
    private String date;
    private Rates rates;
    // Getters and Setters
    // ...
}
// Rates.java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Map;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Rates {
    private Map<String, Double> rates;
    // Getter and Setter
    public Map<String, Double> getRates() {
        return rates;
    }
    public void setRates(Map<String, Double> rates) {
        this.rates = rates;
    }
}

步骤 3: 配置 RestTemplate 并调用服务

在 Spring Boot 的主类或配置类中,声明一个 RestTemplate Bean。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class WebserviceApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebserviceApplication.class, args);
    }
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

步骤 4: 创建一个 Service 来调用 WebService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ExchangeRateService {
    @Autowired
    private RestTemplate restTemplate;
    // 假设你有一个 API Key,这里用占位符
    private final String API_KEY = "YOUR_API_KEY"; 
    private final String API_URL = "http://api.exchangerate.host/latest?access_key=" + API_KEY + "&base=USD&symbols=CNY";
    public double getUsdToCnyRate() {
        // 使用 RestTemplate 发送 GET 请求,并将响应体自动映射为 RateResponse 对象
        RateResponse response = restTemplate.getForObject(API_URL, RateResponse.class);
        if (response != null && "true".equals(response.getSuccess())) {
            // 从响应对象中提取汇率
            return response.getRates().getRates().get("CNY");
        } else {
            throw new RuntimeException("Failed to get exchange rate");
        }
    }
}

步骤 5: 在 Controller 中调用 Service

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExchangeRateController {
    @Autowired
    private ExchangeRateService exchangeRateService;
    @GetMapping("/rate")
    public String getRate() {
        double rate = exchangeRateService.getUsdToCnyRate();
        return "当前美元对人民币汇率为: " + rate;
    }
}

启动 Spring Boot 应用,访问 http://localhost:8080/rate 即可看到结果。

优点:

  • 现代标准:与 Spring 生态系统完美集成。
  • 简洁易用:代码非常直观,基于 HTTP 协议,易于理解和调试。
  • 灵活性高:可以轻松处理各种 HTTP 请求/响应,支持 JSON、XML 等多种数据格式。
  • 异步支持WebClient (Spring WebFlux) 提供了强大的非阻塞异步调用能力。

缺点:

  • 仅适用于 RESTful 风格的 WebService,不适用于 SOAP。

总结与如何选择

特性 JAX-WS Apache CXF Spring Boot + RestTemplate
适用协议 SOAP SOAP & REST RESTful (首选)
易用性 简单 (标准) 中等 简单 (声明式)
灵活性
依赖 JDK 内置 需引入 CXF 框架 需引入 Spring Boot
集成度 中等 极高 (与 Spring 生态)
主要用途 调用传统、遗留的 SOAP 服务。 需要处理复杂 SOAP 协议(如 WS-Security)或同时需要 SOAP/REST 的项目。 开发新的 RESTful 服务或调用现代 REST API 的首选。

选择建议:

  1. 如果你的任务是调用一个现有的 SOAP WebService

    • 如果项目简单,不想引入新依赖,使用 JAX-WS
    • 如果项目复杂,需要日志、安全等高级功能,或者你熟悉 CXF,使用 Apache CXF
  2. 如果你的任务是调用一个 RESTful WebService (返回 JSON/XML)

    • 毫不犹豫地选择 Spring Boot + RestTemplate (或 WebClient),这是当前业界的主流和最佳实践。
  3. 如果你需要同时开发客户端和服务器端

    • 对于 SOAP,CXF 是一个非常健壮的选择。
    • 对于 RESTful,Spring Boot 全家桶是绝对的首选。
分享:
扫描分享到社交APP
上一篇
下一篇