杰瑞科技汇

Java如何调用WebService?

什么是 WebService?

WebService 是一种基于 Web 的、跨平台的、跨语言的远程服务调用技术,它使用 XML 来传输数据,并通过 HTTP 协议进行通信,最核心的标准是 SOAP (Simple Object Access Protocol)WSDL (Web Services Description Language)

Java如何调用WebService?-图1
(图片来源网络,侵删)
  • WSDL (Web Services Description Language): 一个 XML 文件,它描述了 WebService 的所有信息,比如服务地址、可用的方法、每个方法的参数类型和返回值类型等,调用方通过 WSDL 文件来了解如何调用服务。
  • SOAP (Simple Object Access Protocol): 一种协议,规定了消息的格式,SOAP 消息是一个 XML 文档,包含了调用的方法名、参数和返回结果。

调用 WebService 的几种主要方式

JDK 自带的 javax.xml.ws (原生 API) - 最传统

这是 Java 标准库自带的方式,无需引入第三方依赖,适合简单的调用,核心是使用 wsimport 工具生成客户端代码。

步骤:

  1. 使用 wsimport 生成客户端代码

    • wsimport 是 JDK 自带的命令行工具,它会根据 WSDL 文件生成一系列 Java 类(如 ServicePortTypeData Type 等)。
    • 打开命令行,执行以下命令:
      # -p: 指定生成的包名
      # -d: 指定生成代码的存放目录
      # -keep: 生成后保留 .java 文件,方便查看
      wsimport -p com.example.client -d ./src/main/java -keep http://www.example.com/service?wsdl
    • 执行成功后,你的项目目录下就会多出 com/example/client 包,里面包含了调用服务所需的所有类。
  2. 在 Java 代码中调用

    Java如何调用WebService?-图2
    (图片来源网络,侵删)
    • 生成的代码中通常会有一个 XXXService 类(MyWebServiceService),这是服务的入口。
    • 通过这个 Service 类可以获取到 XXX 端口(MyWebService),这个端口对象就是你实际用来调用的服务代理。

示例代码:

假设 wsimport 生成了 MyWebServiceServiceMyWebService 这两个类。

import com.example.client.MyWebService; // 生成的服务接口
import com.example.client.MyWebServiceService; // 生成的服务工厂类
public class JdkWebServiceClient {
    public static void main(String[] args) {
        try {
            // 1. 创建服务工厂对象
            // 参数是 wsdl 文件中的 service name
            MyWebServiceService service = new MyWebServiceService();
            // 2. 从工厂获取服务端口 (Port)
            // 参数是 wsdl 文件中的 port name
            MyWebService webService = service.getMyWebServicePort();
            // 3. 调用 WebService 的方法
            // 假设 WSDL 中定义了一个名为 sayHello 的方法,参数为 String name
            String result = webService.sayHello("Java Client");
            // 4. 处理结果
            System.out.println("WebService 返回结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点:

  • 无需额外依赖,JDK 自带。
  • 官方支持,稳定可靠。

缺点:

Java如何调用WebService?-图3
(图片来源网络,侵删)
  • 需要预先通过 wsimport 生成代码,开发流程稍显繁琐。
  • 生成的代码可能很多,增加项目体积。
  • 处理复杂的数据类型(如 Map、List)时可能不太方便。

Apache CXF - 业界主流框架

Apache CXF 是一个非常强大和流行的开源框架,用于构建和开发 WebService,它既支持作为服务器端框架,也支持作为客户端框架,CXF 可以使用原生 API 方式,也可以使用更简单的动态客户端。

使用原生 API (类似 JDK 方式)

这种方式和 JDK 的 javax.xml.ws 类似,CXF 也提供了自己的注解和 API,但如果你习惯 JDK 的方式,CXF 完全兼容。

动态客户端 (更简单,推荐)

动态客户端不需要预先生成任何代码,而是直接在运行时通过 WSDL 地址来调用服务,非常灵活。

步骤:

  1. 添加 Maven 依赖

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.4.5</version> <!-- 使用合适的版本 -->
    </dependency>

    注意:即使你不用 Spring Boot,也可以使用 cxf-rt-frontend-jaxwscxf-rt-transports-http 等核心依赖。

  2. 编写 Java 代码调用

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class CxfDynamicClient {
    public static void main(String[] args) {
        // 1. 创建 JaxWsProxyFactoryBean 实例
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 2. 设置 WebService 的 WSDL 地址
        factory.setAddress("http://www.example.com/service?wsdl");
        // 3. 设置服务接口 (这个接口需要你根据 WSDL 手动定义,或者用 CXF 的 wsdl2java 工具生成)
        // 为了演示,我们假设有一个接口 MyWebService
        factory.setServiceClass(MyWebService.class);
        // 4. 创建服务代理对象
        MyWebService webService = factory.create(MyWebService.class);
        // 5. 调用方法
        String result = webService.sayHello("CXF Dynamic Client");
        // 6. 处理结果
        System.out.println("WebService 返回结果: " + result);
    }
}

优点:

  • 功能强大,支持 SOAP 1.1/1.2, RESTful 等多种协议。
  • 动态客户端非常灵活,无需生成代码。
  • 社区活跃,文档丰富。
  • 与 Spring/Spring Boot 集成非常方便。

缺点:

  • 引入了第三方框架,会增加项目依赖。

Spring Boot 整合 CXF - 现代企业级首选

这是目前企业开发中最常见的方式,它将 CXF 客户端无缝集成到 Spring Boot 应用中,可以方便地使用 Spring 的特性(如依赖注入)。

步骤:

  1. 添加 Maven 依赖 (同 CXF 方式)

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.4.5</version>
    </dependency>
  2. 定义服务接口 (根据 WSDL 手动创建或生成)

    // com/example/service/MyWebService.java
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebService;
    @WebService(name = "MyWebService", targetNamespace = "http://www.example.com/")
    public interface MyWebService {
        @WebMethod
        String sayHello(@WebParam(name = "name") String name);
    }
  3. 创建客户端配置类

    使用 @Bean 将 CXF 的客户端工厂声明为 Spring Bean。

    // com/example/config/WebServiceClientConfig.java
    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration
    public class WebServiceClientConfig {
        @Bean
        public MyWebService myWebServiceClient() {
            JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
            factory.setAddress("http://www.example.com/service?wsdl");
            factory.setServiceClass(MyWebService.class);
            return (MyWebService) factory.create();
        }
    }
  4. 在 Service 中注入并调用

    // com/example/service/MyAppService.java
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    @Service
    public class MyAppService {
        @Autowired
        private MyWebService myWebService; // 注入客户端 Bean
        public void callWebService() {
            String result = myWebService.sayHello("Spring Boot Client");
            System.out.println("WebService 返回结果: " + result);
        }
    }

优点:

  • 集成度高,符合 Spring Boot 的开发习惯。
  • 客户端管理清晰,通过 Spring IoC 容器管理。
  • 代码结构清晰,易于维护和测试。

Spring Boot 整合 WebClient - 调用 RESTful WebService

如果你的 WebService 是 RESTful 风格(基于 HTTP/HTTPS,通常返回 JSON/XML,而不是 SOAP),那么使用 Spring 5+ 引入的 WebClient 是最佳选择,它是一个响应式的、非阻塞的 HTTP 客户端。

步骤:

  1. 添加 Maven 依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
  2. 编写调用代码

    假设有一个 RESTful 服务,地址是 http://www.example.com/api/users/123,返回 JSON 数据。

    import org.springframework.stereotype.Service;
    import org.springframework.web.reactive.function.client.WebClient;
    import reactor.core.publisher.Mono;
    @Service
    public class RestWebServiceClient {
        private final WebClient webClient;
        // 通过构造器注入 WebClient.Builder
        public RestWebServiceClient(WebClient.Builder webClientBuilder) {
            this.webClient = webClientBuilder.baseUrl("http://www.example.com").build();
        }
        public String getUserInfo(String userId) {
            // 定义返回的数据结构
            class User {
                public String id;
                public String name;
                public String email;
            }
            // 发起 GET 请求并异步获取响应
            Mono<User> userMono = this.webClient.get()
                    .uri("/api/users/{id}", userId)
                    .retrieve()
                    .bodyToMono(User.class);
            // 阻塞并获取结果 (在同步方法中)
            User user = userMono.block();
            return "User: " + user.name + ", Email: " + user.email;
        }
    }

优点:

  • 现代、异步、高性能。
  • 专门用于调用 RESTful API,非常直观。
  • 是 Spring 生态系统的标准 HTTP 客户端。

缺点:

  • 只适用于 RESTful 服务,不适用于传统的 SOAP WebService。

总结与对比

方式 适用场景 优点 缺点
JDK javax.xml.ws 简单、快速调用,不想引入第三方库。 无需依赖,JDK 自带。 需要预生成代码,处理复杂数据麻烦。
Apache CXF (动态) 需要灵活调用,不想维护生成的代码。 无需生成代码,功能强大,支持多种协议。 引入框架依赖,需要手动定义接口。
Spring Boot + CXF 企业级 Spring Boot 项目,需要整合 Spring 生态。 集成度高,代码清晰,易于管理。 引入框架依赖,配置稍显复杂。
Spring Boot + WebClient 调用 RESTful 风格的 WebService 或 API。 现代、异步、高性能,与 Spring 生态完美结合。 不适用于 SOAP

如何选择?

  1. 如果你的服务是 SOAP 协议

    • 小型项目/快速验证:使用 JDK 原生 API
    • 需要灵活性:使用 CXF 动态客户端
    • 企业级 Spring Boot 项目:使用 Spring Boot + CXF,这是最佳实践。
  2. 如果你的服务是 RESTful 协议

    • 直接使用 Spring Boot + WebClient,这是目前最现代和推荐的方式。

希望这个详细的指南能帮助你理解如何在 Java 中调用 WebService!

分享:
扫描分享到社交APP
上一篇
下一篇