如何在Apache Camel的process方法中提取SOAP请求Body并兼容cProcessor组件
在Apache Camel Processor中提取SOAP请求Body的解决方案
首先,先看你提供的待解析SOAP请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:gas="http://solveralynx.com/abc/webservice/pressuredataaccess"> <soapenv:Header/> <soapenv:Body> <pressure:getBalance> <!--Optional:--> <dateFrom>: 2021-02-04</dateFrom> <!--Optional:--> <dateTo>: 2021-02-06</dateTo> <!--Optional:--> <Ident>26986</Ident> </pressure:getBalance> </soapenv:Body> </soapenv:Envelope>
你当前的代码存在几个核心问题,导致没有输出结果:
- 你创建了一个全新的空SOAPMessage,而不是从Camel Exchange中获取实际的请求SOAP内容
- 代码中
soapResponse变量未定义,根本没有指向实际的请求消息 - 没有正确处理Exchange中的输入数据流转
下面是完全适配org.apache.camel.Processor接口的process方法实现,帮你正确提取SOAP Body内容:
import org.apache.camel.Exchange; import javax.xml.soap.*; import javax.xml.transform.stream.StreamSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SoapBodyExtractorProcessor implements org.apache.camel.Processor { private static final Logger LOG = LoggerFactory.getLogger(SoapBodyExtractorProcessor.class); @Override public void process(Exchange exchange) throws Exception { // 1. 从Exchange中获取输入的SOAP请求内容(通常是InputStream或String) Object inputBody = exchange.getIn().getBody(); StreamSource source; if (inputBody instanceof String) { source = new StreamSource(new java.io.StringReader((String) inputBody)); } else if (inputBody instanceof java.io.InputStream) { source = new StreamSource((java.io.InputStream) inputBody); } else { throw new IllegalArgumentException("Unsupported input type: " + inputBody.getClass().getName()); } // 2. 创建SOAP消息工厂并解析输入内容 MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL); SOAPMessage soapMessage = messageFactory.createMessage(); soapMessage.getSOAPPart().setContent(source); soapMessage.saveChanges(); // 3. 获取SOAP Body并遍历子元素 SOAPBody soapBody = soapMessage.getSOAPBody(); LOG.info("开始解析SOAP Body内容"); // 注意:你的请求里getBalance使用了pressure命名空间,需要指定命名空间URI String pressureNamespace = "http://solveralynx.com/abc/webservice/pressuredataaccess"; javax.xml.soap.NodeList getBalanceNodes = soapBody.getElementsByTagNameNS(pressureNamespace, "getBalance"); if (getBalanceNodes.getLength() > 0) { SOAPElement getBalanceElement = (SOAPElement) getBalanceNodes.item(0); // 遍历getBalance下的子元素 java.util.Iterator<?> childItr = getBalanceElement.getChildElements(); while (childItr.hasNext()) { Node node = (Node) childItr.next(); if (node.getNodeType() == Node.ELEMENT_NODE) { Element ele = (Element) node; String nodeName = ele.getLocalName(); String textContent = ele.getTextContent().trim(); LOG.info("{} = {}", nodeName, textContent); // 如果你需要把提取的内容存回Exchange,可以这样做 exchange.setProperty(nodeName, textContent); } } } else { LOG.warn("未找到pressure:getBalance元素"); } } }
关键说明:
- 从Exchange获取输入:必须从
exchange.getIn().getBody()拿到实际的请求数据,而不是创建空的SOAPMessage - 命名空间处理:你的SOAP请求中
getBalance属于http://solveralynx.com/abc/webservice/pressuredataaccess命名空间,使用getElementsByTagNameNS才能精准定位元素,避免遗漏 - 日志替代System.out:在Camel环境中建议使用SLF4J日志而不是
out.println,更符合企业级应用的日志规范 - 异常处理:代码中加入了基础的类型判断和异常抛出,你可以根据实际需求扩展异常处理逻辑
- 内容回存Exchange:如果需要把提取的参数传递给后续路由,可以存入Exchange的Property或直接替换In Body
另外的简化实现方式(使用Camel内置组件)
如果你不想手动解析SOAP,也可以用Camel的camel-soap组件或者camel-xpath组件来提取Body内容,比如用XPath:
import org.apache.camel.Exchange; import org.apache.camel.builder.xml.XPathBuilder; public class SoapBodyXPathProcessor implements org.apache.camel.Processor { @Override public void process(Exchange exchange) throws Exception { // 定义命名空间前缀映射 XPathBuilder xpath = new XPathBuilder("//gas:getBalance/*") .namespace("gas", "http://solveralynx.com/abc/webservice/pressuredataaccess") .namespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); // 提取所有子元素 java.util.List<org.w3c.dom.Node> nodes = xpath.evaluate(exchange, java.util.List.class); for (org.w3c.dom.Node node : nodes) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { org.w3c.dom.Element ele = (org.w3c.dom.Element) node; LOG.info("{} = {}", ele.getLocalName(), ele.getTextContent().trim()); } } } }
这种方式无需手动处理SOAPMessage的创建和解析,更简洁高效。
内容的提问来源于stack exchange,提问作者Katja
相关产品推荐
相关产品推荐

