第 78 章 CXF
CXF 组件
cxf: 组件提供与 Apache CXF 集成,以连接到在 CXF 中托管的 JAX-WS 服务。
Maven 用户必须将此组件的 pom.xml
添加以下依赖项:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cxf</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
如果要了解 CXF 依赖项,请参阅 WHICH-JARS
文本文件。
在流模式中使用 CXF 时(请参阅 DataFormat 选项),然后读取 流缓存。
Camel on EAP 部署
此组件由 EAP 上的 Camel (Wildfly Camel)框架支持,该框架在 Red Hat JBoss Enterprise Application Platform (JBoss EAP)容器上提供了简化的部署模型。
CXF 组件与也使用 Apache CXF 的 JBoss EAP webservices
susbsystem 集成。如需更多信息,请参阅 JAX-WS。
目前,EAP 子系统上的 Camel 不支持 CXF 或 Restlet 用户。但是,可以使用 CamelProxy
来模拟 CXF 消费者。
URI 格式
cxf:bean:cxfEndpoint[?options]
其中 cxfEndpoint 代表一个 Bean ID,它引用了 Spring bean registry 中的 bean。使用这个 URI 格式,大多数端点详情都在 bean 定义中指定。
cxf://someAddress[?options]
其中 someAddress 指定 CXF 端点的地址。使用这个 URI 格式,大多数端点详情都使用选项来指定。
对于上述任一样式,您可以按如下方式将选项附加到 URI:
cxf:bean:cxfEndpoint?wsdlURL=wsdl/hello_world.wsdl&dataFormat=PAYLOAD
选项
Name | 必填 | 描述 |
| 否 | WSDL 的位置。WSDL 默认从端点地址获取。例如:
|
| 是 | SEI (服务端点接口)类的名称。此类可以有,但不需要 JSR181 注释。从 2.0 开始, 只有 POJO 模式需要这个选项。如果提供了 wsdlURL 选项,则 PAYLOAD 和 MESSAGE 模式不需要 serviceClass。当在没有 serviceClass 的情况下使用 wsdlURL 选项时,提供 serviceName 和 portName (用于 Spring 配置的endpointName)选项 MUST。
从 2.0 开始,可以使用
建议引用的对象不能是一个代理(Spring AOP Proxy is OK), 因为它依赖于 non Spring AOP Proxy 的 从 2.8 开始, 可以为 PAYLOAD 和 MESSAGE 模式省略 wsdlURL 和 serviceClass 选项。当忽略它们时,任意 XML 元素可以放在 CxfPayload 的正文(PAYLOAD 模式)中,以便于 CXF Dispatch Mode。
例如: |
|
只有在 WSDL 中存在多个 |
此服务实施的服务名称,它映射到
|
|
只有 |
此服务实施的端口名称,它映射到
|
| 否 |
CXF 端点支持的消息数据格式。可能的值有: |
| 否 |
定义 CXF 端点中继路由中的标头。请参阅 “relayHeaders 选项的描述”一节。目前仅在 |
| 否 |
CXF 端点生成者调用的操作类型。可能的值有: |
| 否 |
由于 2.5.0 是 WSDL 样式,用于描述 SOAP 正文中如何表示参数。如果值为 |
| 否 |
deprecated : 指定是否为这个端点使用默认的 CXF 总线。可能的值有: |
| 否 |
deprecated : 指定是否为这个端点使用默认的 CXF 总线。可能的值有: |
| 否 |
使用 默认情况下,使用 CXF Bus Factory 创建的默认总线。 |
| 否 |
使用 |
| 否 |
使用 \: 表示法引用来自 registry swig-wagon 的标头过滤器策略对象,例如: |
| 否 |
在 2.3 中,这个选项启用 CXF Logging 功能,它将写入入站和出站 SOAP 消息进行日志记录。可能的值有: |
| 否 |
在 2.4 中,此选项设置由 CxfProducer 调用远程服务的
|
| 否 | 在 2.4 中,此选项设置 CxfProducer 使用的默认 operationNamespace,后者调用远程服务。例如:
|
| 否 |
在 2.5 中,这个选项可让 CXF 端点决定使用 sync 或 async API 进行底层工作。默认值为 |
| 否 |
2.5 中的新选项覆盖已发布的 WSDL 中出现的端点 URL,该端点使用服务地址 URL 和
|
| 否 |
Camel 2.8: 允许您在端点 URI 中设置自定义 CXF 属性。例如,设置 |
| 否 |
2.8.2 中的新功能。这个选项控制 CXF 组件是否在 PAYLOAD 模式下运行时(请参阅以下),DOM 会将传入的消息解析为 DOM Elements,或者将有效负载保留为 |
| 否 | 2.11 中的新功能。这个选项控制 PhaseInterceptorChain 是否跳过记录它捕获的 Fault。 |
| 否 |
Camel 2.11 中的新功能。这个选项可以应用 |
| 否 | Camel 2.12.3 中的新选项用于为 CXF 客户端设置用户名的基本身份验证信息。 |
| 否 | Camel 2.12.3 中的新选项用于为 CXF 客户端设置密码的基本身份验证信息。 |
| 否 | Camel 2.14.0 中的新选项用于设置 CXF continuation 超时,当 CXF 服务器使用 Jetty 或 Servlet 传输时,默认可在 CxfConsumer 中使用。(在 Camel 2.14.0 之前,CxfConsumer 将 continuation 超时设置为 0,这意味着 continuation suspend 操作永远不会超时。) 默认 : 30000 示例 :continuation=80000 |
serviceName
和 portName
是 QNames,因此如果您为它们提供,请务必为其添加 {namespace}
前缀,如上例中所示。
dataformats 的描述
DataFormat | 描述 |
| POJO (纯 Java 对象)是目标服务器上调用的方法的 Java 参数。支持协议和逻辑 JAX-WS 处理程序。 |
|
|
|
|
|
Camel 2.8.2 中的新功能, |
您可以通过检索交换属性 CamelCXFDataFormat
来确定交换的数据格式模式。Exchange key 常量在 org.apache.camel.component.cxf.CxfConstants.DATA_FORMAT_PROPERTY
中定义。
使用 Apache Aries Blueprint 配置 CXF 端点.
从 Camel 2.8 开始,支持对 CXF 端点使用 Aries 蓝图依赖项注入。模式与 Spring 模式非常相似,因此转换过程比较透明。
例如:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:cxfcore="http://cxf.apache.org/blueprint/core" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <camel-cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:9001/router" serviceClass="org.apache.servicemix.examples.cxf.HelloWorld"> <camel-cxf:properties> <entry key="dataFormat" value="MESSAGE"/> </camel-cxf:properties> </camel-cxf:cxfEndpoint> <camel-cxf:cxfEndpoint id="serviceEndpoint" address="http://localhost:9000/SoapContext/SoapPort" serviceClass="org.apache.servicemix.examples.cxf.HelloWorld"> </camel-cxf:cxfEndpoint> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="routerEndpoint"/> <to uri="log:request"/> </route> </camelContext> </blueprint>
目前,endpoint 元素是第一个支持的 CXF namespacehandler。
您还可以像 spring 中一样使用 bean 引用
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws" xmlns:cxf="http://cxf.apache.org/blueprint/core" xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd "> <camelcxf:cxfEndpoint id="reportIncident" address="/camel-example-cxf-blueprint/webservices/incident" wsdlURL="META-INF/wsdl/report_incident.wsdl" serviceClass="org.apache.camel.example.reportincident.ReportIncidentEndpoint"> </camelcxf:cxfEndpoint> <bean id="reportIncidentRoutes" class="org.apache.camel.example.reportincident.ReportIncidentRoutes" /> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <routeBuilder ref="reportIncidentRoutes"/> </camelContext> </blueprint>
如何在 MESSAGE 模式中启用 CXF 的 LoggingOutInterceptor
CXF 的 LoggingOutInterceptor
输出位于有线到日志记录系统(java.util.logging
)的出站消息。由于 LoggingOutInterceptor
处于 PRE_STREAM
阶段(但 PRE_STREAM
阶段被删除为 MESSAGE
模式),因此您必须在 WRITE
阶段运行 LoggingOutInterceptor
。以下是一个示例。
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"> <!-- it really should have been user-prestream but CXF does have such phase! --> <constructor-arg value="target/write"/> </bean> <cxf:cxfEndpoint id="serviceEndpoint" address="http://localhost:9002/helloworld" serviceClass="org.apache.camel.component.cxf.HelloService"> <cxf:outInterceptors> <ref bean="loggingOutInterceptor"/> </cxf:outInterceptors> <cxf:properties> <entry key="dataFormat" value="MESSAGE"/> </cxf:properties> </cxf:cxfEndpoint>
relayHeaders 选项的描述
有来自 JAXWS WSDL-first 开发者的 in-band 和 out-of-band on-the-wire 标头。
in-band 标头是标头,作为端点(如 SOAP 标头)的 WSDL 绑定合同的一部分。
带外 标头是通过线线序列化的标头,但不明确成为 WSDL 绑定合同的一部分。
标头中继/过滤是双向的。
当路由具有 CXF 端点并且开发人员需要有在线标头(如 SOAP 标头)时,将在另一个 JAXWS 端点消耗的路由中转发,然后将 relayHeaders
设置为 true
,这是默认值。
仅在 POJO 模式中提供
relayHeaders=true
设置表示转发标头的意图。是否将给定标头中继的实际决定被委派给实现 MessageHeadersRelay
接口的可插拔实例。已查询 MessageHeadersRelay
的 concrete 实现,以决定是否需要转发标头。已有一个 SoapMessageHeadersRelay
的一个实现,它将自身绑定到已知的 SOAP 命名空间。目前,只过滤带外标头,当 relayHeaders=true
时始终转发带外的标头。如果有线上的标头,其命名空间在运行时未知,则使用 fall back DefaultMessageHeadersRelay
,它只允许所有标头转发。
relayHeaders=false
设置表示所有标头(带外和带外)都会被丢弃。
您可以对自己的 MessageHeadersRelay
实现进行插件,或者在中继列表中添加其他内容。要覆盖预加载的中继实例,请确保您的 MessageHeadersRelay
实现服务与您要覆盖的命名空间相同。另请注意,覆盖中继必须将所有命名空间作为您要覆盖的命名空间提供服务,否则会抛出路由启动时的运行时异常,因为这会在命名空间中引入一种不确定性来转发实例映射。
<cxf:cxfEndpoint ...> <cxf:properties> <entry key="org.apache.camel.cxf.message.headers.relays"> <list> <ref bean="customHeadersRelay"/> </list> </entry> </cxf:properties> </cxf:cxfEndpoint> <bean id="customHeadersRelay" class="org.apache.camel.component.cxf.soap.headers.CustomHeadersRelay"/>
查看显示您如何转发/过滤标头的测试:
从版本 2.0 开始的更改
-
支持
POJO
和PAYLOAD
模式。在POJO
模式中,只有带外的消息标头可用于过滤,因为 CXF 从标头列表中删除。in-band 标头被合并到POJO
模式的MessageContentList
中。camel-cxf
组件会试图从MessageContentList
中删除带外标头(如果需要过滤 in-band 标头),请使用PAYLOAD
模式或插入(pretty directly) CXF 拦截器/JAXWS 处理程序到 CXF 端点。 Message Header Relay 机制已合并到
CxfHeaderFilterStrategy
中。relayHeaders
选项、其语义和默认值保持不变,但它是CxfHeaderFilterStrategy
的属性。以下是配置它的示例:<bean id="dropAllMessageHeadersStrategy" class="org.apache.camel.component.cxf.common.header.CxfHeaderFilterStrategy"> <!-- Set relayHeaders to false to drop all SOAP headers --> <property name="relayHeaders" value="false"/> </bean>
然后,您的端点可以引用
CxfHeaderFilterStrategy
。<route> <from uri="cxf:bean:routerNoRelayEndpoint?headerFilterStrategy=#dropAllMessageHeadersStrategy"/> <to uri="cxf:bean:serviceNoRelayEndpoint?headerFilterStrategy=#dropAllMessageHeadersStrategy"/> </route>
MessageHeadersRelay
接口稍有变化,并重命名为MessageHeaderFilter
。它是CxfHeaderFilterStrategy
的属性。以下是配置用户定义的 Message Header Filters 的示例:<bean id="customMessageFilterStrategy" class="org.apache.camel.component.cxf.common.header.CxfHeaderFilterStrategy"> <property name="messageHeaderFilters"> <list> <!-- SoapMessageHeaderFilter is the built in filter. It can be removed by omitting it. --> <bean class="org.apache.camel.component.cxf.common.header.SoapMessageHeaderFilter"/> <!-- Add custom filter here --> <bean class="org.apache.camel.component.cxf.soap.headers.CustomHeaderFilter"/> </list> </property> </bean>
-
除了
relayHeaders
外,还有可在CxfHeaderFilterStrategy
中配置的新属性。
Name | 描述 | type | 必需? | 默认值 |
| 所有消息标头都由 Message Header Filters 处理 |
| 否 |
|
| 所有消息标头都会传播(无需由 Message Header Filters 处理) |
| 否 |
|
|
在激活命名空间中处理重叠过滤器。如果值为 |
| 否 |
|
使用 Spring 配置 CXF 端点
您可以使用以下显示的 Spring 配置文件配置 CXF 端点,您也可以将端点嵌入到 camelContext
标签中。当您调用服务端点时,您可以将 operationName
和 operationNamespace
标头设置为明确您调用的操作的状态。
请注意,在 Camel 2.x 中,我们改为使用 http://camel.apache.org/schema/cxf
作为 CXF 端点的目标命名空间。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> ...
在 Apache Camel 2.x 中 ,http://activemq.apache.org/camel/schema/cxfEndpoint
命名空间被改为 http://camel.apache.org/schema/cxf。
务必包含 root Bean 元素上指定的 JAX-WS schemaLocation
属性。这允许 CXF 验证文件,并是必需的。另请注意 < cxf:cxfEndpoint/>
标签末尾的命名空间声明是必需的,因为此标签的属性值不支持合并 {namespace}localName
语法。
cxf:cxfEndpoint
元素支持很多附加属性:
Name | 值 |
|
此服务实施的端点名称,它映射到 |
|
此服务实施的服务名称,它映射到 |
| WSDL 的位置。可以在 classpath、文件系统上,也可以远程托管。 |
|
要使用的服务模型的 |
| 服务发布地址。 |
| JAX-WS 端点中使用的总线名称。 |
| 可以具有 JSR181 注解或没有该类的 SEI (服务端点接口)类的名称。 |
它还支持许多子元素:
Name | 值 |
|
此端点的传入拦截器。< |
|
此端点的传入错误拦截器。< |
|
此端点的传出拦截器。< |
|
此端点的传出错误拦截器。< |
| 提供给 JAX-WS 端点的属性映射。 |
| 提供给 JAX-WS 端点的 JAX-WS 处理程序列表。 |
|
您可以指定端点中使用哪个 |
|
您可以指定要使用的此端点的 |
|
保存此端点拦截器的功能。< |
|
要使用的端点的 schema 位置。< |
|
要使用此端点的服务工厂。这可以通过 Spring < |
您可以在此处找到更详细的示例,它们演示了如何提供拦截器、属性和处理程序: http://cwiki.apache.org/CXF20DOC/jax-ws-configuration.html
您可以使用 CXF:properties 从 Spring 配置文件设置 CXF 端点的 dataFormat
和 setDefaultBus
属性,如下所示:
<cxf:cxfEndpoint id="testEndpoint" address="http://localhost:9000/router" serviceClass="org.apache.camel.component.cxf.HelloService" endpointName="s:PortName" serviceName="s:ServiceName" xmlns:s="http://www.example.com/test"> <cxf:properties> <entry key="dataFormat" value="MESSAGE"/> <entry key="setDefaultBus" value="true"/> </cxf:properties> </cxf:cxfEndpoint>
如何将 camel-cxf 组件使用 log4j 而不是 java.util.logging
cxf 的默认日志记录器是 java.util.logging
。如果要将其更改为 log4j
,请按如下所示操作:在 classpath 中,创建一个名为 META-INF/cxf/org.apache.cxf.logger
的文件。此文件必须在一行中包含类的完全限定名称 org.apache.cxf.common.logging.Log4jLogger
,且无注释。
如何使用 xml 启动文档让 camel-cxf 响应消息
如果您使用一些 SOAP 客户端,如 PHP,可能会导致此类错误,因为 CXF 不会添加 XML 启动文档 < ?xml version="1.0" encoding="utf-8"?>
。
Error:sendSms: SoapFault exception: [Client] looks like we got no XML document in [...]
要解决这个问题,您只需要告诉 StaxOutInterceptor 为您编写 XML 启动文档。
public class WriteXmlDeclarationInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public WriteXmlDeclarationInterceptor() { super(Phase.PRE_STREAM); addBefore(StaxOutInterceptor.class.getName()); } public void handleMessage(SoapMessage message) throws Fault { message.put("org.apache.cxf.stax.force-start-document", Boolean.TRUE); } }
您可以添加客户拦截器,并将其配置为 camel-cxf
endpont
<cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:${CXFTestSupport.port2}/CXFGreeterRouterTest/CamelContext/RouterPort" serviceClass="org.apache.hello_world_soap_http.GreeterImpl" skipFaultLogging="true"> <cxf:outInterceptors> <!-- This interceptor forces the CXF server send the XML start document to client --> <bean class="org.apache.camel.component.cxf.WriteXmlDeclarationInterceptor"/> </cxf:outInterceptors> <cxf:properties> <!-- Set the publishedEndpointUrl which could override the service address from generated WSDL as you want --> <entry key="publishedEndpointUrl" value="http://www.simple.com/services/test" /> </cxf:properties> </cxf:cxfEndpoint>
或者,如果您正在使用 Camel 2.4,则为它添加一个消息标头。
// set up the response context which force start document Map<String, Object> map = new HashMap<String, Object>(); map.put("org.apache.cxf.stax.force-start-document", Boolean.TRUE); exchange.getOut().setHeader(Client.RESPONSE_CONTEXT, map);
如何以 POJO 数据格式消耗来自 camel-cxf 端点的消息
camel-cxf
端点消费者 POJO
数据格式基于 cxf 调用器,因此消息标题具有名为 CxfConstants.OPERATION_NAME
的属性,消息正文是 SEI 方法参数的列表。
public class PersonProcessor implements Processor { private static final transient Logger LOG = LoggerFactory.getLogger(PersonProcessor.class); @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { LOG.info("processing exchange in camel"); BindingOperationInfo boi = (BindingOperationInfo)exchange.getProperty(BindingOperationInfo.class.toString()); if (boi != null) { LOG.info("boi.isUnwrapped" + boi.isUnwrapped()); } // Get the parameters list which element is the holder. MessageContentsList msgList = (MessageContentsList)exchange.getIn().getBody(); Holder<String> personId = (Holder<String>)msgList.get(0); Holder<String> ssn = (Holder<String>)msgList.get(1); Holder<String> name = (Holder<String>)msgList.get(2); if (personId.value == null || personId.value.length() == 0) { LOG.info("person id 123, so throwing exception"); // Try to throw out the soap fault message org.apache.camel.wsdl_first.types.UnknownPersonFault personFault = new org.apache.camel.wsdl_first.types.UnknownPersonFault(); personFault.setPersonId(""); org.apache.camel.wsdl_first.UnknownPersonFault fault = new org.apache.camel.wsdl_first.UnknownPersonFault("Get the null value of person name", personFault); // Since camel has its own exception handler framework, we can't throw the exception to trigger it // We just set the fault message in the exchange for camel-cxf component handling and return exchange.getOut().setFault(true); exchange.getOut().setBody(fault); return; } name.value = "Bonjour"; ssn.value = "123"; LOG.info("setting Bonjour as the response"); // Set the response message, first element is the return value of the operation, // the others are the holders of method parameters exchange.getOut().setBody(new Object[] {null, personId, ssn, name}); } }
如何以 POJO 数据格式为 camel-cxf 端点准备消息
camel-cxf
端点生成者基于 cxf 客户端 API。首先,您需要在消息标头中指定操作名称,然后将方法参数添加到列表中,然后使用此参数列表初始化消息。响应消息的正文是 messageContentsList
,您可以从该列表获取结果。
如果您没有在消息标头中指定操作名称,CxfProducer
会尝试使用 CxfEndpoint
中的 defaultOperationName
。如果 CxfEndpoint
上没有设置 defaultOperationName
,它会从操作列表中选择第一个操作名称。
如果要从消息正文获取对象数组,您可以使用 message.getbody (Object[].class)
获取正文,如下所示:
Exchange senderExchange = new DefaultExchange(context, ExchangePattern.InOut); final List<String> params = new ArrayList<String>(); // Prepare the request message for the camel-cxf procedure params.add(TEST_MESSAGE); senderExchange.getIn().setBody(params); senderExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, ECHO_OPERATION); Exchange exchange = template.send("direct:EndpointA", senderExchange); org.apache.camel.Message out = exchange.getOut(); // The response message's body is an MessageContentsList which first element is the return value of the operation, // If there are some holder parameters, the holder parameter is filled in the reset of List. // The result is extract from the MessageContentsList with the String class type MessageContentsList result = (MessageContentsList)out.getBody(); LOG.info("Received output text: " + result.get(0)); Map<String, Object> responseContext = CastUtils.cast((Map<?, ?>)out.getHeader(Client.RESPONSE_CONTEXT)); assertNotNull(responseContext); assertEquals("The response context", "UTF-8", responseContext.get(org.apache.cxf.message.Message.ENCODING)); assertEquals("Reply body on Camel is wrong", "echo " + TEST_MESSAGE, result.get(0));
如何以 PAYLOAD 数据格式处理 camel-cxf 端点的消息
在 Apache Camel 2.0 中: CxfMessage.getBody ()
返回 org.apache.camel.component.cxf.CxfPayload
对象,它具有 SOAP 消息标头和 Body 元素的 getter。这个更改支持将原生 CXF 消息与 Apache Camel 消息分离。
protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { public void configure() { from(SIMPLE_ENDPOINT_URI + "&dataFormat=PAYLOAD").to("log:info").process(new Processor() { @SuppressWarnings("unchecked") public void process(final Exchange exchange) throws Exception { CxfPayload<SoapHeader> requestPayload = exchange.getIn().getBody(CxfPayload.class); List<Source> inElements = requestPayload.getBodySources(); List<Source> outElements = new ArrayList<Source>(); // You can use a customer toStringConverter to turn a CxfPayLoad message into String as you want String request = exchange.getIn().getBody(String.class); XmlConverter converter = new XmlConverter(); String documentString = ECHO_RESPONSE; Element in = new XmlConverter().toDOMElement(inElements.get(0)); // Just check the element namespace if (!in.getNamespaceURI().equals(ELEMENT_NAMESPACE)) { throw new IllegalArgumentException("Wrong element namespace"); } if (in.getLocalName().equals("echoBoolean")) { documentString = ECHO_BOOLEAN_RESPONSE; checkRequest("ECHO_BOOLEAN_REQUEST", request); } else { documentString = ECHO_RESPONSE; checkRequest("ECHO_REQUEST", request); } Document outDocument = converter.toDOMDocument(documentString); outElements.add(new DOMSource(outDocument.getDocumentElement())); // set the payload header with null CxfPayload<SoapHeader> responsePayload = new CxfPayload<SoapHeader>(null, outElements, null); exchange.getOut().setBody(responsePayload); } }); } }; }
如何在 POJO 模式中获取和设置 SOAP 标头
POJO
表示,当 CXF 端点生成或使用 Camel 交换时,数据格式是 Java 对象的列表。尽管 Apache Camel 在此模式中将消息正文公开为 POJO,但 CXF 组件仍然提供对读取和写入 SOAP 标头的访问。但是,由于 CXF 拦截器在处理后从标头列表中删除带外 SOAP 标头,因此只有 POJO 模式才提供带外 SOAP 标头。
以下示例演示了如何获取/设置 SOAP 标头。假设我们有一个路由,它从一个 CXF 端点转发到另一个端点。也就是说,SOAP Client
<route> <from uri="cxf:bean:routerRelayEndpointWithInsertion"/> <process ref="InsertRequestOutHeaderProcessor" /> <to uri="cxf:bean:serviceRelayEndpointWithInsertion"/> <process ref="InsertResponseOutHeaderProcessor" /> </route>
在 2.x SOAP 标头中,会传播到 Apache Camel 消息标头。Apache Camel 消息标头名称是 org.apache.cxf.headers.Header.list
,它是 CXF 中定义的常量(org.apache.cxf.headers.Header.Header.HEADER_LIST
)。标头值是 CXF SoapHeader
对象(org.apache.cxf.binding.soap.SoapHeader
)的 List
<>。以下片段是 InsertResponseOutHeaderProcessor
(它会在响应消息中插入一个新的 SOAP 标头)。在 InsertResponseOutHeaderProcessor
和 InsertRequestOutHeaderProcessor
中访问 SOAP 标头的方式实际相同。两个处理器之间的唯一区别是设置插入 SOAP 标头的方向。
public static class InsertResponseOutHeaderProcessor implements Processor { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { // If exchange is routed from camel-cxf endpoint, this is the header List<SoapHeader> soapHeaders = CastUtils.cast((List<?>)exchange.getIn().getHeader(Header.HEADER_LIST)); if (soapHeaders == null) { // we just create a new soap headers in case the header is null soapHeaders = new ArrayList<SoapHeader>(); } // Insert a new header String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><outofbandHeader " + "xmlns=\"http://cxf.apache.org/outofband/Header\" hdrAttribute=\"testHdrAttribute\" " + "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" soap:mustUnderstand=\"1\">" + "<name>New_testOobHeader</name><value>New_testOobHeaderValue</value></outofbandHeader>"; SoapHeader newHeader = new SoapHeader(soapHeaders.get(0).getName(), DOMUtils.readXml(new StringReader(xml)).getDocumentElement()); // make sure direction is OUT since it is a response message. newHeader.setDirection(Direction.DIRECTION_OUT); //newHeader.setMustUnderstand(false); soapHeaders.add(newHeader); } }
如何在 PAYLOAD 模式中获取和设置 SOAP 标头
我们已演示了如何以 PAYLOAD
模式访问 SOAP 消息(CxfPayload
对象) (请参阅 如何处理 PAYLOAD 数据格式的 camel-cxf 端点的消息)。
获取 CxfPayload
对象后,您可以调用 CxfPayload.getHeaders ()
方法,该方法返回 DOM Elements (SOAP 标头) 列表
。
from(getRouterEndpointURI()).process(new Processor() { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { CxfPayload<SoapHeader> payload = exchange.getIn().getBody(CxfPayload.class); List<Source> elements = payload.getBodySources(); assertNotNull("Elements here", elements); assertEquals("Get the wrong elements size", 1, elements.size()); Element el = new XmlConverter().toDOMElement(elements.get(0)); elements.set(0, new DOMSource(el)); assertEquals("Get the wrong namespace URI", "http://camel.apache.org/pizza/types", el.getNamespaceURI()); List<SoapHeader> headers = payload.getHeaders(); assertNotNull("Headers here", headers); assertEquals("Get the wrong headers size", headers.size(), 1); assertEquals("Get the wrong namespace URI", ((Element)(headers.get(0).getObject())).getNamespaceURI(), "http://camel.apache.org/pizza/types"); } }) .to(getServiceEndpointURI());
自 Camel 2.16.0 起,您可以使用 “如何在 POJO 模式中获取和设置 SOAP 标头”一节 中所述的方法设置或获取 SOAP 标头。现在,您可以使用 org.apache.cxf.headers.Header.list
标头来获取和设置 SOAP 标头列表。这意味着,如果您有一个路由从一个 Camel CXF 端点转发到另一个(SOAP Client org.apache.cxf.headers.Header.list
Camel 标头中删除它们。
SOAP 标头在 MESSAGE 模式中不可用
在跳过 SOAP 处理时,在 MESSAGE
模式中不提供 SOAP 标头。
如何从 Apache Camel 抛出 SOAP 故障
如果您使用 CXF 端点来消耗 SOAP 请求,您可能需要从 camel 上下文抛出 SOAP Fault
。基本上,您可以使用 throwFault
DSL 来执行此操作;它适用于 POJO
、PAYLOAD
和 MESSAGE
数据格式。您可以定义 soap 错误,如下所示:
SOAP_FAULT = new SoapFault(EXCEPTION_MESSAGE, SoapFault.FAULT_CODE_CLIENT); Element detail = SOAP_FAULT.getOrCreateDetail(); Document doc = detail.getOwnerDocument(); Text tn = doc.createTextNode(DETAIL_TEXT); detail.appendChild(tn);
然后按以下方式抛出它:
from(routerEndpointURI).setFaultBody(constant(SOAP_FAULT));
如果您的 CXF 端点以 MESSAGE
数据格式工作,您可以在消息正文中设置 SOAP Fault 消息,并在消息标头中设置响应代码。
from(routerEndpointURI).process(new Processor() { public void process(Exchange exchange) throws Exception { Message out = exchange.getOut(); // Set the message body with the out.setBody(this.getClass().getResourceAsStream("SoapFaultMessage.xml")); // Set the response code here out.setHeader(org.apache.cxf.message.Message.RESPONSE_CODE, new Integer(500)); } });
对于 POJO 数据格式来说也是如此。您可以在 Out 正文上设置 SOAP Fault,并通过调用 Message.setFault (true)
来指示其存在故障,如下所示:
from("direct:start").onException(SoapFault.class).maximumRedeliveries(0).handled(true) .process(new Processor() { public void process(Exchange exchange) throws Exception { SoapFault fault = exchange .getProperty(Exchange.EXCEPTION_CAUGHT, SoapFault.class); exchange.getOut().setFault(true); exchange.getOut().setBody(fault); } }).end().to(serviceURI);
如何传播 CXF 端点的请求和响应上下文
CXF 客户端 API 提供了使用请求和响应上下文调用操作的方法。如果您使用 CXF 端点制作者调用外部 Web 服务,您可以设置请求上下文,并使用以下代码获取响应上下文:
CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() { public void process(final Exchange exchange) { final List<String> params = new ArrayList<String>(); params.add(TEST_MESSAGE); // Set the request context to the inMessage Map<String, Object> requestContext = new HashMap<String, Object>(); requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, JAXWS_SERVER_ADDRESS); exchange.getIn().setBody(params); exchange.getIn().setHeader(Client.REQUEST_CONTEXT , requestContext); exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION); } }); org.apache.camel.Message out = exchange.getOut(); // The output is an object array, the first element of the array is the return value Object\[\] output = out.getBody(Object\[\].class); LOG.info("Received output text: " + output\[0\]); // Get the response context form outMessage Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT)); assertNotNull(responseContext); assertEquals("Get the wrong wsdl opertion name", "{http://apache.org/hello_world_soap_http}greetMe", responseContext.get("javax.xml.ws.wsdl.operation").toString());
附加支持
POJO 模式 : 支持带有 Attachment 和 MTOM 的 SOAP (请参阅 Payload Mode 为启用 MTOM 的示例)。无论没有测试,带有 Attachment 的 SOAP 不会被测试。因为 2.1.Since 附加功能被推广到 Camel 消息的附件。Since 附加到 POJO,用户通常不需要处理附件。
DataHandler Message.getAttachment(String id)
.
有效负载模式: 自 2.1 起支持 MTOM。附加功能可以通过上述 Camel 消息 API 检索。不支持使用 Attachment 的 SOAP,因为此模式中没有 SOAP 处理。
要启用 MTOM,将 CXF 端点属性 "mtom_enabled" 设置为 true。(我相信您只能通过 Spring 执行此操作。)
<cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:${CXFTestSupport.port1}/CxfMtomRouterPayloadModeTest/jaxws-mtom/hello" wsdlURL="mtom.wsdl" serviceName="ns:HelloService" endpointName="ns:HelloPort" xmlns:ns="http://apache.org/camel/cxf/mtom_feature"> <cxf:properties> <!-- enable mtom by setting this property to true --> <entry key="mtom-enabled" value="true"/> <!-- set the camel-cxf endpoint data fromat to PAYLOAD mode --> <entry key="dataFormat" value="PAYLOAD"/> </cxf:properties>
您可以在 Payload 模式中生成带有附件的 Camel 消息,以发送到 CXF 端点。
Exchange exchange = context.createProducerTemplate().send("direct:testEndpoint", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut); List<Source> elements = new ArrayList<Source>(); elements.add(new DOMSource(DOMUtils.readXml(new StringReader(MtomTestHelper.REQ_MESSAGE)).getDocumentElement())); CxfPayload<SoapHeader> body = new CxfPayload<SoapHeader>(new ArrayList<SoapHeader>(), elements, null); exchange.getIn().setBody(body); exchange.getIn().addAttachment(MtomTestHelper.REQ_PHOTO_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.REQ_PHOTO_DATA, "application/octet-stream"))); exchange.getIn().addAttachment(MtomTestHelper.REQ_IMAGE_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.requestJpeg, "image/jpeg"))); } }); // process response CxfPayload<SoapHeader> out = exchange.getOut().getBody(CxfPayload.class); Assert.assertEquals(1, out.getBody().size()); Map<String, String> ns = new HashMap<String, String>(); ns.put("ns", MtomTestHelper.SERVICE_TYPES_NS); ns.put("xop", MtomTestHelper.XOP_NS); XPathUtils xu = new XPathUtils(ns); Element oute = new XmlConverter().toDOMElement(out.getBody().get(0)); Element ele = (Element)xu.getValue("//ns:DetailResponse/ns:photo/xop:Include", oute, XPathConstants.NODE); String photoId = ele.getAttribute("href").substring(4); // skip "cid:" ele = (Element)xu.getValue("//ns:DetailResponse/ns:image/xop:Include", oute, XPathConstants.NODE); String imageId = ele.getAttribute("href").substring(4); // skip "cid:" DataHandler dr = exchange.getOut().getAttachment(photoId); Assert.assertEquals("application/octet-stream", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.RESP_PHOTO_DATA, IOUtils.readBytesFromStream(dr.getInputStream())); dr = exchange.getOut().getAttachment(imageId); Assert.assertEquals("image/jpeg", dr.getContentType()); BufferedImage image = ImageIO.read(dr.getInputStream()); Assert.assertEquals(560, image.getWidth()); Assert.assertEquals(300, image.getHeight());
您还可以在 Payload 模式中使用从 CXF 端点接收的 Camel 消息。
public static class MyProcessor implements Processor { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { CxfPayload<SoapHeader> in = exchange.getIn().getBody(CxfPayload.class); // verify request assertEquals(1, in.getBody().size()); Map<String, String> ns = new HashMap<String, String>(); ns.put("ns", MtomTestHelper.SERVICE_TYPES_NS); ns.put("xop", MtomTestHelper.XOP_NS); XPathUtils xu = new XPathUtils(ns); Element body = new XmlConverter().toDOMElement(in.getBody().get(0)); Element ele = (Element)xu.getValue("//ns:Detail/ns:photo/xop:Include", body, XPathConstants.NODE); String photoId = ele.getAttribute("href").substring(4); // skip "cid:" assertEquals(MtomTestHelper.REQ_PHOTO_CID, photoId); ele = (Element)xu.getValue("//ns:Detail/ns:image/xop:Include", body, XPathConstants.NODE); String imageId = ele.getAttribute("href").substring(4); // skip "cid:" assertEquals(MtomTestHelper.REQ_IMAGE_CID, imageId); DataHandler dr = exchange.getIn().getAttachment(photoId); assertEquals("application/octet-stream", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.REQ_PHOTO_DATA, IOUtils.readBytesFromStream(dr.getInputStream())); dr = exchange.getIn().getAttachment(imageId); assertEquals("image/jpeg", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.requestJpeg, IOUtils.readBytesFromStream(dr.getInputStream())); // create response List<Source> elements = new ArrayList<Source>(); elements.add(new DOMSource(DOMUtils.readXml(new StringReader(MtomTestHelper.RESP_MESSAGE)).getDocumentElement())); CxfPayload<SoapHeader> sbody = new CxfPayload<SoapHeader>(new ArrayList<SoapHeader>(), elements, null); exchange.getOut().setBody(sbody); exchange.getOut().addAttachment(MtomTestHelper.RESP_PHOTO_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.RESP_PHOTO_DATA, "application/octet-stream"))); exchange.getOut().addAttachment(MtomTestHelper.RESP_IMAGE_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.responseJpeg, "image/jpeg"))); } }
Message Mode: Attachments 不支持,因为它根本不处理消息。
CXF_MESSAGE Mode: 支持 MTOM,而附件则可通过上述 Camel 消息 API 检索。
当收到多部分(即 MTOM)时,将默认的 SOAPMessage
传给 String
转换器在正文上提供完整的多部分有效负载。如果您只需要 SOAP XML 作为 String
,您可以使用 message.getSOAPPart ()
设置消息正文,并且 Camel 转换可以为您做剩余工作。
如何传播堆栈追踪信息
可以配置 CXF 端点,以便在服务器端引发 Java 异常时,异常的堆栈追踪会被放入故障消息并返回到客户端。要启用这种情况,请将 dataFormat
设置为 PAYLOAD
,并在 cxfEndpoint
元素中将 faultStackTraceEnabled
属性设置为 true
,如下所示:
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
wsdlURL="ship.wsdl"
endpointName="s:TestSoapEndpoint"
serviceName="s:TestService"
xmlns:s="http://test">
<cxf:properties>
<!-- enable sending the stack trace back to client; the default value is false-->
<entry key="faultStackTraceEnabled" value="true" /> <entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
为安全起见,堆栈跟踪不包括导致异常(即,由 导致的
堆栈追踪的一部分)。如果要在堆栈追踪中包含导致异常,在 cxfEndpoint
元素中将 exceptionMessageCauseEnabled
属性设置为 true
,如下所示:
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
wsdlURL="ship.wsdl"
endpointName="s:TestSoapEndpoint"
serviceName="s:TestService"
xmlns:s="http://test">
<cxf:properties>
<!-- enable to show the cause exception message and the default value is false -->
<entry key="exceptionMessageCauseEnabled" value="true" />
<!-- enable to send the stack trace back to client, the default value is false-->
<entry key="faultStackTraceEnabled" value="true" />
<entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
仅为测试和诊断目的启用 exceptionMessageCauseEnabled
标志。对于服务器而言,正常做法是让恶意用户探测到服务器的最初原因。
PAYLOAD 模式流支持
在 2.8.2 中,camel-cxf 组件现在支持在使用 PAYLOAD 模式时流传输传入的消息。在以前的版本中,传入的信息会被完全解析 DOM。对于大型消息,这非常耗时,使用大量内存。从 2.8.2 开始,在路由时,传入的消息可以保留为 javax.xml.transform.Source,如果没有修改有效负载,则可以直接流传输到目标目的地。对于常见的"简单代理"用例(例如: from ("cxf:…").to ("cxf:…")),这可以提供非常显著的性能增加,并显著降低内存要求。
然而,在有些情况下流可能不合适或需要的。由于流性质,在稍后处理链中可能无法发现无效的传入的 XML。此外,某些操作可能要求消息是 DOM 解析的任何方式(如 WS-Security 或消息追踪等),在这种情况下,流的优势是有限的。此时,可以通过两种方式控制流:
- endpoint 属性:您可以添加 "allowStreaming=false" 作为端点属性,来打开/关闭流。
- 组件属性:CxfComponent 对象也具有 allowStreaming 属性,可以为从该组件创建的端点设置默认值。
-
全局系统属性:如果关闭,您可以添加
org.apache.camel.component.cxf.streaming
的系统属性,以关闭。这会设置全局默认值,但设置上面的 endpoint 属性会覆盖该端点的值。
使用通用 CXF Dispatch 模式
从 2.8.0,camel-cxf 组件支持通用 CXF 分配模式,它可以传输任意结构的消息(例如,不绑定到特定 XML 模式)。要使用此模式,您只需要省略指定 CXF 端点的 wsdlURL 和 serviceClass 属性。
<cxf:cxfEndpoint id="testEndpoint" address="http://localhost:9000/SoapContext/SoapAnyPort"> <cxf:properties> <entry key="dataFormat" value="PAYLOAD"/> </cxf:properties> </cxf:cxfEndpoint>
请注意,默认的 CXF 分配客户端不会发送特定的 SOAPAction 标头。因此,当目标服务需要特定的 SOAPAction 值时,会使用键 SOAPAction (不区分大小写)在 Camel 标头中提供。
78.1. WildFly 上的 CXF 用户
WildFly 上的 camel-cxf 用户配置与独立 Camel 的配置不同。生产者端点可以正常运行。
在 WildFly 上,camel-cxf 用户利用容器提供的默认 Undertow HTTP 服务器。服务器在 undertow 子系统配置中定义。以下是 standalone.xml 中默认配置的摘录:
<subsystem xmlns="urn:jboss:domain:undertow:4.0"> <buffer-cache name="default" /> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" /> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true" /> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content" /> <filter-ref name="server-header" /> <filter-ref name="x-powered-by-header" /> <http-invoker security-realm="ApplicationRealm" /> </host> </server> </subsystem>
在本实例中,Undertow 配置为侦听 http 和 https socket-binding 指定的接口/端口。默认情况下,对于 http,对于端口 8080,https 为 8443。
例如,如果您使用不同的主机或端口组合配置端点使用者,服务器日志文件中会显示警告。例如,以下主机和端口配置将被忽略:
<cxf:rsServer id="cxfRsConsumer" address="http://somehost:1234/path/to/resource" serviceClass="org.example.ServiceClass" />
<cxf:cxfEndpoint id="cxfWsConsumer" address="http://somehost:1234/path/to/resource" serviceClass="org.example.ServiceClass" />
[org.wildfly.extension.camel] (pool-2-thread-1) Ignoring configured host: http://somehost:1234/path/to/resource
但是,消费者在默认主机和端口 localhost:8080 或 localhost:8443 上仍然可用。
使用 camel-cxf 使用者 的应用程序必须 打包为 WAR。在以前的 WildFly-Camel 版本中,允许 JAR 等其他类型的存档,但不再受支持。
78.1.1. 配置替代端口
如果要接受替代端口,则必须通过 WildFly 子系统配置它们。这在服务器文档中解释:
78.1.2. 配置 SSL
要配置 SSL,请参阅 WildFly SSL 配置指南:
78.1.3. 使用 Elytron 配置安全性
WildFly-Camel 支持使用 Elytron 安全框架保护 camel-cxf 消费者端点。
78.1.3.1. 配置安全域
要使用 Elytron 保护 WildFly-Camel 应用程序,需要在 WAR 部署的 WEB-INF/jboss-web.xml
中引用应用程序安全域:
<jboss-web> <security-domain>my-application-security-domain</security-domain> </jboss-web>
& lt;security-domain&
gt; 配置引用 Undertow 子系统定义的 < application-security-domain
> 的名称。例如,Undertow 子系统 < ;application-security-domain
> 在 WildFly 服务器 standalone.xml
配置文件中配置,如下所示:
<subsystem xmlns="urn:jboss:domain:undertow:6.0"> ... <application-security-domains> <application-security-domain name="my-application-security-domain" http-authentication-factory="application-http-authentication"/> </application-security-domains> </subsystem>
& lt;http-authentication-factory
> application-http-authentication
在 Elytron 子系统中定义。application-http-authentication
默认在 standalone.xml
和 standalone-full.xml
服务器配置文件中可用。例如:
<subsystem xmlns="urn:wildfly:elytron:1.2"> ... <http> ... <http-authentication-factory name="application-http-authentication" http-server-mechanism-factory="global" security-domain="ApplicationDomain"> <mechanism-configuration> <mechanism mechanism-name="BASIC"> <mechanism-realm realm-name="Application Realm" /> </mechanism> <mechanism mechanism-name="FORM" /> </mechanism-configuration> </http-authentication-factory> <provider-http-server-mechanism-factory name="global" /> </http> ... </subsystem>
& lt;http-authentication-factory
> 名为 application-http-authentication
,包含对名为 ApplicationDomain
的 Elytron 安全域的引用。
有关如何配置 Elytron 子系统的更多信息,请参阅 Elytron 文档。
78.1.3.2. 配置安全约束、身份验证方法和安全角色
安全约束、camel-cxf 消费者端点的身份验证方法和安全角色可以在 WAR 部署 WEB-INF/web.xml
中配置。例如,配置 BASIC 身份验证:
<web-app> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/webservices/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>my-role</role-name> </auth-constraint> </security-constraint> <security-role> <description>The role that is required to log in to /webservices/*</description> <role-name>my-role</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> <realm-name>my-realm</realm-name> </login-config> </web-app>
请注意,由 Servlet 规范定义的 <url-pattern
> 相对于 web 应用程序的上下文路径。如果您的应用程序被打包为 my-app.war
,Wild 将在上下文路径 /my-app
下访问它,< url-patternpattern>
; /webservices
GovCloud 将应用到相对于 /my-app
的路径。
例如,针对 http://my-server/my-app/webservices/my-endpoint
的请求将与 /webservices netobserv
模式匹配,而 http://my-server/webservices/my-endpoint
不匹配。
这很重要,因为 WildFly-Camel 允许创建 camel-cxf 端点消费者,其基本路径位于主机 Web 应用上下文路径之外。例如,可以为 my-app.war
中的 http://my-server/webservices/my-endpoint
创建 camel-cxf 使用者。
要为此类上下文端点定义安全约束,Wild-Camel 支持自定义非标准 & lt; url-pattern&
gt; 约定,其中为带有三个正斜杠 ///
前缀的模式作为服务器主机名。例如,要在 my-app.war
内保护 http://my-server/webservices/my-endpoint
,您可以将以下配置添加到 web.xml
中:
<web-app> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>///webservices/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>my-role</role-name> </auth-constraint> </security-constraint> <security-role> <description>The role that is required to log in to /webservices/*</description> <role-name>my-role</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> <realm-name>my-realm</realm-name> </login-config> </web-app>