You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring环境调用SOAP服务报错:无法定位有效EngineConfigurationFactory

问题分析与解决方案

你遇到的空指针异常,根源是Apache Axis这个旧框架和新的Spring Boot 2环境兼容性不匹配。Axis在Spring Boot的类加载机制下,找不到它需要的EngineConfigurationFactory实现类,导致初始化Service时抛出NPE。既然不想生成Stub,而且所有服务方法都返回字节数组,推荐你用以下两种更适配当前技术栈的简易方案:

方案一:用Spring WebServiceTemplate(推荐,贴合Spring生态)

Spring自带的WebServiceTemplate可以直接构造SOAP请求并调用服务,无需生成Stub。步骤如下:

1. 添加Gradle依赖

implementation 'org.springframework.boot:spring-boot-starter-web-services'

2. 配置WebServiceTemplate Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.http.HttpUrlConnectionMessageSender;

@Configuration
public class SoapClientConfig {

    @Bean
    public WebServiceTemplate webServiceTemplate() {
        WebServiceTemplate template = new WebServiceTemplate();
        // 设置HTTP消息发送器
        template.setMessageSender(new HttpUrlConnectionMessageSender());
        // 配置SOAP服务的端点地址
        template.setDefaultUri("http://docsystem.intra.com:18080/documents/services");
        return template;
    }
}

3. 编写调用逻辑

import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import org.springframework.ws.soap.saaj.SaajSoapMessage;

import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@Service
public class DocumentSoapClient {

    private final WebServiceTemplate webServiceTemplate;

    // 构造注入WebServiceTemplate
    public DocumentSoapClient(WebServiceTemplate webServiceTemplate) {
        this.webServiceTemplate = webServiceTemplate;
    }

    public byte[] callService(String methodName, Object... params) throws SOAPException, IOException {
        // 创建SOAP请求消息
        SaajSoapMessage request = (SaajSoapMessage) webServiceTemplate.createWebServiceMessage();
        SOAPBody soapBody = request.getSaajMessage().getSOAPBody();

        // 构造请求元素(注意替换成实际的命名空间和方法参数)
        SOAPElement requestElement = soapBody.addChildElement(methodName, "", "http://server.priv.doc/");
        // 添加方法参数(根据实际需求调整)
        for (int i = 0; i < params.length; i++) {
            SOAPElement param = requestElement.addChildElement("param" + (i + 1));
            param.setValue(params[i].toString());
        }

        // 发送请求并获取响应
        SaajSoapMessage response = (SaajSoapMessage) webServiceTemplate.sendAndReceive(
                request,
                new SoapActionCallback("http://server.priv.doc/" + methodName)
        );

        // 将响应转为字节数组返回
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        response.writeTo(outputStream);
        return outputStream.toByteArray();
    }
}

方案二:用原生HTTP客户端(轻量无额外依赖)

如果不想引入Spring WS的依赖,也可以直接用Java原生的HttpURLConnection发送SOAP请求,手动构造SOAP信封:

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class SimpleSoapClient {

    public byte[] callSoapService(String endpoint, String methodName, String namespace) throws Exception {
        // 构造SOAP信封(根据实际WSDL调整参数部分)
        String soapEnvelope = String.format(
                "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"%s\">" +
                "   <soapenv:Header/>" +
                "   <soapenv:Body>" +
                "       <ser:%s>" +
                "           <!-- 这里添加你的方法参数,比如 <ser:documentId>123</ser:documentId> -->" +
                "       </ser:%s>" +
                "   </soapenv:Body>" +
                "</soapenv:Envelope>",
                namespace, methodName, methodName
        );

        // 建立HTTP连接
        URL url = new URL(endpoint);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
        connection.setRequestProperty("SOAPAction", namespace + methodName);
        connection.setDoOutput(true);

        // 发送SOAP请求
        connection.getOutputStream().write(soapEnvelope.getBytes("UTF-8"));

        // 读取响应字节
        InputStream inputStream = connection.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }

        // 关闭资源
        inputStream.close();
        connection.disconnect();

        return outputStream.toByteArray();
    }

    // 使用示例
    public static void main(String[] args) throws Exception {
        SimpleSoapClient client = new SimpleSoapClient();
        byte[] result = client.callSoapService(
                "http://docsystem.intra.com:18080/documents/services",
                "getDocument", // 替换为实际方法名
                "http://server.priv.doc/"
        );
        // 处理返回的字节数组
    }
}

为什么旧的Axis代码不能用了?

旧项目中的Axis依赖可能完整包含了配置工厂的实现,但在Spring Boot 2环境下,要么是依赖冲突导致Axis的配置类被覆盖,要么是类加载顺序问题让Axis找不到所需的实现类,最终触发NPE。放弃旧的Axis框架,改用更适配现代Spring环境的方式,是更稳定的选择。

内容的提问来源于stack exchange,提问作者tomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:31:23