杰瑞科技汇

Java如何调用并获取WebService数据?

调用 SOAP WebService

SOAP 是一种基于 XML 的协议,功能强大,但相对复杂,在 Java 中,调用 SOAP WebService 主要有以下几种方式:

Java如何调用并获取WebService数据?-图1
(图片来源网络,侵删)

使用 JDK 自带的 wsimport 工具 (最经典、最常用)

这是最传统和标准的方法,通过客户端代理的方式调用,它从 WSDL (Web Services Description Language) 文件生成客户端代码。

适用场景:目标服务提供了标准的 WSDL 文件,且您希望生成一个强类型的客户端。

步骤:

获取 WSDL 文件地址

Java如何调用并获取WebService数据?-图2
(图片来源网络,侵删)

访问 WebService 的 WSDL 地址,通常是一个 .wsdl 结尾的 URL。http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl

使用 wsimport 生成客户端代码

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

# 基本语法
wsimport -keep -p com.example.client -d . http://example.com/service?wsdl
# 参数解释:
# -keep: 生成源代码文件
# -p <package.name>: 指定生成代码的包名
# -d <directory>: 指定生成.class文件的目录,`.` 表示当前目录
# <wsdl_url>: WSDL 文件的地址

调用 WebXml 提供的 QQ 在线状态查询服务:

Java如何调用并获取WebService数据?-图3
(图片来源网络,侵删)
wsimport -keep -p com.example.qqclient -d . http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl

执行成功后,会在指定的目录下生成一堆 Java 文件(.java)和 class 文件(.class)。

编写 Java 代码调用服务

你可以像调用本地 Java 对象一样调用远程服务了。

package com.example.qqclient;
public class MainApp {
    public static void main(String[] args) {
        // 1. 创建服务视图 (Service)
        // 注意:这里的类名是根据 WSDL 生成的,通常是 "XXXService"
        qqOnlineWebService service = new qqOnlineWebService();
        // 2. 获取服务端点 (Port)
        // 注意:这里的端口名是根据 WSDL 生成的,通常是 "XXX"
        qqOnlineWebServiceSoap port = service.getqqOnlineWebServiceSoap();
        // 3. 调用具体的方法
        // 查询 QQ 号码 "12345678" 的在线状态
        String qqCode = "12345678";
        String result = port.checkOnline(qqCode);
        // 4. 处理结果
        System.out.println("QQ 号码 " + qqCode + " 的在线状态是: " + result);
    }
}

优点

  • 强类型,编译时检查。
  • 代码直观,易于理解和使用。
  • 是 Java EE 的标准做法。

缺点

  • 需要一个额外的代码生成步骤。
  • 生成的代码可能比较庞大。

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

CXF 是一个开源的 Services 框架,它支持 SOAP、RESTful 等多种 WebService 标准,它也支持从 WSDL 生成客户端,但提供了更多的灵活性和高级功能。

适用场景:项目已经使用 CXF,或者需要更高级的特性(如 WS-Security、RESTful 集成等)。

步骤:

添加 CXF 依赖

如果你使用 Maven,在 pom.xml 中添加:

<dependencies>
    <!-- CXF 核心依赖 -->
    <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>

使用 cxf-xjc-utils 或 Maven 插件生成代码 (可选)

CXF 也提供了 wsdl2java 工具,功能和 wsimport 类似,但更强大,你可以通过 Maven 插件或命令行使用。

编写 Java 代码调用

生成的客户端代码和使用方式与 wsimport 非常相似,底层实现由 CXF 处理。

// ... 生成的 import 语句 ...
public class CxfClientApp {
    public static void main(String[] args) {
        // JAX-WS 标准方式创建客户端,CXF 在底层实现它
        QQOnlineWebService service = new QQOnlineWebService();
        QQOnlineWebServiceSoap port = service.getQQOnlineWebServiceSoapPort(); // 端口名可能不同
        String result = port.checkOnline("87654321");
        System.out.println("CXF 调用结果: " + result);
    }
}

优点

  • 功能强大,支持 WS-* 标准(如安全、事务等)。
  • 与 Spring 框架集成得非常好。
  • 性能和灵活性优于标准 JDK 实现。

使用第三方库(如 Axis2JAX-WS RI

Axis2 是另一个非常流行的 WebService 框架,功能同样强大。JAX-WS RI (Metro) 是 Sun 官方的参考实现,有时比 JDK 自带的更新更快。

它们的用法与 CXF 类似,都需要引入依赖并生成客户端代码。



调用 RESTful WebService (现在更常见)

RESTful 服务通常返回 JSON 或 XML 数据,而不是 SOAP 信封,在 Java 中调用 RESTful 服务,通常不是“获取”一个服务,而是“消费”一个 API。

使用 java.net.http.HttpClient (Java 11+,推荐)

这是 Java 11 引入的现代化、功能强大的 HTTP 客户端 API。

适用场景:Java 11 或更高版本,需要简洁、标准的方式来调用 REST API。

示例:调用一个返回 JSON 的公共 API

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建 HttpClient
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2)
                .connectTimeout(Duration.ofSeconds(10))
                .build();
        // 2. 创建 HttpRequest
        // 以 JSONPlaceholder 为例,这是一个免费的测试 API
        HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
                .header("Accept", "application/json")
                .build();
        // 3. 发送请求并获取响应
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        // 4. 处理响应
        System.out.println("Status Code: " + response.statusCode());
        System.out.println("Response Body: " + response.body());
    }
}

优点

  • 现代、内置、无外部依赖。
  • 支持 HTTP/2,异步请求等高级特性。

使用 Apache HttpClient (经典、稳定)

这是一个非常成熟和广泛使用的第三方 HTTP 客户端库。

适用场景:Java 8 或更低版本,或者需要比标准库更丰富的功能和更好的性能。

步骤:

添加依赖

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.1</version> <!-- 使用最新版 -->
</dependency>
<!-- 如果需要处理 JSON,添加 Jackson 或 Gson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>

编写代码

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.io.entity.EntityUtils;
public class ApacheHttpClientExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建 HttpClient 实例
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 2. 创建 HTTP GET 请求
            HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");
            request.addHeader("Accept", "application/json");
            // 3. 执行请求
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                // 4. 获取并处理响应体
                String responseBody = EntityUtils.toString(response.getEntity());
                System.out.println("Status Code: " + response.getCode());
                System.out.println("Response Body: " + responseBody);
            }
        }
    }
}

使用 Spring RestTemplate (Spring 生态)

如果你正在使用 Spring Boot 或 Spring 框架,RestTemplate 是调用 REST API 的传统选择(在 Spring 3.0+ 中引入)。

适用场景:Spring 项目。

添加依赖 (Spring Boot Starter 已包含)

<!-- Spring Boot Starter Web 已经包含了 RestTemplate -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

配置和使用

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 MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
    // 将 RestTemplate 注册为 Bean
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class MyApiClient implements CommandLineRunner {
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public void run(String... args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        // 直接将响应体映射到一个 POJO (Plain Old Java Object)
        Post post = restTemplate.getForObject(url, Post.class);
        System.out.println("Title: " + post.getTitle());
        System.out.println("Body: " + post.getBody());
    }
}
// 假设的 Post 类,与 JSON 结构对应
class Post {
    private int userId;
    private int id;
    private String title;
    private String body;
    // Getters and Setters...
    public String getTitle() { return title; }
    public String getBody() { return body; }
    // ...
}

注意:在 Spring Boot 3.2 中,RestTemplate 已被标记为过时,推荐使用 WebClient


使用 Spring WebClient (Spring 5+,异步、非阻塞)

WebClient 是 Spring 5 引入的响应式 HTTP 客户端,是 RestTemplate 的替代品,支持非阻塞 I/O,性能更高。

适用场景:Spring WebFlux 项目,或者在传统 Spring MVC 项目中需要高性能异步调用。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class MyWebFluxApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyWebFluxApplication.class, args);
    }
    @Bean
    public WebClient webClient() {
        return WebClient.create();
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Component
public class MyWebClientApiCaller implements CommandLineRunner {
    @Autowired
    private WebClient webClient;
    @Override
    public void run(String... args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        Mono<Post> postMono = webClient.get()
                .uri(url)
                .retrieve() // 发出请求并获取响应
                .bodyToMono(Post.class); // 将响应体解析为 Post 对象的单个流
        // 订阅 Mono 并打印结果
        postMono.subscribe(post -> {
            System.out.println("Title: " + post.getTitle());
            System.out.println("Body: " + post.getBody());
        });
    }
}
// Post 类同上

总结与选择指南

调用类型 推荐方法 适用场景 优点 缺点
SOAP JDK wsimport 快速、标准的 SOAP 调用,无复杂依赖 强类型,简单直接 需要生成代码,灵活性差
Apache CXF 企业级应用,需要 WS-* 安全等高级特性 功能强大,灵活,与 Spring 集成好 引入第三方依赖
RESTful java.net.http.HttpClient Java 11+ 项目,追求现代和标准 内置,无依赖,支持 HTTP/2 功能相对基础
Apache HttpClient Java 8+ 项目,需要稳定和丰富的功能 成熟稳定,社区强大,功能全面 需要手动管理依赖
Spring RestTemplate 传统 Spring MVC 项目 与 Spring 生态无缝集成,方便 同步阻塞,在 Spring 3.2+ 中已过时
Spring WebClient 新项目,特别是 Spring WebFlux,或需要高性能异步调用 响应式,非阻塞,性能高 学习曲线稍陡,需要响应式编程基础

如何选择?

  1. 首先判断是 SOAP 还是 RESTful

    • WSDL 文件存在,基本可以确定是 SOAP。
    • 如果是 RESTful,通常没有 WSDL,而是通过 API 文档(如 Swagger/OpenAPI)来描述。
  2. 根据你的技术栈选择

    • 纯 Java 项目:SOAP 用 wsimport,RESTful 用 java.net.http.HttpClient (JDK 11+) 或 Apache HttpClient
    • Spring 项目:SOAP 用 wsimport + Spring 注入,RESTful 优先考虑 WebClient,旧项目用 RestTemplate

希望这个详细的指南能帮助您在 Java 中成功获取和调用 WebService!

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