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
相关产品推荐
相关产品推荐

