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

如何配置Stub代理消费SOAP服务(javax ws)?开发环境替代第三方服务

太懂这种被第三方服务卡开发进度的痛苦了!我之前做JAX-WS SOAP客户端的时候,也折腾过类似的Stub配置,给你分享几个实用的方案,帮你在开发环境彻底摆脱对第三方应用的依赖:

方法1:用Mockito快速Mock Port接口(最简单高效)

如果你的核心需求只是验证业务逻辑,不需要模拟完整的SOAP消息结构,直接Mock生成的Port接口就完事了。毕竟JAX-WS生成的Port本身就是一个Java接口,Mockito可以直接接管它的方法返回:

// 假设你通过WSDL生成的Port接口是ThirdPartySoapPort
public interface ThirdPartySoapPort extends javax.jws.WebService {
    ResponseData pushData(RequestData request);
}

// 开发环境中Mock这个接口
ThirdPartySoapPort mockPort = Mockito.mock(ThirdPartySoapPort.class);

// 预设你想要的响应结果
ResponseData mockResponse = new ResponseData();
mockResponse.setStatus("SUCCESS");
mockResponse.setMessage("Mocked response from dev stub");

// 指定当调用pushData方法时,不管传入什么参数都返回预设响应
Mockito.when(mockPort.pushData(Mockito.any(RequestData.class))).thenReturn(mockResponse);

// 接下来把这个mockPort注入到你的业务代码里,代替真实的Port即可

如果用Spring的话,还可以结合@Profile注解,让开发环境自动注入Mock实例,生产环境用真实客户端:

@Configuration
public class SoapClientConfig {

    @Bean
    @Profile("dev")
    public ThirdPartySoapPort thirdPartySoapPortDev() {
        ThirdPartySoapPort mockPort = Mockito.mock(ThirdPartySoapPort.class);
        ResponseData mockResponse = new ResponseData();
        mockResponse.setStatus("SUCCESS");
        mockResponse.setMessage("Dev env mock response");
        Mockito.when(mockPort.pushData(Mockito.any(RequestData.class))).thenReturn(mockResponse);
        return mockPort;
    }

    @Bean
    @Profile("prod")
    public ThirdPartySoapPort thirdPartySoapPortProd() {
        // 返回真实的SOAP客户端Port
        return new ThirdPartyService().getThirdPartySoapPort();
    }
}

方法2:通过JAX-WS Stub + 自定义Handler拦截并替换响应(适合模拟完整SOAP消息)

如果需要模拟更真实的SOAP交互(比如要验证SOAP消息的格式、处理Fault场景),可以利用JAX-WS的Stub接口和SOAPHandler来拦截请求并返回自定义的SOAP响应:

// 先获取真实的Port,然后强制转换为Stub(JAX-WS生成的Port默认实现了Stub接口)
ThirdPartySoapPort realPort = new ThirdPartyService().getThirdPartySoapPort();
Stub stub = (Stub) realPort;

// 创建自定义的SOAPHandler,用来替换响应
SOAPHandler<SOAPMessageContext> mockHandler = new SOAPHandler<>() {
    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        // 判断当前是请求( outbound=true)还是响应(outbound=false)方向
        Boolean isOutbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isOutbound) {
            // 拦截响应,替换为我们预设的SOAP消息
            try {
                // 构建Mock的SOAP响应
                SOAPMessage mockSoapResponse = MessageFactory.newInstance().createMessage();
                SOAPBody soapBody = mockSoapResponse.getSOAPBody();
                
                // 根据WSDL定义的响应结构构建内容,这里举个例子:
                QName responseQName = new QName("http://your-thirdparty-namespace.com", "PushDataResponse");
                SOAPElement responseElement = soapBody.addChildElement(responseQName);
                
                SOAPElement statusElement = responseElement.addChildElement("status");
                statusElement.setValue("SUCCESS");
                
                SOAPElement messageElement = responseElement.addChildElement("message");
                messageElement.setValue("Mocked SOAP response from handler");
                
                // 把Mock的消息设置回上下文,替代真实响应
                context.setMessage(mockSoapResponse);
            } catch (SOAPException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        // 如果需要模拟Fault场景,在这里处理即可
        return true;
    }

    @Override
    public void close(MessageContext context) {}

    @Override
    public Set<QName> getHeaders() {
        return Collections.emptySet();
    }
};

// 将Handler添加到Stub的HandlerChain中
List<Handler> handlers = new ArrayList<>();
handlers.add(mockHandler);
stub.setHandlerChain(handlers);

// 现在调用stub的pushData方法,就会返回我们Mock的SOAP响应了

方法3:自定义Mock Service类(适合复杂场景)

如果上面两种方法满足不了你的需求(比如需要模拟不同场景的动态响应),可以自定义一个Mock Service类,继承自WSDL生成的Service类,重写getPort方法返回自己实现的Mock Port:

public class MockThirdPartyService extends ThirdPartyService {
    @Override
    public ThirdPartySoapPort getThirdPartySoapPort() {
        // 返回自定义的Mock Port实现
        return new ThirdPartySoapPort() {
            @Override
            public ResponseData pushData(RequestData request) {
                // 这里可以根据请求参数动态返回不同响应
                if (request.getUserId() == 123) {
                    ResponseData response = new ResponseData();
                    response.setStatus("SUCCESS");
                    response.setMessage("User 123 processed");
                    return response;
                } else {
                    ResponseData response = new ResponseData();
                    response.setStatus("FAILURE");
                    response.setMessage("Invalid user");
                    return response;
                }
            }
        };
    }
}

// 开发环境中使用这个MockService代替真实的Service
ThirdPartySoapPort mockPort = new MockThirdPartyService().getThirdPartySoapPort();

最后小提示

  • 开发环境记得把SOAP客户端的日志打开,方便验证Mock的响应是否符合预期。
  • 如果需要模拟不同的业务场景,可以结合配置文件(比如application-dev.properties)来动态调整Mock响应的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:07:40