杰瑞科技汇

Java webservice调用如何实现?

目录

  1. WebService 简介
    • SOAP (Simple Object Access Protocol)
    • REST (Representational State Transfer)
  2. 调用 SOAP WebService 的方法
    • 使用 JDK 自带的 wsimport 工具 (最传统)
    • 使用 Apache CXF 框架 (更强大、更灵活)
    • 使用 Spring Boot + CXF (企业级应用首选)
  3. 调用 RESTful WebService (Web API) 的方法
    • 使用 java.net.HttpURLConnection (原生,不推荐)
    • 使用 Apache HttpClient (业界标准)
    • 使用 OkHttp (轻量级,流行)
    • 使用 Spring Boot RestTemplate (经典、便捷)
    • 使用 Spring Boot WebClient (响应式、现代)
  4. 总结与对比

WebService 简介

WebService 是一种跨编程语言和跨操作系统的远程调用技术,允许不同应用通过网络进行交互,主要有两种风格:

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

SOAP (Simple Object Access Protocol)

  • 特点:
    • 是一个协议,有严格的规范(如 WSDL, SOAP Header, SOAP Body)。
    • 基于 XML 进行数据交换,格式非常严谨、冗长。
    • 通常运行在 HTTP/HTTPS 上,但也可以使用 SMTP 等协议。
    • 具有内置的安全事务支持。
    • 耦合度高,客户端和服务端必须严格遵守契约(WSDL)。
  • 场景: 传统的企业级应用(如银行、政府、电信系统),对安全性、事务性要求高的场景。

REST (Representational State Transfer)

  • 特点:
    • 是一种架构风格,而不是一个协议。
    • 基于 HTTP 协议,利用其方法(GET, POST, PUT, DELETE)。
    • 数据交换格式通常使用轻量级的 JSON 或 XML。
    • 无状态,每次请求都包含处理该请求所需的所有信息。
    • 耦合度低,非常灵活,是现代 Web 和移动应用后端服务的标准。
  • 场景: 几乎所有现代 Web 应用、移动 App、微服务架构,我们通常称之为 "Web API"。

调用 SOAP WebService 的方法

假设我们要调用一个天气预报的 SOAP WebService,其 WSDL 地址为 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

使用 JDK 自带的 wsimport 工具 (最传统)

这是最基础的方法,不需要引入第三方库。

步骤 1: 生成客户端代码

打开命令行,执行以下命令,这会根据 WSDL 文件生成一系列 Java 源文件和 class 文件。

Java webservice调用如何实现?-图2
(图片来源网络,侵删)
# -keep: 生成源代码
# -d: 指定 class 文件输出目录
# -p: 指定包名
wsimport -keep -d . -p com.example.weather http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

执行后,你会得到 com.example.weather 包下的 WeatherWebServiceWeatherWebServiceSoapArrayOfString 等类。

步骤 2: 编写 Java 代码调用

import com.example.weather.ArrayOfString;
import com.example.weather.WeatherWebService;
import com.example.weather.WeatherWebServiceSoap;
public class WeatherClient {
    public static void main(String[] args) {
        // 1. 创建服务视图对象 (WeatherWebService)
        WeatherWebService service = new WeatherWebService();
        // 2. 获取服务端点接口 (WeatherWebServiceSoap)
        WeatherWebServiceSoap soap = service.getWeatherWebServiceSoap();
        // 3. 调用具体的方法,传入参数
        // 查询北京、上海、广州的天气
        ArrayOfString result = soap.getWeather("北京,上海,广州", "");
        // 4. 处理返回结果
        if (result != null && result.getString() != null) {
            for (String s : result.getString()) {
                System.out.println(s);
            }
        }
    }
}

优点:

  • 无需额外依赖,JDK 自带。
  • 简单直接。

缺点:

Java webservice调用如何实现?-图3
(图片来源网络,侵删)
  • 功能有限,不支持 WS-Security 等高级特性。
  • 生成的代码有时会比较冗余。

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

CXF 是一个开源的 Services 框架,支持 SOAP 和 RESTful 服务。

步骤 1: 添加 Maven 依赖

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

步骤 2: 使用 CXF 的 wsdl2java 工具生成客户端代码

CXF 也提供了类似的工具,功能更强大。

# -client: 生成客户端测试代码
wsdl2java -client -p com.example.cxf.weather http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

步骤 3: 编写 Java 代码调用

CXF 生成的代码通常有更清晰的客户端工厂类。

import com.example.cxf.weather.WeatherWebService;
import com.example.cxf.weather.WeatherWebServiceService;
public class CxfWeatherClient {
    public static void main(String[] args) {
        // 1. 通过工厂类创建服务
        WeatherWebServiceService service = new WeatherWebServiceService();
        // 2. 获取服务端口
        WeatherWebService port = service.getWeatherWebServiceSoap();
        // 3. 调用方法
        String city = "北京";
        // 注意:CXF 生成的参数类型可能与原生 wsimport 不同,需要查看生成的代码
        java.util.List<String> result = port.getWeather(city, "").getString();
        // 4. 处理结果
        System.out.println("北京的天气信息:");
        result.forEach(System.out::println);
    }
}

优点:

  • 功能强大,支持 WS-* 标准(安全、事务等)。
  • 可与 Spring 框架无缝集成。
  • 性能更好,可配置性更高。

使用 Spring Boot + CXF (企业级应用首选)

这是在 Spring Boot 项目中集成 SOAP 服务的标准做法。

步骤 1: 创建 Spring Boot 项目,添加 CXF 依赖

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>3.4.5</version>
</dependency>

步骤 2: 创建一个客户端配置类

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WeatherClientConfig {
    @Bean
    public WeatherWebService weatherWebServiceClient() {
        // 1. 创建工厂
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 2. 设置服务接口 (wsdl 中定义的)
        factory.setServiceClass(com.example.weather.WeatherWebService.class);
        // 3. 设置 WSDL 地址
        factory.setAddress("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
        // 4. 创建并返回客户端代理对象
        return (WeatherWebService) factory.create();
    }
}

注意:这里的 com.example.weather.WeatherWebService 是用 wsdl2java 工具生成的接口。

步骤 3: 创建 Service 层调用

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.weather.ArrayOfString;
import com.example.weather.WeatherWebService;
@Service
public class WeatherService {
    @Autowired
    private WeatherWebService weatherWebService;
    public void getWeatherInfo(String cityName) {
        System.out.println("正在查询 " + cityName + " 的天气...");
        ArrayOfString result = weatherWebService.getWeather(cityName, "");
        if (result != null && result.getString() != null) {
            result.getString().forEach(System.out::println);
        }
    }
}

优点:

  • 完全融入 Spring 生态,依赖注入、事务管理等都可以使用。
  • 代码结构清晰,易于维护和测试。
  • 企业级应用的最佳实践。

调用 RESTful WebService (Web API) 的方法

假设我们要调用一个公共的 IP 地址查询 API:http://ip-api.com/json/8.8.8.8?fields=status,message,country,city,query,它会返回一个 JSON 对象。

使用 Spring Boot RestTemplate (经典、便捷)

RestTemplate 是 Spring 框架提供的用于同步 HTTP 请求的客户端,非常经典和方便。

步骤 1: 在 Spring Boot 启动类上添加 @EnableRestTemplate

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);
    }
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

步骤 2: 创建 Service 调用

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
// 定义一个与返回 JSON 结构对应的 Java 类
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略 JSON 中存在但 Java 类中没有的字段
class IpInfo {
    private String status;
    private String country;
    private String city;
    private String query;
    // Getters and Setters...
}
@Service
public class IpApiService {
    @Autowired
    private RestTemplate restTemplate;
    public void getIpInfo() {
        String url = "http://ip-api.com/json/8.8.8.8?fields=status,message,country,city,query";
        // 使用 getForObject 方法,直接将 JSON 映射到 IpInfo 对象
        IpInfo ipInfo = restTemplate.getForObject(url, IpInfo.class);
        if (ipInfo != null && "success".equals(ipInfo.getStatus())) {
            System.out.println("查询成功!");
            System.out.println("IP: " + ipInfo.getQuery());
            System.out.println("国家: " + ipInfo.getCountry());
            System.out.println("城市: " + ipInfo.getCity());
        } else {
            System.out.println("查询失败: " + (ipInfo != null ? ipInfo.getMessage() : "未知错误"));
        }
    }
}

优点:

  • Spring 生态核心,使用极其广泛。
  • API 设计简洁,支持 GET, POST, PUT, DELETE 等各种方法。
  • 自动将 JSON/XML 转换为 Java 对象(反序列化),反之亦然(序列化)。

缺点:

  • 在 Spring Boot 2.4 之后,官方已标记为不推荐使用,建议迁移到 WebClient

使用 Spring Boot WebClient (响应式、现代)

WebClient 是 Spring 5 引入的、基于响应式编程的非阻塞 HTTP 客户端,是 RestTemplate 的替代品。

步骤 1: 创建 WebClient 实例

通常使用 WebClient.create() 静态方法。

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class WebClientIpApiService {
    // 创建一个可重用的 WebClient 实例
    private final WebClient webClient;
    public WebClientIpApiService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("http://ip-api.com").build();
    }
    public void getIpInfo() {
        String ip = "8.8.8.8";
        String path = "/json/" + ip;
        String fields = "status,message,country,city,query";
        // 定义响应式流
        Mono<IpInfo> ipInfoMono = this.webClient.get()
                .uri(uriBuilder -> uriBuilder.path(path).queryParam("fields", fields).build())
                .retrieve() // 发出请求并获取响应
                .bodyToMono(IpInfo.class); // 将响应体反序列化为 IpInfo 对象,并包装在 Mono 中
        // 订阅 Mono 并处理结果
        ipInfoMono.subscribe(
                ipInfo -> {
                    if ("success".equals(ipInfo.getStatus())) {
                        System.out.println("WebClient 查询成功!");
                        System.out.println("IP: " + ipInfo.getQuery());
                        System.out.println("国家: " + ipInfo.getCountry());
                        System.out.println("城市: " + ipInfo.getCity());
                    }
                },
                error -> System.err.println("WebClient 查询出错: " + error.getMessage())
        );
        // 因为 WebClient 是非阻塞的,主线程可能先于响应结束
        // 在实际应用中,通常会阻塞等待或在 WebFlux 环境中处理
        try {
            Thread.sleep(1000); // 简单等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

注意:IpInfo 类和 RestTemplate 示例中一样。

优点:

  • 非阻塞,性能更高,能更好地利用系统资源,适合高并发场景。
  • 响应式编程,提供了更灵活的数据流处理能力(Mono, Flux)。
  • 是 Spring 官方推荐的未来方向。

缺点:

  • 学习曲线比 RestTemplate 陡峭,需要理解响应式编程。
  • 对于简单的同步调用,代码可能显得更复杂。

总结与对比

特性 SOAP (wsimport/CXF) REST (RestTemplate) REST (WebClient)
风格 协议,严格 架构风格,灵活 架构风格,灵活
数据格式 XML (严格) JSON/XML (轻量) JSON/XML (轻量)
协议 HTTP/SMTP/等 HTTP HTTP
状态 无/有状态 无状态 无状态
主要场景 传统企业应用,高安全/事务要求 大部分 Java Web 应用 高并发、微服务、响应式应用
易用性 中等 (需生成代码) (非常简单) 中等 (需学习响应式)
性能 同步,较低 同步,中等 异步非阻塞,高
官方推荐 - 不推荐 (已弃用) 推荐

如何选择?

  • 如果你的服务是 SOAP 协议的:

    • 新项目,强烈推荐使用 Spring Boot + CXF,因为它结构最清晰,最易于维护。
    • 简单的、一次性的调用,可以使用 wsimport
  • 如果你的服务是 RESTful API 的:

    • 如果你还在使用 Spring Boot 2.3 或更早版本,或者项目简单RestTemplate 是一个非常成熟和方便的选择。
    • 如果你在开发新项目,特别是高并发或微服务项目:请直接学习并使用 WebClient,它是未来的趋势。

希望这份详细的指南能帮助你掌握在 Java 中调用 WebService 的各种方法!

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