跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

JDK9 及以上版本适配 wsimport 生成的 SOAP 代码

介绍在 JDK9 及以上环境(重点验证 JDK17)下,如何适配 wsimport 生成的 SOAP 客户端代码。主要解决因 JDK 移除 com.sun.xml.internal.* 包导致的编译及运行异常。方案包括配置正确的 Maven 依赖(如 spring-ws-core、jaxws-rt),并通过 System.setProperty 显式指定内部实现类路径以覆盖 SPI 默认加载逻辑,最终实现在 Spring 容器中注入并使用 SOAP 服务。

灭霸发布于 2026/3/29更新于 2026/10/24112 浏览

JDK9 及以上版本适配 wsimport 生成的 SOAP 代码

背景

在系统集成场景中,部分遗留系统及第三方服务仍保留 SOAP 接口。尽管 SOAP 协议已逐步被 REST 等轻量级方案替代,但出于兼容性考虑,新系统有时仍需通过 SOAP 协议进行跨系统通信。本文介绍基于 JDK8+ 环境(重点验证 JDK17)的 SOAP 客户端实现方案,解决兼容性问题。

一、wsimport自动生成客户端代码

工具简介
wsimport是 JDK8 内置的命令行工具,核心功能为:解析 SOAP 服务的 WSDL 文档,自动生成可直接调用的 Java 客户端代码。生成内容包括:

  • 请求/响应参数的实体类(XML 与 Java 对象映射)
  • 服务接口(Service 类)及实现类
  • 内置 HTTP 通信、XML 序列化/反序列化逻辑

使用命令

wsimport -encoding UTF-8 -s 存放 Java 代码的本地目录 -p 生成代码的包名 -keep 远程 WSDL 地址 

示例:

wsimport -encoding UTF-8 -s D:\project\springboot-soap-client\src\main\java -p com.example.soap.client.weather -keep http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl 

二、JDK9+(JDK17)适配 wsimport 生成的代码

核心问题
wsimport 生成的类里会包含 javax.xml.bind.annotation.、javax.jws.、javax.xml.ws.*等引用,然而,2019 年 Oracle 将 JavaEE 捐赠给 Eclipse 基金会,Eclipse 将其重命名为 Jakarta EE,并且将所有 API 的包名做了「一刀切」迁移:所有 javax.xxx 全部改为 jakarta.xxx,这就很恶心了。因为一旦引用错误,比如用 3.0.x 的 jakarta 版本会出现包名冲突,反而出问题,使得编译失败!

依赖管理策略
需严格匹配 Jakarta EE 版本与 JDK 兼容性,推荐使用经过验证的依赖组合(以 Maven 为例):

<!-- Spring WebServices 核心:必须加!提供 WebServiceTemplate 和 JAXB2Marshaller -->
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.3.1.RELEASE</version>
    <exclusions>
        <exclusion>
            commons-logging
            commons-logging
        
    



    javax.jws
    javax.jws-api
    1.1



    javax.xml.ws
    jaxws-api
    2.3.1



    com.sun.xml.ws
    jaxws-rt
    2.1.3
    
        
        
            javax.xml.ws
            jaxws-api
        
        
            javax.activation
            activation
        
        
            javax.xml.soap
            saaj-api
        
        
            javax.xml.stream
            stax-api
        
    

<groupId>
</groupId>
<artifactId>
</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- JAX-WS 规范 API 包含 javax.jws.* 全部注解 -->
<dependency>
<groupId>
</groupId>
<artifactId>
</artifactId>
<version>
</version>
</dependency>
<!-- 核心:提供所有 javax.xml.ws.* 完整 API 类,包含 RequestWrapper/ResponseWrapper 等全部缺失类 -->
<dependency>
<groupId>
</groupId>
<artifactId>
</artifactId>
<version>
</version>
</dependency>
<!-- JAX-WS 参考实现(核心,替代 com.sun.xml.internal.ws) -->
<dependency>
<groupId>
</groupId>
<artifactId>
</artifactId>
<version>
</version>
<exclusions>
<!-- 排除冲突的旧版 API -->
<exclusion>
<groupId>
</groupId>
<artifactId>
</artifactId>
</exclusion>
<exclusion>
<groupId>
</groupId>
<artifactId>
</artifactId>
</exclusion>
<exclusion>
<groupId>
</groupId>
<artifactId>
</artifactId>
</exclusion>
<exclusion>
<groupId>
</groupId>
<artifactId>
</artifactId>
</exclusion>
</exclusions>
</dependency>

三、修复找不到 com.sun.xml.internal.* 包以及 ServiceSoap 远程访问的部分异常

问题原因

  1. JDK17 彻底删除了所有 com.sun.xml.internal.* 包;
  2. 引入的独立依赖包(jaxws-rt/saaj-impl/jaxb-impl)里,所有类的包名都去掉了 internal;
  3. JAX-WS/SAAJ/JAXB 底层会通过「系统 SPI 机制」读取默认的类路径,而默认读取的还是带 internal 的旧路径,导致持续报类找不到。

解决方案
通过代码显式指定 Jakarta 实现类,覆盖默认 SPI 加载逻辑:

@Configuration
public class WebServiceConfig {
    // ============ 核心:JDK17 一站式修正 所有 com.sun.xml.internal.* → com.sun.xml.* 路径 ============
    static {
        // 1. 修复 JAX-WS ProviderImpl 路径:internal 移除
        System.setProperty("javax.xml.ws.spi.Provider", "com.sun.xml.ws.spi.ProviderImpl");
        // 2. 修复 JAXB ContextFactory 路径:internal 移除
        System.setProperty("javax.xml.bind.context.factory", "com.sun.xml.bind.v2.ContextFactory");
        // 3. 修复 SAAJ MetaFactoryImpl 路径:internal 移除【解决你当前的新报错 核心配置】
        System.setProperty("javax.xml.soap.MetaFactory", "com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl");
        // 4. 修复 SAAJ MessageFactory 路径:internal 移除
        System.setProperty("javax.xml.soap.MessageFactory", "com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl");
        // 5. 修复 SAAJ SOAPFactory 路径:internal 移除
        System.setProperty("javax.xml.soap.SOAPFactory", "com.sun.xml.messaging.saaj.soap.ver1_1.SOAPFactory1_1Impl");
    }

    /**
     * 注册 ServiceSoap 代理 Bean 到 Spring 容器
     */
    @Bean
    public ServiceSoap xxxServiceSoap() {
        try {
            URL wsdlUrl = new URL("https://你的 WSDL 地址?wsdl");
            Service service = new Service(wsdlUrl);
            ServiceSoap serviceSoap = service.getServiceSoap();
            BindingProvider bindingProvider = (BindingProvider) serviceSoap;
            // 获取请求上下文
            Map<String, Object> requestContext = bindingProvider.getRequestContext();
            // 防止请求发送到的 URL 地址不对问题
            requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://你的 WSDL 地址");
            // 设置连接超时(单位:毫秒)
            requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 5000);
            // 设置读取超时(单位:毫秒)
            requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 10000);
            Map<String, List<String>> headers = new HashMap<>();
            // 防止 Unsupported Content-Type: text/html Supported ones are: [text/xml] 错误
            headers.put("Content-Type", Collections.singletonList("text/xml;charset=UTF-8"));
            bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
            return serviceSoap;
        } catch (Exception e) {
            throw new RuntimeException("初始化 ServiceSoap 失败", e);
        }
    }
}

四、注入使用

使用方式如同正常的 Bean,在你自己的 service 方法里,使用

@Resource // 或@Autowired 都可以,此时 Bean 已正确初始化并指定了真实地址
private ServiceSoap xxxServiceSoap;

,并在方法里通过 xxxServiceSoap.xxxfunction(param) 即可。

目录

  1. JDK9 及以上版本适配 wsimport 生成的 SOAP 代码
  2. 背景
  3. 一、wsimport自动生成客户端代码
  4. 二、JDK9+(JDK17)适配 wsimport 生成的代码
  5. 三、修复找不到 com.sun.xml.internal.* 包以及 ServiceSoap 远程访问的部分异常
  6. 四、注入使用

更多推荐文章

查看全部
  • Java 阻塞队列原理及生产者 - 消费者模型应用
  • AIGC 实战测评:通义万相 2.1 图生视频部署指南
  • 热门 5 个 AI 视频工具盘点及收费说明
  • 基于 Atlas 300I Duo 推理卡使用 MindIE 和 WebUI 运行 32B 大语言模型
  • DeepSeek-R1-Distill-Llama-8B 实操指南:Ollama 模型 HTTP API 鉴权与访问控制
  • Claude Code 中 CLAUDE.md 的加载时机与书写最佳实践
  • 基于 Scrapy 的论坛帖子内容抓取实战教程
  • JavaSE 多线程:阻塞队列原理与实现
  • Linux 上通过 Docker 快速部署 Dify
  • Trae 集成图片素描 MCP 工具实现多风格转换
  • WhisperX 语音识别实战:从安装到说话人分离
  • C++ 异常处理机制详解
  • Python EXE 解包工具实战:py2exe 与 pyinstaller 逆向
  • 多种编程语言数组遍历实现对比
  • Telegram 搜索机器人搭建指南(含 Python 脚本)
  • 50 道前端进阶面试题:HTML/CSS/JS/Vue/React/TS/工程化/网络/跨端
  • PySide6 QtSerialPort 库串口通信开发指南
  • Stable Diffusion 3.5 FP8 镜像部署与量化技术详解
  • OpenClaw 新手入门:环境搭建、模型配置与远程访问
  • 软考上午题高频真题汇总:前端备考指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online