杰瑞科技汇

java远程调用webservice

什么是 WebService?

在开始之前,简单理解一下 WebService,它是一种跨编程语言、跨操作系统、跨平台的远程调用技术,通过标准的 XML 格式进行数据交换,并使用 SOAP (Simple Object Access Protocol) 协议作为通信规范,最常用的描述 WebService 接口的语言是 WSDL (Web Services Description Language)

java远程调用webservice-图1
(图片来源网络,侵删)

使用 JDK 自带的 javax.xml.ws (JAX-WS API)

这是 Java 标准库提供的方法,无需添加任何第三方依赖,非常适合快速开发和简单的 WebService 调用。

适用场景

  • 调用基于 SOAP 协议的、符合 JAX-WS 规范的 WebService。
  • 不想引入第三方库,追求轻量级。

实现步骤

假设我们要调用一个公开的天气查询 WebService(http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl)。

第1步:获取 WSDL 地址

WSDL 文件是 WebService 的“说明书”,里面定义了所有可用的方法、参数和返回值,通常是一个 .asmx?wsdl 结尾的 URL。

java远程调用webservice-图2
(图片来源网络,侵删)

第2步:生成客户端代码

你需要使用 JDK 自带的 wsimport 工具,根据 WSDL 文件生成一系列 Java 代码(客户端存根)。

  1. 打开命令行(CMD 或 PowerShell)。
  2. 执行以下命令:
    # -keep: 生成源代码后保留 .java 文件
    # -d: 指定编译后的 .class 文件存放目录
    # -p: 指定生成的包名
    wsimport -keep -d D:\temp -p com.example.weather http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

    执行成功后,D:\temp 目录下会生成 com/example/weather 包,里面包含一堆 .class.java 文件,你只需要关注 WeatherWebServiceWeatherWebServiceSoap 这两个核心接口。

第3步:编写 Java 调用代码

java远程调用webservice-图3
(图片来源网络,侵删)

将生成的 Java 文件(或其编译后的 .class 文件)导入到你的项目中,然后编写调用逻辑。

import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import com.example.weather.ArrayOfString;
public class JaxwsClient {
    public static void main(String[] args) {
        // 1. 创建服务视图 (Service)
        // WeatherWebService 是 wsimport 生成的类,用于获取服务端口
        WeatherWebService service = new WeatherWebService();
        // 2. 获取服务端点接口 (Service Endpoint Interface, SEI)
        // WeatherWebServiceSoap 是 wsimport 生成的接口,包含了所有可用的方法
        WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
        // 3. 调用具体的方法
        String cityCode = "北京";
        ArrayOfString result = port.getWeather(cityCode, "");
        // 4. 处理返回结果
        // 返回结果通常是一个 List<String>,包含了天气信息
        System.out.println("查询 " + cityCode + " 的天气信息:");
        for (String info : result.getString()) {
            System.out.println(info);
        }
    }
}

使用 Apache CXF 框架

Apache CXF 是一个功能强大、灵活的开源框架,它不仅支持 SOAP,还支持 RESTful 服务,对于复杂的 WebService 或需要更多自定义的场景,CXF 是更好的选择。

适用场景

  • 需要更高级的、可配置的 SOAP 功能。
  • 项目中已经集成了 CXF 框架。
  • 需要同时支持 SOAP 和 RESTful 调用。

实现步骤

第1步:添加 Maven 依赖

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

<dependencies>
    <!-- CXF 核心依赖 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-core</artifactId>
        <version>3.4.5</version> <!-- 使用较新版本 -->
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.4.5</version>
    </dependency>
</dependencies>

第2步:生成客户端代码 (可选)

CXF 也提供了一个更强大的代码生成工具 cxf-xjc-utilswsdl2java,它比 JDK 自带的 wsimport 功能更全,支持更多数据类型的绑定。

# 下载 cxf-xjc-utils 并解压
# 运行 wsdl2java.bat (Windows) 或 wsdl2java.sh (Linux/Mac)
# 示例命令:
# bin\wsdl2java -p com.example.weather -d D:\temp http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

第3步:编写 Java 调用代码

CXF 的调用方式与 JAX-WS 非常相似,因为 CXF 本身就是 JAX-WS 的一个实现。

import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import com.example.weather.ArrayOfString;
public class CxfClient {
    public static void main(String[] args) {
        // 1. 创建服务视图
        WeatherWebService service = new WeatherWebService();
        // 2. 获取服务端口
        WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
        // 3. 调用方法
        String cityCode = "上海";
        ArrayOfString result = port.getWeather(cityCode, "");
        // 4. 处理结果
        System.out.println("查询 " + cityCode + " 的天气信息:");
        for (String info : result.getString()) {
            System.out.println(info);
        }
    }
}

使用 Spring Boot + CXF (企业级推荐)

在现代 Spring Boot 项目中,集成 CXF 来调用 WebService 是最优雅、最企业级的方式,它将 WebService 客户端的创建交由 Spring 容器管理,便于配置、注入和生命周期管理。

适用场景

  • 基于 Spring Boot 的项目。
  • 需要集成到现有的 Spring 生态系统中。
  • 希望通过配置文件管理 WebService 的地址、超时等信息。

实现步骤

第1步:添加 Maven 依赖

除了 CXF 的依赖,还需要添加 Spring Boot 的 Web starter。

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- CXF Dependencies -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.4.5</version> <!-- 注意版本要与 Spring Boot 兼容 -->
    </dependency>
</dependencies>

第2步:生成客户端代码

同方法二,使用 wsdl2java 生成客户端代码。

第3步:创建配置类

创建一个配置类,将生成的 WebService 客户端类注册为 Spring Bean。

import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class CxfClientConfig {
    // @Bean 定义一个 Spring Bean
    // @Primary 表示当有多个相同类型的 Bean 时,优先使用这个
    @Bean
    @Primary
    public WeatherWebServiceSoap weatherWebServiceSoap() {
        // 1. 创建 JaxWsProxyFactoryBean
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 2. 设置服务接口
        factory.setServiceClass(WeatherWebServiceSoap.class);
        // 3. 设置 WebService 的地址 (注意:这里不是 WSDL 地址)
        factory.setAddress("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
        // 4. 可以设置超时时间等属性
        // factory.getOutInterceptors().add(new LoggingInInterceptor());
        // factory.getOutInterceptors().add(new LoggingOutInterceptor());
        // 5. 创建并返回代理对象
        return (WeatherWebServiceSoap) factory.create();
    }
}

第4步:在 Service 或 Controller 中注入并使用

现在你可以在任何需要的地方通过 @Autowired 注入这个客户端,然后直接调用方法。

import com.example.weather.ArrayOfString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WeatherService {
    @Autowired
    private WeatherWebServiceSoap weatherWebServiceSoap; // 注入客户端
    public void getWeatherInfo(String cityCode) {
        System.out.println("正在查询 " + cityCode + " 的天气...");
        ArrayOfString result = weatherWebServiceSoap.getWeather(cityCode, "");
        System.out.println("查询结果:");
        result.getString().forEach(System.out::println);
    }
}

然后在你的 WeatherController 中调用 WeatherService 即可。


总结与对比

特性 JDK javax.xml.ws (JAX-WS) Apache CXF Spring Boot + CXF
依赖 无需额外依赖 需要 CXF 库 需要 Spring Boot + CXF
易用性 简单,适合快速上手 简单,功能更丰富 需要理解 Spring,但集成后最优雅
灵活性 较低,配置选项少 高,支持拦截器、数据绑定等 非常高,可与 Spring 生态无缝集成
适用场景 简单的、一次性的调用 复杂项目、需要高级功能 现代 Spring Boot 企业级应用
代码生成 wsimport wsdl2java (功能更强) wsdl2java
推荐度 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐

如何选择?

  • 如果你只是写一个小的测试程序,或者临时调用一个 WebService,使用 方法一 (JAX-WS) 最快,不用配置任何东西。
  • 如果你的项目已经是一个复杂的 Java Web 应用,并且对性能和灵活性有要求,使用 方法二 (Apache CXF) 是一个稳健的选择。
  • 如果你的项目是基于 Spring Boot 的,或者你希望遵循 Spring 的开发规范,追求可维护性和可扩展性方法三 (Spring Boot + CXF) 是最佳实践,也是目前业界的主流方案。
分享:
扫描分享到社交APP
上一篇
下一篇