1. 引言
本教程探讨如何在Java中将原始SOAP XML字符串转换为可用的SOAPMessage
对象。**SOAPMessage
是Java API for XML-based messaging (SAAJ)的核心组件,它封装了完整的SOAP请求或响应,包含信封(Envelope)、头部(Header)和主体(Body)。**
2. 使用SAAJ MessageFactory
第一种方法采用javax.xml.soap
包提供的标准MessageFactory
。该工厂直接从输入流创建SOAPMessage
,其核心流程是:
- 将原始字符串转换为字节流
- 通过工厂解析生成结构化SOAP消息
以下是工具方法usingSAAJMessageFactory()
的实现:
static SOAPMessage usingSAAJMessageFactory(String soapXml) throws Exception {
ByteArrayInputStream input = new ByteArrayInputStream(soapXml.getBytes(StandardCharsets.UTF_8));
MessageFactory factory = MessageFactory.newInstance();
return factory.createMessage(null, input);
}
关键点解析:
- ✅ 使用
StandardCharsets.UTF_8
确保编码转换无丢失 - ✅
MessageFactory.newInstance()
获取默认实现 - ✅
createMessage()
方法直接解析输入流
准备测试用的SOAP字符串(股票价格查询示例):
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soapenv:Header/>" +
"<soapenv:Body>" +
"<m:GetStockPrice xmlns:m=\"http://example.com/stock\">" +
"<m:StockName>GOOG</m:StockName>" +
"</m:GetStockPrice>" +
"</soapenv:Body>" +
"</soapenv:Envelope>";
SOAPMessage message = SoapParser.usingSAAJMessageFactory(xml);
验证结果正确性:
SOAPBody body = message.getSOAPBody();
assertNotNull(message, "SOAPMessage should not be null");
assertNotNull(body, "SOAP Body should not be null");
assertTrue(body.getTextContent().contains("GOOG"), "Expected 'GOOG' not found in the SOAP body");
适用场景: 需要完整访问SOAP消息组件(信封/头部/主体)时
3. 使用DOM解析
替代方案:先通过DOM API将XML解析为Document
对象,再用DOM结构填充SOAPPart
。实现方法usingDOMParsing()
如下:
static SOAPMessage usingDOMParsing(String soapXml) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true); // 关键:启用命名空间感知
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(soapXml.getBytes(StandardCharsets.UTF_8)));
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPPart part = message.getSOAPPart();
part.setContent(new DOMSource(doc.getDocumentElement())); // 用DOM源替换内容
message.saveChanges(); // 确保结构更新
return message;
}
核心步骤:
- 创建命名空间感知的
DocumentBuilderFactory
(SOAP依赖XML命名空间) - 解析字符串为
Document
对象 - 初始化空
SOAPMessage
- 用
DOMSource
包装文档根元素并设置到SOAPPart
- 调用
saveChanges()
完成构建
测试代码与方案1相同:
SOAPMessage message = SoapParser.usingDOMParsing(xml);
验证逻辑保持一致:
SOAPBody body = message.getSOAPBody();
assertNotNull(message, "SOAPMessage should not be null");
assertNotNull(body, "SOAP Body should not be null");
assertTrue(body.getTextContent().contains("GOOG"), "Expected 'GOOG' not found in the SOAP body");
优势场景:
- ✅ 需在构建前修改XML结构时
- ✅ 系统已使用
Document
处理XML时
4. 结论
两种方案对比:
方案 | 特点 | 适用场景 |
---|---|---|
MessageFactory | 简单直接 | 基础转换需求 |
DOM解析 | 灵活可控 | 需预处理XML或与现有DOM系统集成 |
踩坑提示:
- ⚠️ 务必启用命名空间感知(
setNamespaceAware(true)
),否则解析SOAP会失败 - ✅ 字符编码统一用UTF-8避免乱码
- ❌ 忘记调用
saveChanges()
可能导致消息结构不完整
源码参考:GitHub示例代码