杰瑞科技汇

调用 java webservice

目录

  1. 核心概念:SOAP vs. REST
  2. 第一部分:调用 SOAP WebService
    • 什么是 SOAP WebService?
    • 准备工作:获取 WSDL 文件
    • 使用 JDK 自带的 wsimport 工具(最经典)
    • 使用 Apache CXF 框架(更灵活、功能更强)
    • 使用 Spring Boot + CXF(现代企业级应用)
  3. 第二部分:调用 RESTful WebService (以 JSON 为例)
    • 什么是 RESTful WebService?
    • 准备工作:了解 API 的 URL、HTTP 方法、请求/响应格式
    • 使用 java.net.HttpURLConnection(原生,无需依赖)
    • 使用 Apache HttpClient(功能更强大的 HTTP 客户端)
    • 使用 Spring Boot RestTemplate(经典、简洁)
    • 使用 Spring Boot WebClient(现代、异步、非阻塞)
  4. 总结与对比

核心概念:SOAP vs. REST

在开始之前,必须明确你要调用的是哪种类型的 WebService,因为它们的调用方式完全不同。

调用 java webservice-图1
(图片来源网络,侵删)
特性 SOAP (Simple Object Access Protocol) REST (Representational State Transfer)
协议 严格基于 XML,是一个协议 一种架构风格,通常基于 HTTP/HTTPS。
数据格式 强制使用 XML。 灵活,常用 JSON, XML, HTML, Text。
标准 有严格的规范(WSDL, SOAP, UDDI)。 没有官方标准,遵循一组约束(如无状态、统一接口)。
操作 通过 POST 请求,在 SOAP Body 中发送指令。 使用标准的 HTTP 方法 (GET, POST, PUT, DELETE)。
描述文件 WSDL (Web Services Description Language),定义了服务的所有接口、方法、参数和返回值。 通常使用 OpenAPI/Swagger 文档来描述 API。
适用场景 企业级应用、金融、电信等对安全性、事务性要求高的场景。 移动应用、Web 前后端分离、微服务架构等。

第一部分:调用 SOAP WebService

SOAP WebService 的调用核心是利用 WSDL 文件,WSDL 文件就像是服务的“说明书”,描述了服务提供了哪些方法、每个方法需要什么参数、返回什么类型。

准备工作:获取 WSDL 文件

假设我们要调用一个天气预报服务,它的 WSDL 地址是: http://ws.webxml.com.cn/WebServices/WeatherWS?wsdl

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

这是最传统、最直接的方法,无需额外引入第三方库。

步骤 1:根据 WSDL 生成 Java 客户端代码

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

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

# -keep: 生成源代码文件
# -d: 指定编译后的 .class 文件存放目录
# -p: 指定生成的包名
wsimport -keep -d D:\temp -p com.example.weather.client http://ws.webxml.com.cn/WebServices/WeatherWS?wsdl

执行后,会在 D:\temp\com\example\weather\client 目录下生成一堆 .java.class 文件,这些就是客户端代理类。

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

  1. 将生成的 .class 文件(或整个包)复制到你的 Java 项目的 classes 目录下,或者打包成 JAR 文件引入项目。
  2. 编写 Java 代码调用服务。
import com.example.weather.client.WeatherWS;
import com.example.weather.client.WeatherWSSoap;
public class SoapClientTest {
    public static void main(String[] args) {
        // 1. 创建服务视图对象 (Service)
        // 这个类是根据 WSDL 中的 <service> 标签生成的
        WeatherWS weatherWS = new WeatherWS();
        // 2. 获取服务端点对象 (PortType)
        // 这个类是根据 WSDL 中的 <portType> 标签生成的,包含了所有可用的方法
        WeatherWSSoap weatherWSSoap = weatherWS.getWeatherWSSoap();
        // 3. 调用具体的方法
        // 假设 getWeather 方法需要一个城市参数
        String result = weatherWSSoap.getWeather("北京", "");
        // 4. 处理返回结果
        System.out.println("调用 SOAP WebService 返回的结果:");
        System.out.println(result);
    }
}

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

CXF 是一个非常流行的开源 WebService 框架,它提供了比 wsimport 更强大的功能和更好的集成能力。

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

步骤 1:添加 Maven 依赖

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

<dependencies>
    <!-- cxf-core -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-core</artifactId>
        <version>3.4.5</version>
    </dependency>
    <!-- cxf-rt-frontend-jaxws -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.4.5</version>
    </dependency>
    <!-- cxf-rt-transports-http -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.4.5</version>
    </dependency>
</dependencies>

步骤 2:使用 CXF 的 JAX-WS 动态客户端

CXF 提供了一种无需预先生成代码的方式,可以直接通过 WSDL 动态调用。

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
public class CxfClientTest {
    public static void main(String[] args) {
        // 方法一:使用 JaxWsProxyFactoryBean (需要知道服务接口)
        // 如果你能从 WSDL 中获取到服务接口的全限定名,这是最简单的方式
        /*
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(com.example.weather.client.WeatherWSSoap.class); // 设置服务接口
        factory.setAddress("http://ws.webxml.com.cn/WebServices/WeatherWS?wsdl");
        WeatherWSSoap weatherService = (WeatherWSSoap) factory.create();
        String result1 = weatherService.getWeather("上海", "");
        System.out.println("JaxWsProxyFactoryBean 结果: " + result1);
        */
        // 方法二:使用 JaxWsDynamicClientFactory (无需任何接口,最灵活)
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://ws.webxml.com.cn/WebServices/WeatherWS?wsdl");
        try {
            // invoke 方法参数:方法名, 参数1, 参数2, ...
            // getWeather 方法需要两个参数,第一个是城市名,第二个是空字符串
            Object[] result = client.invoke("getWeather", "广州", "");
            System.out.println("JaxWsDynamicClientFactory 结果: " + result[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第二部分:调用 RESTful WebService

RESTful WebService 的调用本质上是发送 HTTP 请求,并处理 HTTP 响应,在现代 Java 开发中,通常使用成熟的 HTTP 客户端库。

假设我们要调用一个公共的 JSONPlaceholder API 来获取一个用户信息:

  • URL: https://jsonplaceholder.typicode.com/users/1
  • HTTP Method: GET
  • 返回格式: JSON

使用 java.net.HttpURLConnection(原生,无需依赖)

这是 Java 自带的,无需任何额外依赖,但代码较为繁琐。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class NativeHttpClientTest {
    public static void main(String[] args) {
        String urlString = "https://jsonplaceholder.typicode.com/users/1";
        try {
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法
            connection.setRequestMethod("GET");
            // 设置请求头
            connection.setRequestProperty("Accept", "application/json");
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            if (responseCode == HttpURLConnection.HTTP_OK) { // 200
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // 打印返回的 JSON 字符串
                System.out.println("Response Body: " + response.toString());
            } else {
                System.out.println("GET request failed");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Apache HttpClient(功能更强大的 HTTP 客户端)

Apache HttpClient 是一个久经考验的 HTTP 客户端库,功能非常全面。

步骤 1:添加 Maven 依赖

<dependencies>
    <!-- Apache HttpClient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <!-- 为了方便处理 JSON,添加一个 JSON 库,Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.0</version>
    </dependency>
</dependencies>

步骤 2:编写调用代码

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class ApacheHttpClientTest {
    public static void main(String[] args) {
        String apiUrl = "https://jsonplaceholder.typicode.com/users/1";
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(apiUrl);
            request.addHeader("accept", "application/json");
            System.out.println("Executing request " + request.getRequestLine());
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                System.out.println(response.getStatusLine().getStatusCode());
                String responseBody = EntityUtils.toString(response.getEntity());
                System.out.println("Response Body: " + responseBody);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用 Spring Boot RestTemplate(经典、简洁)

如果你的项目是基于 Spring Boot 的,RestTemplate 是调用 RESTful API 的首选方式之一。

步骤 1:配置 RestTemplate

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

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

步骤 2:注入并使用 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 RestTemplateUser implements CommandLineRunner {
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public void run(String... args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/users/1";
        // 直接获取 JSON 字符串
        String jsonString = restTemplate.getForObject(url, String.class);
        System.out.println("RestTemplate (String): " + jsonString);
        // 将 JSON 自动映射到 Java 对象 (需要定义一个对应的 User 类)
        // 假设我们有一个 User 类,其字段名与 JSON 的 key 一致
        User user = restTemplate.getForObject(url, User.class);
        System.out.println("RestTemplate (Object): " + user.getName() + ", " + user.getEmail());
    }
}
// 一个简单的 POJO 类,用于映射 JSON
class User {
    private int id;
    private String name;
    private String username;
    private String email;
    // ... 其他字段,以及 getter/setter
    // 为了简化,省略了 getter/setter,实际项目中需要添加
    @Override
    public String toString() {
        return "User{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}';
    }
}

使用 Spring Boot WebClient(现代、异步、非阻塞)

WebClient 是 Spring 5 引入的、作为 RestTemplate 替代品的新一代 HTTP 客户端,它基于响应式编程,支持非阻塞 I/O,性能更高,尤其适合微服务架构。

步骤 1:添加依赖

WebClient 在 spring-webflux 中,但它与 Spring Boot Web starter 兼容。

<!-- spring-boot-starter-web 已经包含了 spring-webflux 的依赖 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

步骤 2:注入并使用 WebClient

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 WebClientUser implements CommandLineRunner {
    @Autowired
    private WebClient.Builder webClientBuilder;
    @Override
    public void run(String... args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/users/1";
        Mono<User> userMono = webClientBuilder.build()
                .get()
                .uri(url)
                .retrieve() // 发出请求并获取响应
                .bodyToMono(User.class); // 将响应体解析为 User 对象的单个值
        // 阻塞式获取结果(在简单的命令行应用中方便)
        // 在实际的异步应用中,应该使用 subscribe() 方法
        User user = userMono.block();
        System.out.println("WebClient Result: " + user.getName() + ", " + user.getEmail());
    }
}

总结与对比

调用类型 推荐方法 优点 缺点 适用场景
SOAP JDK wsimport 无需外部依赖,简单直接。 生成代码,不够灵活,处理复杂 XML/附件麻烦。 快速原型、简单的遗留系统集成。
Apache CXF 功能强大,支持多种协议,动态调用无需生成代码,易于集成到 Spring。 需要引入额外框架。 企业级应用、需要高级特性(如 WS-Security)的项目。
RESTful 原生 HttpURLConnection 无依赖,轻量级。 代码繁琐,功能有限,需要手动处理连接、流和错误。 极简应用、无法引入第三方库的环境。
Apache HttpClient 功能全面稳定,社区支持好,可定制性强。 代码量比 RestTemplate 多,需要手动处理 JSON。 需要精细控制 HTTP 请求/响应的复杂应用。
Spring RestTemplate 集成简单,代码简洁,支持自动 JSON/XML 转换。 是同步阻塞模型,性能不如 WebClient。 大多数 Spring/Spring Boot 项目的同步调用。
Spring WebClient 异步非阻塞,性能高,支持响应式编程。 学习曲线较陡,基于响应式编程模型。 新的 Spring 5+ 项目,微服务,对性能要求高的应用。

给你的建议:

  • 如果调用 SOAP 服务:如果你的项目不复杂,直接用 wsimport,如果项目是 Spring 体系,或者你需要更强大的功能(如安全、WS-Addressing),直接用 Apache CXF
  • 如果调用 RESTful 服务
    • 如果你的项目是 Spring Boot首选 RestTemplate(简单同步)或 WebClient(高性能异步)。
    • 如果不是 Spring 项目,或者你需要一个非常轻量级的解决方案,可以用 原生 HttpURLConnection
    • 如果你需要非常精细的 HTTP 控制,或者项目已经在使用 Apache Commons 生态,Apache HttpClient 是一个可靠的选择。
分享:
扫描分享到社交APP
上一篇
下一篇