杰瑞科技汇

Java webservice客户端调用,如何正确实现?

核心概念

在开始之前,我们先明确几个基本概念:

Java webservice客户端调用,如何正确实现?-图1
(图片来源网络,侵删)
  1. Web Service (WS):一种跨编程语言、跨操作系统、跨网络的远程调用技术,通常基于 SOAP (Simple Object Access Protocol) 协议,使用 XML 格式进行数据交换。
  2. WSDL (Web Services Description Language):一个 XML 文件,用于描述 Web Service 的功能、接口、方法、参数、返回值以及如何访问它,它是客户端调用的“说明书”或“地图”。
  3. SOAP (Simple Object Access Protocol):一种协议,用于在 Web 上交换结构化的和类型化的信息,SOAP 消息是 XML 格式的。

使用 JAX-WS (Java API for XML Web Services) - 最主流、推荐

JAX-WS 是 Java 官方推出的用于创建和调用 Web Service 的 API,它已经内置于 Java 标准库中(从 JDK 5 开始),这是目前 Java 开发中最常用、最标准的方法。

生成客户端代码

JAX-WS 提供了一个命令行工具 wsimport,它会根据 WSDL 文件自动生成一系列 Java 类(客户端存根/Stub),这些类封装了网络通信的细节,让你可以像调用本地方法一样调用远程的 Web Service。

如何使用 wsimport

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

Java webservice客户端调用,如何正确实现?-图2
(图片来源网络,侵删)
# 基本语法
wsimport -keep -p com.example.client -d . http://example.com/service?wsdl
# 参数解释:
# -keep: 生成源代码并保留,方便查看和调试。
# -p <package>: 指定生成类的包名,com.example.client。
# -d <dir>: 指定生成 .class 文件的输出目录,这里用 "." 表示当前目录。
# <wsdl-url>: Web Service 的 WSDL 文件地址。

执行成功后,你会得到一堆 .java.class 文件,其中最重要的通常是一个名为 XXXService 的服务类和一个名为 XXX 的接口(HelloServiceHello)。

调用 Web Service

生成的代码中,XXXService 类有一个 getXXXPort() 方法,它会返回一个实现了 XXX 接口的代理对象,你只需要调用这个代理对象的方法即可。

示例代码:

假设我们根据一个天气预报的 WSDL 生成了 WeatherServiceWeather 接口。

Java webservice客户端调用,如何正确实现?-图3
(图片来源网络,侵删)
import com.example.client.Weather; // 生成的接口
import com.example.client.WeatherService; // 生成的服务类
public class JaxwsClientExample {
    public static void main(String[] args) {
        // 1. 创建服务 Service 实例
        WeatherService service = new WeatherService();
        // 2. 获取服务端点接口,这是一个代理对象
        //    getWeatherPort() 是根据 WSDL 生成的
        Weather port = service.getWeatherPort();
        try {
            // 3. 像调用本地方法一样调用远程方法
            String cityName = "北京";
            String weatherInfo = port.getWeather(cityName); // 假设 getWeather 是 WSDL 中定义的方法
            // 4. 处理返回结果
            System.out.println("查询城市: " + cityName);
            System.out.println("天气信息: " + weatherInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用 Apache CXF - 功能强大、灵活

Apache CXF 是一个开源的 Services 框架,它支持多种 Web Service 标准,包括 SOAP、RESTful HTTP Services、WS-* 等,它比 JAX-WS 更灵活,支持更多高级特性,并且可以轻松集成到 Spring 框架中。

添加依赖

在你的 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-jetty</artifactId>
        <version>3.4.5</version>
    </dependency>
</dependencies>

调用 Web Service

CXF 同样可以使用 wsimport(或其自己的 cxf-wsdl2java)来生成客户端代码,调用方式与 JAX-WS 几乎一样。

更重要的是,CXF 提供了更简洁的 无客户端代码 的调用方式,通过动态代理实现。

示例代码 (动态代理):

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.example.client.Weather; // 假设你已经有这个接口,或者从 WSDL 手动定义
public class CxfClientExample {
    public static void main(String[] args) {
        // 1. 创建 JaxWsProxyFactoryBean 实例
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 2. 设置服务接口
        factory.setServiceClass(Weather.class);
        // 3. 设置 Web Service 的地址
        factory.setAddress("http://localhost:8080/weather?wsdl");
        // 4. 创建客户端代理对象
        Weather weatherService = factory.create(Weather.class);
        // 5. 调用方法
        try {
            String result = weatherService.getWeather("上海");
            System.out.println("上海天气: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点

  • 无需生成代码:直接通过接口和地址创建代理,非常方便。
  • 集成度高:与 Spring 框架无缝集成,可以轻松将 Web Service 声明为 Bean。
  • 功能丰富:支持 WS-Security, WS-Addressing 等企业级特性。

使用 Spring Boot + WebServiceTemplate - 现代化、Spring 生态首选

如果你正在使用 Spring Boot,WebServiceTemplate 是最佳选择,它由 Spring Framework 提供,为调用 Web Service 提供了模板化的操作,类似于 RestTemplate 对于 RESTful API。

添加依赖

在 Spring Boot 项目的 pom.xml 中添加:

<dependencies>
    <!-- Spring WebService -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web-services</artifactId>
    </dependency>
    <!-- CXF 支持可选,但推荐 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.4.5</version>
    </dependency>
</dependencies>

配置和调用

示例代码:

import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapActionCallback;
// 你的请求和响应对象 (JAXB 注解的 POJO)
// import com.example.weatherschema.GetWeatherRequest;
// import com.example.weatherschema.GetWeatherResponse;
@Service
public class WeatherClient {
    private final WebServiceTemplate webServiceTemplate;
    // 通过构造器注入,推荐
    public WeatherClient() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // 设置要生成的包名,这个包名需要和 WSDL 中定义的 targetNamespace 一致
        marshaller.setPackagesToScan("com.example.weatherschema");
        this.webServiceTemplate = new WebServiceTemplate(marshaller);
    }
    public String getWeather(String city) {
        // 1. 创建请求对象
        // GetWeatherRequest request = new GetWeatherRequest();
        // request.setCityName(city);
        // 2. 定义消息的 URI (通常对应 WSDL 中的 portType 和 operation)
        String uri = "http://example.com/weather/GetWeather";
        // 3. 设置 SOAP Action (非常重要!通常在 WSDL 中定义)
        String soapActionUri = "http://example.com/weather/GetWeatherRequest";
        // 4. 发送请求并获取响应
        // GetWeatherResponse response = (GetWeatherResponse) webServiceTemplate
        //     .marshalSendAndReceive(uri, request, new SoapActionCallback(soapActionUri));
        // return response.getWeatherInfo();
        // 为了简化,这里展示一个更通用的调用方式
        // 实际项目中,你需要根据 WSDL
分享:
扫描分享到社交APP
上一篇
下一篇