Spring Boot中调用SOAP XML Web Service的最佳方法咨询
基于Spring Boot的SOAP XML Web服务调用最佳方案
结合你已生成JAXB类的情况,推荐以下三种落地方案,按Spring生态适配度排序:
方案一:Spring WebServices(官方集成首选)
Spring WS是Spring生态下的SOAP服务客户端工具,和JAXB天然适配,配置简洁,适合Spring Boot项目。
1. 引入依赖
在pom.xml中添加Spring WS starter及JAXB依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency>
2. 配置核心模板与Marshaller
创建配置类,指定JAXB类的包路径(需包含Header和Body对应的生成类):
@Configuration public class SoapClientConfig { @Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); // 替换为你生成的JAXB类实际包路径 marshaller.setContextPaths( "com.bi.service.entity.message._2003", "com.bi.service.provider.bi.biService.findBIDoc._2003" ); return marshaller; } @Bean public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller) { WebServiceTemplate template = new WebServiceTemplate(); template.setMarshaller(marshaller); template.setUnmarshaller(marshaller); // 设置目标SOAP服务端点地址 template.setDefaultUri("http://your-actual-soap-endpoint"); return template; } }
3. 编写客户端调用逻辑
封装服务调用,手动注入SOAP Header(对应你Postman示例中的BIContext):
@Service public class BIDocSoapClient { private final WebServiceTemplate webServiceTemplate; // 构造注入模板 public BIDocSoapClient(WebServiceTemplate webServiceTemplate) { this.webServiceTemplate = webServiceTemplate; } public FindBIDocResponse invokeFindBIDoc() { // 构造请求Body FindBIDocRequest request = new FindBIDocRequest(); request.setVersion(new Version("13")); request.setDocNumber("789999"); request.setUserId("test"); request.setReadOnly(true); // 构造请求Header BIContext biContext = new BIContext(); biContext.setMessageId("89"); biContext.setCreationTimestamp(OffsetDateTime.parse("2018-07-27T03:56:56.449Z")); biContext.setHostName("localhost"); // 发送请求并注入Header return (FindBIDocResponse) webServiceTemplate.marshalSendAndReceive( request, message -> { SoapMessage soapMsg = (SoapMessage) message; webServiceTemplate.getMarshaller().marshal(biContext, soapMsg.getSoapHeader().getResult()); } ); } }
方案二:Apache CXF(高自定义需求首选)
如果需要拦截器、安全认证等高级自定义功能,Apache CXF是更灵活的选择,Spring Boot集成也很方便。
1. 引入依赖
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.6.2</version> <!-- 选择与Spring Boot版本兼容的版本 --> </dependency>
2. 生成客户端接口(可选)
用CXF的wsdl2java工具生成客户端代码(若已有JAXB类,可跳过直接手动定义接口):
wsdl2java -p com.bi.service.client -d src/main/java your-service.wsdl
3. 配置CXF客户端与Header拦截器
@Configuration public class CxfClientConfig { @Bean public FindBIDocService findBIDocService() { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(FindBIDocService.class); // 生成的客户端接口 factory.setAddress("http://your-actual-soap-endpoint"); // 添加自定义Header拦截器 factory.getOutInterceptors().add(new BIContextHeaderInterceptor()); return (FindBIDocService) factory.create(); } // 自定义SOAP Header拦截器 private static class BIContextHeaderInterceptor extends AbstractSoapInterceptor { public BIContextHeaderInterceptor() { super(Phase.PREPARE_SEND); } @Override public void handleMessage(SoapMessage message) throws Fault { try { BIContext biContext = new BIContext(); biContext.setMessageId("89"); biContext.setCreationTimestamp(OffsetDateTime.parse("2018-07-27T03:56:56.449Z")); biContext.setHostName("localhost"); JAXBContext jaxbContext = JAXBContext.newInstance(BIContext.class); jaxbContext.createMarshaller().marshal(biContext, message.getHeader().getResult()); } catch (JAXBException e) { throw new Fault(new RuntimeException("Header序列化失败", e)); } } } }
4. 调用服务
@Service public class BIDocCxfClient { private final FindBIDocService findBIDocService; public BIDocCxfClient(FindBIDocService findBIDocService) { this.findBIDocService = findBIDocService; } public FindBIDocResponse getBIDoc() { FindBIDocRequest request = new FindBIDocRequest(); request.setVersion(new Version("13")); request.setDocNumber("789999"); request.setUserId("test"); request.setReadOnly(true); return findBIDocService.findBIDoc(request); } }
方案三:原生JAX-WS(无框架依赖)
若不想引入任何第三方框架,可直接使用JDK自带的JAX-WS API,适合简单场景快速验证。
1. 生成客户端代码
用JDK自带的wsimport工具生成客户端:
wsimport -p com.bi.service.client -keep your-service.wsdl
2. 原生调用实现
public class NativeSoapClient { public static void main(String[] args) { // 初始化服务与端口 FindBIDocService service = new FindBIDocService(); FindBIDocPortType port = service.getFindBIDocPort(); // 设置端点地址 BindingProvider bindingProvider = (BindingProvider) port; bindingProvider.getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://your-actual-soap-endpoint" ); // 构造并注入Header try { BIContext biContext = new BIContext(); biContext.setMessageId("89"); biContext.setCreationTimestamp(OffsetDateTime.parse("2018-07-27T03:56:56.449Z")); biContext.setHostName("localhost"); JAXBContext jaxbContext = JAXBContext.newInstance(BIContext.class); Marshaller marshaller = jaxbContext.createMarshaller(); StringWriter writer = new StringWriter(); marshaller.marshal(biContext, writer); List<Header> headers = new ArrayList<>(); headers.add(new Header( new QName("http://service.bi.com/entity/message/2003/", "BIContext"), writer.toString() )); bindingProvider.getRequestContext().put(JAXWSProperties.HTTP_HEADERS, headers); } catch (JAXBException e) { e.printStackTrace(); } // 构造请求并调用 FindBIDocRequest request = new FindBIDocRequest(); request.setVersion(new Version("13")); request.setDocNumber("789999"); request.setUserId("test"); request.setReadOnly(true); FindBIDocResponse response = port.findBIDoc(request); // 处理响应逻辑 } }
关键注意事项
- 确认JAXB类的包路径与Marshaller配置一致,避免序列化失败
- 替换所有
http://your-actual-soap-endpoint为真实的服务地址 - Header的命名空间必须与Postman示例完全匹配(
http://service.bi.com/entity/message/2003/) - 日期类型需与生成的JAXB类字段类型匹配(若生成的是
XMLGregorianCalendar,需对应转换)
内容的提问来源于stack exchange,提问作者samd
相关产品推荐
相关产品推荐

