使用 Apache Camel 和 CXF 端点调用 RPC/encoded Web 服务
Call RPC/encoded Webservice with Apache Camel and CXF Endpoint
有很多关于 Apache Camel + CXF-Endpoint 和 RPC/encoded 遗留网络服务的信息。
但是直到现在我都没有找到解决问题的方法。
我想通过 CXF 端点从 Apache Camel 调用 RPC/encoded 网络服务。
CXF 不支持 RPC/encoded Web 服务。
所以我尝试了两种方法来解决问题。
将wsdl从RPC/encoded转换为RPC/literal并生成源文件。
调用CXF支持的RPC/literal风格的webservice。
以下文章建议这种方法可以解决我的问题:Best way to consume RPC/encoded webservice?
发送完整的 SOAP 消息而不映射到对象(无 JAXB)。
方法 1 和方法 2 均无效。
在接下来的部分中,我将更详细地解释我的方法和问题。
先决条件
- 阿帕奇 Tomcat 7
- 阿帕奇骆驼 2.14.1
- Apache CXF 2.7.10
- Web 服务端点在 http://localhost:9000/myfunctionalmock
上使用 SOAP-UI 5.0.0 模拟
第一种方法:将 wsdl RPC/encoded 转换为 RPC/literal 并生成源代码
在 RCP/encoded wsdl 中,我更改了以下内容:
WSDL 绑定:
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://my.example.com/myFunction" use="encoded"/>
</wsdl:input>
...
至
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body namespace="http://my.example.com/myFunction" use="literal"/>
</wsdl:input>
…
对象数组:
<complexType name="ArrayOfMyElement">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="impl:MyElement[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOfMyElement">
<xsd:sequence>
<xsd:element name="MyElement"
type="impl:MyElement"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
简单类型数组:
<complexType name="ArrayOf_xsd_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOf_xsd_string">
<xsd:sequence>
<xsd:element name="item"
type="xsd:string"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
未定义类型的数组 (anyType):
<complexType name="ArrayOf_xsd_anyType">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOf_xsd_anyType">
<xsd:sequence>
<xsd:element name="item"
type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
之后我用 IntelliJ Webservice 插件生成了源文件(通过 CXF wsdl2java)
在 Camel 中,我配置了以下端点:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setWsdlURL("wsdl/myservice_literal.wsdl");
endpoint.setServiceClass("com.my.example.MyFunctionalWebservices");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.POJO);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_ENDPOINT_URL);
camelContext.addEndpoint(MY_ENDPOINT_URL, endpoint);
CXF-Endpoint 在 Camel 路由中的使用:
我想调用以下网络服务功能:
public Result isAlive(java.lang.String identifier);
骆驼路线中的计时器仅用于触发网络服务。
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant("1620000018")
.setHeader("operationName", constant("isAlive"))
.setHeader("operationNamespace", constant("http://my.example.com/myFunction"))
.to(MyCamelConfiguration.MY_ENDPOINT_URL);
这种方法的问题:
在运行时部署时会出现以下消息:
2015-03-05 09:57:46,659; 2010; [localhost-startStop-1]; DEBUG; wsdl11.WSDLServiceBuilder; Operation {http://my.example.com/myFunction}isAlive cannot be unwrapped, input message must reference global element declaration with same localname as operation
运行时出现以下异常:
org.apache.cxf.binding.soap.SoapFault: No namespace on "HTML" element. You must send a SOAP request.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:111)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:155)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:835)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1614)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1504)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1310)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:628)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:565)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474)
at org.apache.camel.component.cxf.CxfProducer.process(CxfProducer.java:149)
at org.apache.camel.impl.SynchronousDelegateProducer.process(SynchronousDelegateProducer.java:62)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:416)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:166)
at org.apache.camel.component.timer.TimerConsumer.run(TimerConsumer.java:74)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
第二种方法:发送 SOAP 消息而不映射到对象。
Camel 中的端点定义:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.RAW);
endpoint.setWrappedStyle(false);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_TEMPLATE_ENDPOINT_URL);
camelContext.addEndpoint(MY_TEMPLATE_ENDPOINT_URL, endpoint);
路线中的用法:
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant(
"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:myns=\"http://my.example.com/myFunction\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <myns:isAlive soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
" <identifier xsi:type=\"xsd:string\">1620000018</identifier>\n" +
" </myns:isAlive>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>"
)
.to(MyCamelConfiguration.MY_TEMPLATE_ENDPOINT_URL)
.log(LoggingLevel.INFO, "END Timer Webservice.")
.log(LoggingLevel.INFO, "Body after ws call = ${body}");
但从未调用 http://localhost:9000/myfunctionalmock 上的网络服务。
我在日志文件中发现以下日志消息:
2015-03-05 10:56:35,522; 12843; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack@1d3694a
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyVerificationInInterceptor@1a0ff10
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; policy.PolicyVerificationInInterceptor; Verified policies for inbound message.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; END Timer Webservice.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; Body after ws call = <HTML>
<HEAD><TITLE>Redirection</TITLE></HEAD>
<BODY><H1>Redirect</H1></BODY>
这两种方法都不work.Is有可能在 Camel 中通过 CXF 调用 RPC/encoded 网络服务吗?
提前致谢。
此致,
最大
如您所说,Apache CXF 不 支持旧的 RPC 样式。您将需要使用较旧的 WS 库,例如 Apache Axis 1.x。没有用于此的 Camel 组件,但由于它只是 java 代码,您可以编写一些使用 Axis 1.x 的 java 代码,然后让 Camel 调用 java代码,使用它的 bean 组件/处理器。
另一种选择是,由于 SOAP 是基于 HTTP 的,因此您也可以只使用 Camel 的 HTTP 组件。但是您需要根据 RPC 样式构建消息 body 和 headers,但这也不难做到。
有很多关于 Apache Camel + CXF-Endpoint 和 RPC/encoded 遗留网络服务的信息。 但是直到现在我都没有找到解决问题的方法。
我想通过 CXF 端点从 Apache Camel 调用 RPC/encoded 网络服务。 CXF 不支持 RPC/encoded Web 服务。 所以我尝试了两种方法来解决问题。
将wsdl从RPC/encoded转换为RPC/literal并生成源文件。 调用CXF支持的RPC/literal风格的webservice。 以下文章建议这种方法可以解决我的问题:Best way to consume RPC/encoded webservice?
发送完整的 SOAP 消息而不映射到对象(无 JAXB)。
方法 1 和方法 2 均无效。 在接下来的部分中,我将更详细地解释我的方法和问题。
先决条件
- 阿帕奇 Tomcat 7
- 阿帕奇骆驼 2.14.1
- Apache CXF 2.7.10
- Web 服务端点在 http://localhost:9000/myfunctionalmock 上使用 SOAP-UI 5.0.0 模拟
第一种方法:将 wsdl RPC/encoded 转换为 RPC/literal 并生成源代码
在 RCP/encoded wsdl 中,我更改了以下内容:
WSDL 绑定:
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://my.example.com/myFunction" use="encoded"/>
</wsdl:input>
...
至
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body namespace="http://my.example.com/myFunction" use="literal"/>
</wsdl:input>
…
对象数组:
<complexType name="ArrayOfMyElement">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="impl:MyElement[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOfMyElement">
<xsd:sequence>
<xsd:element name="MyElement"
type="impl:MyElement"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
简单类型数组:
<complexType name="ArrayOf_xsd_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOf_xsd_string">
<xsd:sequence>
<xsd:element name="item"
type="xsd:string"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
未定义类型的数组 (anyType):
<complexType name="ArrayOf_xsd_anyType">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[]"/>
</restriction>
</complexContent>
</complexType>
至
<complexType name="ArrayOf_xsd_anyType">
<xsd:sequence>
<xsd:element name="item"
type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
之后我用 IntelliJ Webservice 插件生成了源文件(通过 CXF wsdl2java)
在 Camel 中,我配置了以下端点:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setWsdlURL("wsdl/myservice_literal.wsdl");
endpoint.setServiceClass("com.my.example.MyFunctionalWebservices");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.POJO);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_ENDPOINT_URL);
camelContext.addEndpoint(MY_ENDPOINT_URL, endpoint);
CXF-Endpoint 在 Camel 路由中的使用:
我想调用以下网络服务功能:
public Result isAlive(java.lang.String identifier);
骆驼路线中的计时器仅用于触发网络服务。
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant("1620000018")
.setHeader("operationName", constant("isAlive"))
.setHeader("operationNamespace", constant("http://my.example.com/myFunction"))
.to(MyCamelConfiguration.MY_ENDPOINT_URL);
这种方法的问题:
在运行时部署时会出现以下消息:
2015-03-05 09:57:46,659; 2010; [localhost-startStop-1]; DEBUG; wsdl11.WSDLServiceBuilder; Operation {http://my.example.com/myFunction}isAlive cannot be unwrapped, input message must reference global element declaration with same localname as operation
运行时出现以下异常:
org.apache.cxf.binding.soap.SoapFault: No namespace on "HTML" element. You must send a SOAP request.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:111)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:155)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:835)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1614)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1504)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1310)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:628)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:565)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474)
at org.apache.camel.component.cxf.CxfProducer.process(CxfProducer.java:149)
at org.apache.camel.impl.SynchronousDelegateProducer.process(SynchronousDelegateProducer.java:62)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:416)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:166)
at org.apache.camel.component.timer.TimerConsumer.run(TimerConsumer.java:74)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
第二种方法:发送 SOAP 消息而不映射到对象。
Camel 中的端点定义:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.RAW);
endpoint.setWrappedStyle(false);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_TEMPLATE_ENDPOINT_URL);
camelContext.addEndpoint(MY_TEMPLATE_ENDPOINT_URL, endpoint);
路线中的用法:
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant(
"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:myns=\"http://my.example.com/myFunction\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <myns:isAlive soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
" <identifier xsi:type=\"xsd:string\">1620000018</identifier>\n" +
" </myns:isAlive>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>"
)
.to(MyCamelConfiguration.MY_TEMPLATE_ENDPOINT_URL)
.log(LoggingLevel.INFO, "END Timer Webservice.")
.log(LoggingLevel.INFO, "Body after ws call = ${body}");
但从未调用 http://localhost:9000/myfunctionalmock 上的网络服务。 我在日志文件中发现以下日志消息:
2015-03-05 10:56:35,522; 12843; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack@1d3694a
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyVerificationInInterceptor@1a0ff10
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; policy.PolicyVerificationInInterceptor; Verified policies for inbound message.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; END Timer Webservice.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; Body after ws call = <HTML>
<HEAD><TITLE>Redirection</TITLE></HEAD>
<BODY><H1>Redirect</H1></BODY>
这两种方法都不work.Is有可能在 Camel 中通过 CXF 调用 RPC/encoded 网络服务吗?
提前致谢。
此致,
最大
如您所说,Apache CXF 不 支持旧的 RPC 样式。您将需要使用较旧的 WS 库,例如 Apache Axis 1.x。没有用于此的 Camel 组件,但由于它只是 java 代码,您可以编写一些使用 Axis 1.x 的 java 代码,然后让 Camel 调用 java代码,使用它的 bean 组件/处理器。
另一种选择是,由于 SOAP 是基于 HTTP 的,因此您也可以只使用 Camel 的 HTTP 组件。但是您需要根据 RPC 样式构建消息 body 和 headers,但这也不难做到。