杰瑞科技汇

java 调webservice

核心概念

在开始之前,先理解几个核心概念:

java 调webservice-图1
(图片来源网络,侵删)
  1. WebService: 一种跨编程语言、跨操作系统平台的远程调用技术,它使用 XML 格式进行数据交换,并遵循 SOAP (Simple Object Access Protocol) 协议。
  2. WSDL (Web Services Description Language): 一个 XML 文件,它描述了 WebService 的所有信息,包括:
    • 服务的地址
    • 可用的方法(操作)
    • 每个方法的参数和返回值的类型
    • 使用的协议(如 SOAP/HTTP)
    • WSDL WebService 的“说明书”或“API文档”。
  3. SOAP (Simple Object Access Protocol): 一种基于 XML 的协议,用于在 Web 上交换结构化的信息,SOAP 消息是一个包含 EnvelopeHeaderBody 的 XML 文档。

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

这是 Java 标准库提供的方式,无需额外引入第三方库,非常适合学习和简单的调用。

场景:调用一个公共的天气查询 WebService

我们以一个公共的 WebService 为例(这个地址是常用的示例,请确保其可用性):

  • WSDL 地址: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
  • 服务端点: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

步骤 1:生成客户端代码

直接在 Java 代码中调用会很复杂,因为需要手动构建 SOAP 请求、解析 SOAP 响应,最佳实践是使用 WSDL 文件自动生成客户端代理类。

下载 WSDL 文件http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl 的内容保存为一个本地文件,WeatherWebService.wsdl

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

使用 wsimport 工具生成代码 wsimport 是 JDK 自带的命令行工具,位于 JAVA_HOME/bin 目录下。

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

# -keep: 生成后保留源文件
# -d: 指定 class 文件的输出目录
# -p: 指定生成的包名
# wsdlLocation: 指定 WSDL 文件的路径(可以是本地文件或网络URL)
wsimport -keep -d ./src -p com.example.weather.client http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

执行成功后,你会在 com.example.weather.client 包下看到一堆生成的 .java 文件,这些就是客户端代理类。

步骤 2:编写 Java 调用代码

在项目中引入生成的代码,然后就可以像调用本地方法一样调用 WebService 了。

java 调webservice-图3
(图片来源网络,侵删)
package com.example.weather;
import com.example.weather.client.WeatherWebService;
import com.example.weather.client.WeatherWebServiceSoap;
public class WeatherClient {
    public static void main(String[] args) {
        // 1. 创建服务 Service 实例
        // WeatherWebService 是生成的类,代表整个 WSDL 服务
        WeatherWebService service = new WeatherWebService();
        // 2. 获取服务端点接口
        // WeatherWebServiceSoap 是生成的接口,代表具体的 SOAP 端点
        WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
        // 3. 调用方法
        // getWeather 是 WSDL 中定义的一个操作
        // 参数 "北京" 是要查询的城市
        String result = port.getWeather("北京", "");
        // 4. 打印结果
        System.out.println("查询结果:");
        System.out.println(result);
    }
}

运行结果: 你会得到一个包含北京天气信息的 XML 字符串。


使用 Spring Boot + WebServiceTemplate

在现代 Spring Boot 项目中,更推荐使用 Spring 提供的 WebServiceTemplate,它封装了底层的调用细节,使用起来更加方便和灵活。

步骤 1:添加 Maven 依赖

在你的 pom.xml 文件中添加 Spring Web 和 WebService 相关的依赖。

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Web Services -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web-services</artifactId>
    </dependency>
    <!-- 用于生成客户端代码的库 (可选,但推荐) -->
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-support</artifactId>
    </dependency>
</dependencies>

步骤 2:生成客户端代码 (推荐)

和第一种方法一样,使用 wsimport 生成客户端代码,并将其放入项目的 src/main/java 目录下,这能让你使用强类型接口,避免手动处理 XML。

步骤 3:配置 WebServiceTemplate

在 Spring Boot 的配置类中,配置一个 WebServiceTemplate Bean。

package com.example.weather.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
@Configuration
public class WeatherWebServiceConfig {
    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // 设置要生成的包名,必须和 wsimport 生成的包名一致
        marshaller.setPackagesToScan("com.example.weather.client");
        return marshaller;
    }
    @Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller) {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        // 设置 WSDL 的地址
        webServiceTemplate.setDefaultUri("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
        // 设置消息转换器
        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.setUnmarshaller(marshaller);
        return webServiceTemplate;
    }
}

步骤 4:创建 Service 层进行调用

创建一个 Service 来封装 WebService 的调用逻辑。

package com.example.weather.service;
import com.example.weather.client.ArrayOfString;
import com.example.weather.client.WeatherWebServiceSoap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WeatherService {
    // 注入由 wsimport 生成的客户端接口
    // 注意:这里不能直接注入 WeatherWebServiceSoap,因为它没有 @Component 注解
    // 我们需要通过另一种方式获取,例如直接 new 一个 Service 实例
    public String getWeather(String city) {
        // 1. 创建服务实例
        com.example.weather.client.WeatherWebService service = new com.example.weather.client.WeatherWebService();
        // 2. 获取端口
        WeatherWebServiceSoap port = service.getWeatherWebServiceSoap();
        // 3. 调用方法
        ArrayOfString result = port.getWeather(city, "");
        // 4. 处理结果
        // 返回的结果是一个字符串列表
        return result.getString().toString();
    }
}

步骤 5:创建 Controller 暴露接口

package com.example.weather.controller;
import com.example.weather.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WeatherController {
    @Autowired
    private WeatherService weatherService;
    @GetMapping("/weather")
    public String getWeather(@RequestParam String city) {
        return weatherService.getWeather(city);
    }
}

你可以启动 Spring Boot 应用,然后访问 http://localhost:8080/weather?city=上海 来获取上海的天气信息。


手动构建 SOAP 请求 (不依赖 WSDL)

如果某些 WebService 没有 WSDL 文件,或者你不想生成客户端代码,可以手动构建 SOAP 请求并发送。

这种方法最灵活,但也最繁琐,需要你了解 SOAP 消息的结构。

示例:调用上面的天气服务

import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
public class ManualWeatherClient extends WebServiceGatewaySupport {
    public String getWeather(String city) {
        // 1. 构建 SOAP 请求体 (XML)
        String soapRequestXml = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "  <soap:Body>\n" +
                "    <getWeather xmlns=\"http://WebXml.com.cn/\">\n" +
                "      <theCityCode>" + city + "</theCityCode>\n" +
                "      <theUserID></theUserID>\n" +
                "    </getWeather>\n" +
                "  </soap:Body>\n" +
                "</soap:Envelope>";
        // 2. 创建 WebServiceTemplate (需要先在配置类中定义)
        // WebServiceTemplate template = getWebServiceTemplate();
        // 3. 发送请求并获取响应
        // 注意:这里直接使用字符串作为请求和响应,需要手动处理 XML
        // 实际项目中,通常会配合 Jaxb2Marshaller 来处理对象和XML的转换
        String response = (String) getWebServiceTemplate().marshalSendAndReceive(
                soapRequestXml,
                new SoapActionCallback("http://WebXml.com.cn/getWeather") // SOAPAction 头
        );
        // 4. 返回响应
        return response;
    }
}

注意:

  • 手动构建 XML 容易出错,且难以维护。
  • 需要仔细阅读 WebService 的文档,了解请求的命名空间、方法名、参数名等。
  • 响应的解析也需要手动进行。

总结与对比

特性 方法一 (JAX-WS wsimport) 方法二 (Spring Boot WebServiceTemplate) 方法三 (手动构建 SOAP)
依赖 JDK 自带,无额外依赖 spring-boot-starter-web-services spring-ws-core
易用性 中等,需要生成代码 ,与 Spring 生态无缝集成 ,繁琐且容易出错
灵活性 低,依赖生成的代码 中等,可以结合手动和自动 ,完全可控
适用场景 简单的 Java 项目、快速原型 现代 Spring Boot 项目 没有 WSDL、需要特殊定制、或学习底层原理
代码风格 传统 Java 调用 现代 Spring 风格 (DI, AOP) 手动处理 XML 字符串

推荐选择:

  • 如果你在使用 Spring Boot,强烈推荐 方法二,它最符合现代开发的习惯,代码清晰、易于维护。
  • 如果你在做一个简单的、非 Spring 的项目,或者只是临时调用一下,方法一 是最快的选择。
  • 只有在万不得已,没有 WSDL 或需要对 SOAP 消息进行精细控制时,才考虑 方法三
分享:
扫描分享到社交APP
上一篇
下一篇