杰瑞科技汇

如何调用Java WebService?

调用 SOAP WebService

SOAP (Simple Object Access Protocol) 是一种基于 XML 的协议,通常通过 WSDL (Web Services Description Language) 文档来定义其接口,Java 中调用 SOAP 服务最经典和强大的工具是 JAX-WS (Java API for XML Web Services)

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

客户端已提供 WSDL 地址

这是最常见的情况,我们可以使用 JDK 自带的 wsimport 工具,根据 WSDL 文件自动生成客户端调用代码。

步骤:

获取 WSDL 地址 假设 WebService 的 WSDL 地址是:http://www.example.com/service?wsdl

使用 wsimport 生成客户端代码 打开命令行(CMD 或 PowerShell),执行以下命令:

如何调用Java WebService?-图2
(图片来源网络,侵删)
# -p: 指定生成的包名
# -d: 指定代码输出目录
# -keep: 保留生成的源文件
# -s: 指定源文件输出目录
wsimport -p com.example.client -d . -s . http://www.example.com/service?wsdl

执行后,会在你指定的目录下生成一堆 .java 文件和 .class 文件,这些就是调用该 WebService 所需的客户端代理类。

在 Java 代码中调用生成的客户端 你可以在你的 Java 项目中使用这些生成的类来调用服务了。

import com.example.client.*; // 导入生成的包
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.URL;
public class SoapWebServiceClient {
    public static void main(String[] args) throws Exception {
        // 1. 指定 WSDL 文件的 URL
        URL wsdlUrl = new URL("http://www.example.com/service?wsdl");
        // 2. 定义服务名和命名空间,这些信息可以从 WSDL 文件中找到
        // <wsdl:service name="MyService">
        // <wsdl:port name="MyServicePort" binding="tns:MyServiceBinding">
        QName serviceName = new QName("http://www.example.com/", "MyService");
        QName portName = new QName("http://www.example.com/", "MyServicePort");
        // 3. 创建 Service 实例
        Service service = Service.create(wsdlUrl, serviceName);
        // 4. 获取 Port (服务端点接口)
        MyService servicePort = service.getPort(portName, MyService.class);
        // 5. 调用 WebService 提供的方法
        // 假设 WSDL 中定义了一个名为 "sayHello" 的方法,接受一个字符串参数
        String response = servicePort.sayHello("Java Client");
        // 6. 打印结果
        System.out.println("调用结果: " + response);
    }
}

重要提示:

  • WebService 服务器需要认证(如用户名/密码),通常需要使用 SOAPHandlerBindingProvider 来添加 SOAP Header。BindingProvider 的方式更简单:
// ... 在获取 Port 之后 ...
BindingProvider bindingProvider = (BindingProvider) servicePort;
bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "your_username");
bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "your_password");

手动构造 SOAP 请求(不使用 wsimport

在某些情况下,你可能无法使用 wsimport(WSDL 文件不可用,或者你需要更灵活地控制请求内容),这时,你可以使用 javax.xml.soap 包来手动构造和发送 SOAP 请求。

如何调用Java WebService?-图3
(图片来源网络,侵删)
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import java.net.URL;
public class ManualSoapClient {
    public static void main(String[] args) throws Exception {
        // 1. 创建 SOAP 连接
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection soapConnection = soapConnectionFactory.createConnection();
        // 2. 创建 SOAP 消息
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        // 3. 创建 SOAP Part (包含 Envelope)
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration("m", "http://www.example.com/"); // 添加命名空间
        // 4. 创建 SOAP Body 和内容
        SOAPBody soapBody = envelope.getBody();
        SOAPBodyElement bodyElement = soapBody.addBodyElement(
                new QName("http://www.example.com/", "sayHello")); // 方法名
        bodyElement.addTextNode("Java Manual Client"); // 参数
        // 5. 设置目标地址
        SOAPAddress soapAddress = envelope.getHeader().addHeaderElement(
                new QName("http://schemas.xmlsoap.org/wsdl/soap//", "endpoint"))
                .addAttribute(new QName("mustUnderstand", "0"), "http://www.example.com/");
        soapAddress.setValueURI("http://www.example.com/service");
        // 6. 保存消息
        soapMessage.saveChanges();
        // 7. 打印请求(可选,用于调试)
        System.out.println("请求 SOAP 消息:");
        soapMessage.writeTo(System.out);
        System.out.println("\n----------------------------------------");
        // 8. 发送请求并获取响应
        URL endpoint = new URL("http://www.example.com/service");
        SOAPMessage soapResponse = soapConnection.call(soapMessage, endpoint);
        // 9. 处理响应
        System.out.println("响应 SOAP 消息:");
        soapResponse.writeTo(System.out);
        // 提取响应内容...
        // ...
        // 10. 关闭连接
        soapConnection.close();
    }
}

这种方法更底层,更灵活,但代码也更复杂。


调用 RESTful WebService

RESTful WebService 更像是一个普通的 Web 应用,它使用 HTTP 协议(GET, POST, PUT, DELETE)和 JSON 或 XML 格式进行数据交换,在 Java 中调用 RESTful 服务,最主流的工具是 Apache HttpClientOkHttp,在现代 Spring Boot 项目中,则更推荐使用 Spring RestTemplate (已进入维护模式) 或 WebClient (推荐)。

使用 Apache HttpClient (通用,适用于任何 Java 项目)

需要在你的 pom.xml 中添加依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version> <!-- 使用较新稳定版 -->
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version> <!-- 用于 JSON 序列化/反序列化 -->
</dependency>

示例代码:

假设我们要调用一个 GET 请求来获取用户信息。

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
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;
import java.io.IOException;
public class RestClientHttpClient {
    public static void main(String[] args) {
        // 1. 创建 HttpClient 实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 2. 创建 HTTP GET 请求
        String apiUrl = "https://jsonplaceholder.typicode.com/posts/1";
        HttpGet request = new HttpGet(apiUrl);
        // 3. 设置请求头 (设置 Accept 为 application/json)
        request.addHeader("Accept", "application/json");
        try {
            // 4. 执行请求
            CloseableHttpResponse response = httpClient.execute(request);
            // 5. 获取响应实体
            HttpEntity entity = response.getEntity();
            String responseString = EntityUtils.toString(entity);
            // 6. 打印响应内容
            System.out.println("响应状态码: " + response.getStatusLine());
            System.out.println("响应内容: " + responseString);
            // 7. 使用 Jackson 解析 JSON
            ObjectMapper objectMapper = new ObjectMapper();
            // 假设响应是一个包含 "id", "title", "body" 的 JSON 对象
            // 可以创建一个对应的 Java 类 (如 Post) 来映射
            // Post post = objectMapper.readValue(responseString, Post.class);
            // System.out.println("解析后的标题: " + post.getTitle());
            // 8. 确保响应实体被完全消费
            EntityUtils.consume(entity);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 9. 关闭 HttpClient
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用 Spring WebClient (推荐,适用于 Spring Boot 项目)

WebClient 是 Spring 5 引入的响应式、非阻塞的 HTTP 客户端,是 RestTemplate 的替代品,功能更强大。

在 Spring Boot 项目的 pom.xml 中确保有 spring-boot-starter-webflux 依赖(它包含了 WebFlux 和 WebClient)。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

示例代码:

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class SpringWebClient {
    public static void main(String[] args) {
        // 1. 创建 WebClient 实例
        WebClient webClient = WebClient.create();
        // 2. 定义 API URL
        String apiUrl = "https://jsonplaceholder.typicode.com/posts/1";
        // 3. 发送 GET 请求并获取响应 (Mono 是一个 0-1 个元素的响应式流)
        Mono<String> responseMono = webClient.get()
                .uri(apiUrl)
                .retrieve() // 获取响应
                .bodyToMono(String.class); // 将响应体转换为 String
        // 4. 订阅 Mono 并处理结果
        responseMono.subscribe(
                responseBody -> {
                    System.out.println("响应内容: " + responseBody);
                    // 在这里可以继续处理 JSON 数据
                },
                error -> {
                    System.err.println("发生错误: " + error.getMessage());
                }
        );
        // 为了让主线程等待异步操作完成
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

WebClient 的优点是异步、非阻塞,性能更高,并且链式调用非常优雅。


总结与对比

特性 SOAP (JAX-WS) REST (HttpClient / WebClient)
协议 基于XML的专用协议 基于HTTP (GET, POST等)
标准 WSDL, UDDI (严格) 无统一标准,遵循RESTful原则
数据格式 XML (强制) JSON, XML, Text等 (灵活)
调用方式 通过生成的客户端代理类 直接构造HTTP请求
性能 通常较低 (XML解析开销大) 通常较高 (轻量级,JSON解析快)
安全性 内置安全标准 (WS-Security) 依赖HTTPS和Token (如JWT, OAuth)
适用场景 企业级应用、金融、电信等对事务和安全要求高的场景 移动应用、前后端分离、微服务、公开API等

如何选择?

  • 如果服务是传统的 Java WebService (Axis, CXF等),并且提供了 WSDL 文件,优先使用 JAX-WS + wsimport,这是最标准、最可靠的方式。
  • 如果服务是现代的 RESTful API,返回 JSON 数据:
    • 普通 Java SE 项目 中,使用 Apache HttpClient
    • Spring / Spring Boot 项目 中,强烈推荐使用 WebClient (异步) 或 RestTemplate (同步,但已不推荐新项目使用)。

希望这份详细的指南能帮助你成功调用 Java WebService!

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