杰瑞科技汇

Java如何接收WebService?

  1. JAX-WS (Java API for XML Web Services):这是目前最主流、最标准的Java官方技术,用于创建和消费SOAP (Simple Object Access Protocol) 类型的WebService,它通常与WSDL (Web Services Description Language) 文件紧密关联。
  2. JAX-RS (Java API for RESTful Web Services):这是用于创建和消费RESTful Web Services的Java API,它基于HTTP协议,使用JSON或XML作为数据格式,更轻量、更灵活,是目前Web开发的首选。
  3. Axis2 / CXF 等框架:这些是功能强大的第三方WebService框架,它们也支持SOAP和REST,提供了比标准JAX-WS/JAX-RS更丰富的功能和更灵活的配置。

下面我将分别详细介绍这三种方式,并提供最常用和最推荐的代码示例。

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

使用 JAX-WS (消费 SOAP WebService)

这是最经典和标准的方式,适用于企业级的、基于SOAP协议的WebService,消费WebService的核心步骤是:

  1. 获取WSDL文件:WSDL是WebService的“说明书”,描述了服务提供哪些方法、方法参数、返回值以及如何访问。
  2. 生成客户端代码:使用wsimport工具(JDK自带)根据WSDL文件生成Java客户端代码(包括接口、实体类等)。
  3. 调用服务:在Java代码中像调用本地方法一样,调用生成的接口来远程调用WebService。

详细步骤与示例

假设我们要调用一个提供查询天气信息的SOAP WebService,其WSDL地址为:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

第1步:生成客户端代码

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

Java如何接收WebService?-图2
(图片来源网络,侵删)
# -p: 指定生成的包名
# -d: 指定代码生成的目录
# -keep: 生成后保留源文件
# -verbose: 显示详细过程
wsimport -p com.example.weather.client -d ./src/main/java -keep -verbose http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

执行成功后,你会在com.example.weather.client包下看到一系列生成的Java文件,其中最重要的是WeatherWSSoap接口(或类似名称,具体取决于WSDL定义)。

第2步:编写Java代码调用服务

生成的代码中会包含一个WeatherWS(或类似名称)的服务工厂类,我们可以用它来获取服务端口(Port),然后调用方法。

import com.example.weather.client.WeatherWS;
import com.example.weather.client.WeatherWSImplService;
import com.example.weather.client.ArrayOfString;
public class JaxWsClientExample {
    public static void main(String[] args) {
        // 1. 创建服务工厂实例
        // WeatherWSImplService 是 wsimport 生成的工厂类
        WeatherWSImplService factory = new WeatherWSImplService();
        // 2. 获取服务端口
        // WeatherWSSoap 是 wsimport 生成的接口,包含了所有可用的方法
        WeatherWS weatherWS = factory.getWeatherWSSoap();
        // 3. 调用WebService方法
        // 假设该方法接收城市名,返回一个字符串数组
        String city = "北京";
        ArrayOfString result = weatherWS.getWeatherbyCityName(city);
        // 4. 处理返回结果
        System.out.println("查询城市: " + city);
        if (result != null && result.getString() != null) {
            for (String info : result.getString()) {
                System.out.println(info);
            }
        } else {
            System.out.println("未能获取天气信息。");
        }
    }
}

关键点:

Java如何接收WebService?-图3
(图片来源网络,侵删)
  • WeatherWSImplService:这是服务工厂类,用于创建服务的客户端实例。
  • WeatherWS (或 WeatherWSSoap):这是核心接口,定义了所有可以远程调用的方法,你只需要像调用普通Java方法一样调用它即可,底层的SOAP请求和响应会由JAX-WS框架自动处理。

使用 JAX-RS (消费 RESTful WebService)

RESTful WebService基于HTTP,通常返回JSON数据,在现代Java开发中,消费REST服务最流行和推荐的方式是使用 Spring Framework 的 RestTemplate (Spring 5之前) 或 WebClient (Spring 5及之后,推荐,响应式编程)。

示例1:使用 Spring RestTemplate (传统同步方式)

假设我们要调用一个公共的REST API获取IP地址的归属地信息: http://ip-api.com/json/8.8.8.8

第1步:添加Spring Boot依赖

确保你的pom.xml中包含了spring-boot-starter-web,它已经包含了RestTemplate

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

第2步:配置并使用 RestTemplate

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@Configuration
public class RestTemplateConfig {
    // 在Spring Boot应用中,推荐通过这种方式定义Bean
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}
// 在你的Service或Controller中使用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class IpLocationService {
    @Autowired
    private RestTemplate restTemplate;
    public String getIpLocation(String ip) {
        // 1. 定义API的URL
        String url = "http://ip-api.com/json/{ip}";
        // 2. 发送GET请求,并直接将响应体映射为String
        // RestTemplate会自动处理HTTP连接和JSON转换
        String response = restTemplate.getForObject(url, String.class, ip);
        // 3. 处理响应
        System.out.println("API Response: " + response);
        return response;
    }
}
// 更高级的用法:将JSON自动映射到Java对象
// 假设API返回的JSON是 {"status":"success","country":"United States","city":"Mountain View"...}
// 我们可以创建一个对应的Java类 IpLocationInfo.java
// 
// IpLocationInfo info = restTemplate.getForObject(url, IpLocationInfo.class, ip);

示例2:使用 Spring WebClient (现代异步响应式方式)

WebClient是Spring 5引入的,支持非阻塞、响应式编程,性能更高,是未来的趋势。

第1步:添加依赖

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

第2步:配置并使用 WebClient

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient(WebClient.Builder builder) {
        return builder.baseUrl("http://ip-api.com").build();
    }
}
// 在你的Service或Controller中使用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class IpLocationServiceWithWebClient {
    @Autowired
    private WebClient webClient;
    public Mono<String> getIpLocationAsync(String ip) {
        return webClient.get()
                .uri("/json/{ip}", ip) // 构建URI
                .retrieve() // 获取响应
                .bodyToMono(String.class); // 将响应体转换为Mono<String>
    }
    // 在Controller中调用
    // public Mono<String> getLocation(@PathVariable String ip) {
    //     return ipLocationServiceWithWebClient.getIpLocationAsync(ip);
    // }
}

使用 Apache CXF (消费 SOAP WebService)

CXF是一个功能强大的开源框架,它也支持SOAP,如果你对JAX-WS生成的代码不满意,或者需要更高级的特性(如WS-Security),可以使用CXF。

CXF消费SOAP服务通常有两种方式:

  1. 从WSDL生成客户端:和JAX-WS类似,使用CXF提供的wsdl2java工具。
  2. 手动创建客户端:不依赖WSDL,手动构建SOAP请求,这种方式更灵活但也更复杂。

示例:使用CXF从WSDL生成客户端并调用

第1步:添加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>

第2步:使用 wsdl2java 生成客户端

CXF也提供了wsdl2java工具,通常在cxf-x.x.x/bin目录下。

# -p: 包名
# -d: 输出目录
# -client: 生成客户端启动类(可选)
wsdl2java -p com.example.cxf.client -d ./src/main/java -keep http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

第3步:编写Java代码调用

生成的代码和使用方式与JAX-WS非常相似,因为CXF本身就是JAX-WS的一个实现。

import com.example.cxf.client.WeatherWS;
import com.example.cxf.client.WeatherWSImplService;
public class CxfClientExample {
    public static void main(String[] args) {
        // 创建服务工厂
        WeatherWSImplService factory = new WeatherWSImplService();
        // 获取服务端点
        WeatherWS weatherWS = factory.getWeatherWSSoap();
        // 调用方法
        String city = "上海";
        ArrayOfString result = weatherWS.getWeatherbyCityName(city);
        // 处理结果
        System.out.println("查询城市: " + city);
        if (result != null && result.getString() != null) {
            result.getString().forEach(System.out::println);
        }
    }
}

总结与对比

特性 JAX-WS (SOAP) JAX-RS (REST) Apache CXF (SOAP)
协议 SOAP (XML) HTTP (JSON/XML) SOAP (XML)
数据格式 XML JSON (主流), XML XML
核心工具 wsimport RestTemplate, WebClient wsdl2java
适用场景 企业级应用、金融、电信等对安全、事务要求高的场景 Web应用、移动后端、微服务,追求高性能和灵活性 复杂SOAP服务、需要高级WS-*特性(如安全)的场景
优点 标准化、功能强大(WS-Security, WS-Addressing等)、严格 轻量、简单、基于HTTP、易于缓存和扩展 功能强大、灵活、支持多种协议和数据绑定
缺点 协议复杂、冗余、性能相对较低 无统一标准,功能取决于实现 配置相对复杂,学习曲线稍陡

如何选择?

  • 如果服务是SOAP类型:直接使用 JAX-WS,因为它是Java标准,简单直接,如果需要JAX-WS不支持的复杂特性(如WS-Security),再考虑 CXF
  • 如果服务是RESTful类型:毫无疑问选择 JAX-RS,在Spring生态中,优先使用 WebClient(新项目),RestTemplate(旧项目或简单同步场景)仍然可用。
  • 如果不确定:优先考虑 RESTful (JAX-RS),因为它更符合现代Web开发的趋势,更简单高效。
分享:
扫描分享到社交APP
上一篇
下一篇