第 78 章 CXF
CXF Component 复制链接链接已复制到粘贴板!
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 (Wildfly Camel)框架上的 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
选项 复制链接链接已复制到粘贴板!
| 名称 | 必填 | 描述 |
|
| 否 | WSDL 的位置。默认情况下,WSDL 从端点地址获取。例如:
|
|
| 是 | SEI (Service Endpoint Interface)类的名称。此类可以具有,但不需要 JSR181 注释。从 2.0 开始, 只有 POJO 模式需要这个选项。如果提供了 wsdlURL 选项,则 PAYLOAD 和 MESSAGE 模式不需要 serviceClass。当在没有 serviceClass 的情况下使用 wsdlURL 选项时,必须提供 serviceName 和 portName (endpointName for Spring configuration)选项。
从 2.0 开始,可以使用
请注意,引用的对象不能是一个 Proxy (Spring AOP Proxy 为 OK), 因为它依赖于非 Spring AOP Proxy 的 从 2.8 开始, 可以为 PAYLOAD 和 MESSAGE 模式省略 wsdlURL 和 serviceClass 选项。当它们被省略时,任意 XML 元素可以放在 PAYLOAD 模式的 CxfPayload 的正文中,以方便 CXF Dispatch 模式。
例如: |
|
|
只有 WSDL 中存在多个 |
此服务正在实现的服务名称,它映射到
|
|
|
只有在 |
此服务实施的端口名称,它映射到
|
|
| 否 |
CXF 端点支持哪些消息数据格式。可能的值有: |
|
| 否 |
定义 CXF 端点中继标头和路由。请参阅 “relayHeaders 选项的描述”一节。目前仅在 |
|
| 否 |
CXF 端点制作者调用的操作类型。可能的值有: |
|
| 否 |
从 2.5.0 开始,WSDL 样式用于描述在 SOAP 正文中如何表示参数。如果值为 |
|
| 否 |
deprecated : 指定是否为这个端点使用默认的 CXF 总线。可能的值有: |
|
| 否 |
deprecated : 指定是否为这个端点使用默认的 CXF 总线。可能的值有: |
|
| 否 |
使用 默认情况下,使用 CXF 总线 Factory 创建的默认总线。 |
|
| 否 |
使用 |
|
| 否 |
使用 |
|
| 否 |
在 2.3 中,这个选项允许 CXF Logging 功能将入站和出站 SOAP 消息写入日志。可能的值有: |
|
| 否 |
在 2.4 中,这个选项设置调用远程服务的
|
|
| 否 | 在 2.4 中,这个选项设置调用远程服务的 CxfProducer 使用的默认 operationNamespace。例如:
|
|
| 否 |
在 2.5 中,这个选项可让 CXF 端点决定使用 sync 或 async API 进行底层工作。默认值为 |
|
| 否 |
在 2.5 中,此选项将覆盖使用服务地址 URL 和
|
|
| 否 |
Camel 2.8: 允许您在端点 URI 中设置自定义 CXF 属性。例如,设置 |
|
| 否 |
2.8.2 中的新内容.这个选项控制在 PAYLOAD 模式运行时 CXF 组件(请参见下面的),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 仅将延续超时设置为 0,这意味着持续暂停操作永远不会超时。) 默认: 30000 示例 :continuation=80000 |
serviceName 和 portName 是 QNames,因此如果您提供它们,请确保它们带有其 {namespace} 前缀,如上例中所示。
dataformats 的描述 复制链接链接已复制到粘贴板!
| DataFormat | 描述 |
|
| POJO (解释旧 Java 对象)是目标服务器上调用的方法的 Java 参数。支持 Protocol 和 Logical JAX-WS 处理程序。 |
|
|
|
|
|
|
|
|
Camel 2.8.2 的新内容, |
您可以通过检索交换属性 CamelCXFDataFormat 来确定交换的数据格式模式。Exchange key 常量在 org.apache.camel.component.cxf.CxfConstants.DATA_FORMAT_PROPERTY 中定义。
使用 Apache Aries 蓝图配置 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 输出进入 wire 到日志记录系统的出站消息(java.util.logging)。由于 LoggingOutInterceptor 位于 PRE_STREAM 阶段(但 PRE_STREAM 阶段以 MESSAGE 模式删除),因此您必须配置 LoggingOutInterceptor 以便在 WRITE 阶段运行。以下是一个示例。
<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 标头是标头,作为端点的 WSDL 绑定合同的一部分(如 SOAP 标头)明确定义。
带外 标头是通过线上序列化但不是 WSDL 绑定合同的一部分的标头。
标头转发/过滤是双向的。
当路由具有 CXF 端点且开发人员需要具有 on-the-wire 标头(如 SOAP 标头)时,将路由转发给另一个 JAXWS 端点,然后将 relayHeaders 设置为 true,这是默认值。
仅适用于 POJO 模式 复制链接链接已复制到粘贴板!
relayHeaders=true 设置表示转发标头的意图。关于给定标头是否被中继到实施 MessageHeadersRelay 接口的可插拔实例的实际决定。使用 MessageHeadersRelay 的具体实施来确定是否需要转发标头。已有 SoapMessageHeadersRelay 的实现,它将自身绑定到众所周知的 SOAP 命名空间。目前,仅过滤带外标头,当 relayHeaders=true 时始终转发带内标头。如果线上有一个标头,其命名空间对运行时未知,则使用回退 DefaultMessageHeadersRelay,这只是允许所有标头进行转发。
relayHeaders=false 设置断言,所有标头( in-band 和 out-of-band)都会被丢弃。
您可以插件自己的 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 simple) CXF 拦截器/JAXWS Handler 到 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的一个属性。以下是配置用户定义的消息标头过滤器的示例:<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中可以配置新的属性。
| 名称 | 描述 | 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 beans 元素中指定的 JAX-WS schemaLocation 属性。这允许 CXF 验证文件并是必需的。另请注意,< cxf:cxfEndpoint/> 标签末尾的命名空间声明是必需的,因为此标签的属性值目前不支持组合的 {namespace}localName 语法。
cxf:cxfEndpoint 元素支持许多额外的属性:
| Name | 值 |
|
|
此服务实施的端点名称,它映射到 |
|
|
此服务正在实现的服务名称,它映射到 |
|
| WSDL 的位置。可以位于类路径、文件系统上,也可以远程托管。 |
|
|
要使用的服务模型的 |
|
| 服务发布地址。 |
|
| JAX-WS 端点中使用的总线名称。 |
|
| SEI (Service Endpoint Interface)类的类名称,它们可能具有 JSR181 注释。 |
它还支持许多子元素:
| 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 start 文档让 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。首先,您需要在消息标头中指定操作名称,然后将 method 参数添加到列表中,并使用此参数列表初始化消息。响应消息的正文是 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 元素的 getters。这个更改启用了从 Apache Camel 消息分离原生 CXF 消息。
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 端点转发到另一个。也就是说,SOA 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_LIST)。标头值是 CXF SoapHeader 对象的 List <> (org.apache.cxf.binding.soap.SoapHeader)。以下代码片段是 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 对象后,您可以调用返回 DOM Elements (SOAP 标头)的 CxfPayload.getHeaders () 方法。
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 端点转发到另一个 Camel CXF 端点(SOAP Client org.apache.cxf.headers.Header.list Camel 标头中删除它们。
SOAP 标头在 MESSAGE 模式中不可用 复制链接链接已复制到粘贴板!
SOAP 标头在 MESSAGE 模式中不可用,因为跳过 SOAP 处理。
如何从 Apache Camel 丢弃 SOAP Fault 复制链接链接已复制到粘贴板!
如果您使用 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 for enable MTOM)。However, SOAP with Attachment is not tested.Since attachments is marshalled and unmarshalled to POJOs, users 通常不需要处理附件来附加它们。从 2.1Soo 开始,Camel 消息附加功能会被传播到 Camel 消息附加。
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>
您可以生成带有附件的 Camel 消息,以发送到 Payload 模式的 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 模式: 支持 MTOM,可以通过上述 Camel 消息 API 检索附件。
当收到多部分(即 MTOM)消息时,默认的 SOAPMessage 到 String converter 在正文上提供了完整的多部分有效负载。如果您只需要 SOAP XML 作为 String,您可以使用 message.getSOAPPart () 设置消息正文,Camel convert 可以为您执行其余工作。
如何传播堆栈追踪信息 复制链接链接已复制到粘贴板!
可以配置 CXF 端点,以便在服务器端抛出 Java 异常时,异常的堆栈追踪会放入故障消息并返回到客户端。要启用此 feaure,请将 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,如果没有修改有效负载,则可以直接流传输到目标目的地。对于常见的"simple proxy"用例(例如: from ("cxf:…").to ("cxf:…"),这可能会造成非常显著的性能增加,并显著降低了内存要求。
然而,在有些情况下,流可能不合适或需要。由于流性质,在处理链中稍后之前,无效的传入 XML 可能无法被发现。此外,某些操作可能需要通过 DOM 解析消息,如 WS-Security 或消息追踪等,在这种情况下,流的优势有限。此时,可以通过两种方式控制流:
- endpoint 属性:您可以添加 "allowStreaming=false" 作为端点属性,以打开流 on/off。
- 组件属性: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 子系统中定义。在 standalone.xml 和 standalone-full.xml 服务器配置文件中默认提供 application-http-authentication。例如:
<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>
名为 application > 包含对名为 -http-authentication 的 <http-authentication-factoryApplicationDomain 的 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,则 WildFly 将使其可在上下文路径 /my-app 下访问,< url-patternpattern& gt; /webservices jpeg 将应用到相对于 /my-app 的路径。
例如,针对 http://my-server/my-app/webservices/my-endpoint 的请求将与 /webservices>.< pattern 匹配,而 http://my-server/webservices/my-endpoint 不匹配。
这很重要,因为 WildFly-Camel 允许创建 camel-cxf 端点消费者,其基本路径在主机 Web 应用上下文路径之外。例如,可以在 my-app.war 中为 http://my-server/webservices/my-endpoint 创建 camel-cxf 使用者。
为了为此类上下文端点定义安全限制,Wildly-Camel 支持自定义、非标准 < 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>