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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:57:48