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

Apache Camel如何获取WebService返回的原始XML数据?

嘿,这个场景我太熟悉了!要在Apache Camel的CXF代理路由里拿到反序列化前的原始XML,有几种实用的方案,根据你的测试需求选就行:

方案1:直接让CXF返回原始XML(最简单)

如果你的测试只需要处理XML字符串,不需要用到反序列化后的Java对象,可以直接把CXF端点的dataFormat设置为RAW。这样Camel就不会自动把XML转成Java对象,getBody()拿到的就是原始XML字符串。

调整你的路由代码:

from("cxf:bean:eaigateway?dataFormat=RAW")
    .process(exchange -> {
        // 获取原始XML
        String rawXml = exchange.getIn().getBody(String.class);
        // 在这里注入内容,比如替换标签或者新增节点
        String modifiedXml = rawXml.replace("</originalTag>", "<injected>测试内容</injected></originalTag>");
        // 把修改后的XML放回Exchange,继续转发到真实WebService
        exchange.getIn().setBody(modifiedXml);
    })
    .to("cxf:bean:webservice?dataFormat=RAW");

这个方案的好处是零额外配置,直接处理字符串,适合快速测试注入逻辑。

方案2:保留Java对象同时获取原始XML

如果既要用到反序列化后的Java对象,又要修改原始XML,你可以从Exchange的头信息里拿到CXF的原始消息对象,从中提取并修改XML:

from("cxf:bean:eaigateway")
    .process(exchange -> {
        // 从Exchange头中获取CXF的Message实例
        org.apache.cxf.message.Message cxfMessage = exchange.getIn().getHeader(Exchange.CXF_MESSAGE, org.apache.cxf.message.Message.class);
        // 读取原始XML输入流
        InputStream inputStream = cxfMessage.getContent(InputStream.class);
        // 转成字符串(记得用IO工具类,比如Apache Commons IO的IOUtils)
        String rawXml = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        
        // 重要:重置输入流,否则后续反序列化会因为流已读完而失败
        inputStream.reset();
        
        // 在这里注入内容到XML
        String modifiedXml = injectCustomContent(rawXml);
        
        // 如果需要让后续反序列化用修改后的XML,替换CXF消息里的输入流
        ByteArrayInputStream newInputStream = new ByteArrayInputStream(modifiedXml.getBytes(StandardCharsets.UTF_8));
        cxfMessage.setContent(InputStream.class, newInputStream);
    })
    .to("cxf:bean:webservice");

注意:这里需要引入Apache Commons IO依赖来读取流,或者自己实现流的读取逻辑,一定要记得重置流!

方案3:用CXF拦截器提前处理XML

如果希望在消息进入Camel路由之前就完成XML注入,可以自定义CXF的入站拦截器,在反序列化阶段之前拦截并修改原始XML:

第一步:创建自定义拦截器

public class XmlInjectInterceptor extends AbstractPhaseInterceptor<Message> {
    public XmlInjectInterceptor() {
        // 选择RECEIVE阶段,这个阶段在CXF反序列化之前
        super(Phase.RECEIVE);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        InputStream inputStream = message.getContent(InputStream.class);
        try {
            // 读取原始XML
            String rawXml = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
            inputStream.reset();
            
            // 注入自定义内容
            String modifiedXml = rawXml.replace("<content>", "<content><test>注入的测试数据</test>");
            
            // 替换输入流,让后续反序列化使用修改后的XML
            message.setContent(InputStream.class, new ByteArrayInputStream(modifiedXml.getBytes(StandardCharsets.UTF_8)));
        } catch (IOException e) {
            throw new Fault(new RuntimeException("处理原始XML失败", e));
        }
    }
}

第二步:把拦截器配置到CXF端点

在你的Spring配置(或者Java Config)里,给eaigateway端点添加这个拦截器:

<bean id="eaigateway" class="org.apache.camel.component.cxf.CxfEndpoint">
    <!-- 你的其他端点配置,比如address、serviceClass等 -->
    <property name="inInterceptors">
        <list>
            <bean class="com.yourpackage.XmlInjectInterceptor"/>
        </list>
    </property>
</bean>

这样消息在到达Camel路由之前就已经被修改了,路由里拿到的Java对象就是基于修改后XML反序列化的结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:46:41