| 此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4! | 
| 此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4! | 
本章介绍了 Spring 集成对 Web 服务的支持,包括:
您需要将此依赖项包含在您的项目中:
- 
Maven 
- 
Gradle 
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-ws</artifactId>
    <version>6.3.5-SNAPSHOT</version>
</dependency>compile "org.springframework.integration:spring-integration-ws:6.3.5-SNAPSHOT"出站 Web 服务网关
要在向通道发送消息时调用 Web 服务,您有两个选项,这两个选项都基于 Spring Web Services 项目:和 。
前者接受 a 或 作为消息负载。
后者支持 和 接口的任何实现。
两者都需要 Spring Web Services 来确定要调用的Web服务的URI。
以下示例显示了调用 Web 服务的两个选项:SimpleWebServiceOutboundGatewayMarshallingWebServiceOutboundGatewayStringjavax.xml.transform.SourceMarshallerUnmarshallerDestinationProvider
 simpleGateway = new SimpleWebServiceOutboundGateway(destinationProvider);
 marshallingGateway = new MarshallingWebServiceOutboundGateway(destinationProvider, marshaller);| 当使用命名空间支持(稍后介绍)时,您只需设置一个 URI。
在内部,解析器配置固定的 URI 实现。
但是,如果您需要在运行时动态解析 URI,则可以提供从注册表中查找 URI 等行为。
有关此策略的更多信息,请参见 Spring Web Services DestinationProviderJavadoc。DestinationProviderDestinationProvider | 
从版本 5.0 开始,您可以为 and 提供外部实例,您可以为任何自定义属性配置该实例,包括 (允许您的应用程序处理不合规的服务)。SimpleWebServiceOutboundGatewayMarshallingWebServiceOutboundGatewayWebServiceTemplatecheckConnectionForFault
| 当使用命名空间支持(稍后介绍)时,您只需设置一个 URI。
在内部,解析器配置固定的 URI 实现。
但是,如果您需要在运行时动态解析 URI,则可以提供从注册表中查找 URI 等行为。
有关此策略的更多信息,请参见 Spring Web Services DestinationProviderJavadoc。DestinationProviderDestinationProvider | 
入站 Web 服务网关
要在收到 Web 服务调用时向通道发送消息,您同样有两个选项:和 。
前者从 中提取 a 并将其设置为消息有效负载。
后者支持 和 接口的实现。
如果传入的 Web 服务消息是 SOAP 消息,则 SOAP 操作头将添加到转发到请求通道的头中。
以下示例显示了这两个选项:SimpleWebServiceInboundGatewayMarshallingWebServiceInboundGatewayjavax.xml.transform.SourceWebServiceMessageMarshallerUnmarshallerMessage
 simpleGateway = new SimpleWebServiceInboundGateway();
 simpleGateway.setRequestChannel(forwardOntoThisChannel);
 simpleGateway.setReplyChannel(listenForResponseHere); //Optional
 marshallingGateway = new MarshallingWebServiceInboundGateway(marshaller);
 //set request and optionally reply channel这两个网关都实现了 Spring Web 服务接口,因此可以根据标准 Spring Web 服务配置来配置它们。MessageEndpointMessageDispatcherServlet
有关如何使用这些组件的更多详细信息,请参见 Spring Web 服务参考指南中介绍创建 Web 服务的章节。 介绍 Object/XML 映射的章节也同样适用。
要将 和 配置添加到 Spring WS 基础结构中,您应该在 和 目标实现之间添加定义,就像对普通 Spring WS 应用程序所做的那样。
为此(从 Spring 集成的角度来看),Spring WS 提供了以下方便的实现:SimpleWebServiceInboundGatewayMarshallingWebServiceInboundGatewayEndpointMappingMessageDispatcherServletMessageEndpointEndpointMapping
- 
o.s.ws.server.endpoint.mapping.UriEndpointMapping
- 
o.s.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping
- 
o.s.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping
- 
o.s.ws.server.endpoint.mapping.XPathPayloadEndpointMapping
您必须在应用程序上下文中为这些类指定 bean,并根据 WS 映射算法引用 and/或 bean 定义。SimpleWebServiceInboundGatewayMarshallingWebServiceInboundGateway
有关更多信息,请参阅终端节点映射。
Web Service Namespace 支持
要配置出站 Web 服务网关,请使用命名空间中的元素,如下例所示:outbound-gatewayws
<int-ws:outbound-gateway id="simpleGateway"
                     request-channel="inputChannel"
                     uri="https://example.org"/>| 此示例不提供 'reply-channel'。
如果 Web 服务返回非空响应,则包含该响应的响应将发送到请求消息标头中定义的回复通道。
如果这不可用,则会引发 channel resolution 异常。
如果要将回复发送到另一个通道,请在 'outbound-gateway' 元素上提供 'reply-channel' 属性。 MessageREPLY_CHANNEL | 
| 默认情况下,当您在对请求使用 String 有效负载后调用返回空响应的 Web 服务时,不会发送任何回复。
因此,您无需在 request 中设置 'reply-channel' 或具有 header 。
如果您确实希望以 形式接收空响应,则可以将 'ignore-empty-responses' 属性设置为 。
这样做仅适用于对象,因为使用 a 或 a 对象会导致 null 响应,因此永远不会生成回复。 MessageMessageREPLY_CHANNELMessageMessagefalseStringSourceDocumentMessage | 
要设置入站 Web Service Gateway,请使用 element,如下例所示:inbound-gateway
<int-ws:inbound-gateway id="simpleGateway"
                    request-channel="inputChannel"/>要使用 Spring OXM 编组器或解组器,必须提供 bean 引用。 以下示例说明如何为出站编组网关提供 Bean 引用:
<int-ws:outbound-gateway id="marshallingGateway"
                     request-channel="requestChannel"
                     uri="https://example.org"
                     marshaller="someMarshaller"
                     unmarshaller="someUnmarshaller"/>下面的示例展示了如何为入站编组网关提供 Bean 引用:
<int-ws:inbound-gateway id="marshallingGateway"
                    request-channel="requestChannel"
                    marshaller="someMarshaller"
                    unmarshaller="someUnmarshaller"/>| 大多数 implementations 还实现了 interface。
使用此类 时,只有 attribute 是必需的。
即使使用 ,您也可以为出站网关上的 提供参考。 MarshallerUnmarshallerMarshallermarshallerMarshallerrequest-callback | 
对于任一出站网关类型,您都可以指定一个属性而不是 (恰好需要其中一个属性)。
然后,你可以引用任何 Spring Web 服务实现(例如,在运行时从注册表中查找 URI)。destination-provideruriDestinationProvider
对于任一出站网关类型,该属性也可以配置为引用任何 Spring Web Services 实现。message-factoryWebServiceMessageFactory
对于简单入站网关类型,您可以将属性设置为 to 将整个(而不仅仅是其有效负载)作为 a 转发到请求通道。
这样做可能很有用,例如,当自定义转换器直接针对 .extract-payloadfalseWebServiceMessageMessageWebServiceMessage
从版本 5.0 开始,reference 属性允许您注入具有任何可能的自定义属性的 a。web-service-templateWebServiceTemplate
| 此示例不提供 'reply-channel'。
如果 Web 服务返回非空响应,则包含该响应的响应将发送到请求消息标头中定义的回复通道。
如果这不可用,则会引发 channel resolution 异常。
如果要将回复发送到另一个通道,请在 'outbound-gateway' 元素上提供 'reply-channel' 属性。 MessageREPLY_CHANNEL | 
| 默认情况下,当您在对请求使用 String 有效负载后调用返回空响应的 Web 服务时,不会发送任何回复。
因此,您无需在 request 中设置 'reply-channel' 或具有 header 。
如果您确实希望以 形式接收空响应,则可以将 'ignore-empty-responses' 属性设置为 。
这样做仅适用于对象,因为使用 a 或 a 对象会导致 null 响应,因此永远不会生成回复。 MessageMessageREPLY_CHANNELMessageMessagefalseStringSourceDocumentMessage | 
| 大多数 implementations 还实现了 interface。
使用此类 时,只有 attribute 是必需的。
即使使用 ,您也可以为出站网关上的 提供参考。 MarshallerUnmarshallerMarshallermarshallerMarshallerrequest-callback | 
Web 服务 Java DSL 支持
以下代码段显示了 Web Service Namespace Support 中显示的网关的等效配置:
@Bean
IntegrationFlow inbound() {
    return IntegrationFlow.from(Ws.simpleInboundGateway()
                .id("simpleGateway"))
        ...
        .get();
}@Bean
IntegrationFlow outboundMarshalled() {
    return f -> f.handle(Ws.marshallingOutboundGateway()
                    .id("marshallingGateway")
                    .marshaller(someMarshaller())
                    .unmarshaller(someUnmarshalller()))
        ...
}@Bean
IntegrationFlow inboundMarshalled() {
    return IntegrationFlow.from(Ws.marshallingInboundGateway()
                .marshaller(someMarshaller())
                .unmarshaller(someUnmarshalller())
                .id("marshallingGateway"))
        ...
        .get();
}可以以流畅的方式在终端节点规范上设置其他属性(其属性取决于是否为出站网关提供了外部)。
例子:WebServiceTemplate
.from(Ws.simpleInboundGateway()
                .extractPayload(false)).handle(Ws.simpleOutboundGateway(template)
            .uri(uri)
            .sourceExtractor(sourceExtractor)
            .encodingMode(DefaultUriBuilderFactory.EncodingMode.NONE)
            .headerMapper(headerMapper)
            .ignoreEmptyResponses(true)
            .requestCallback(requestCallback)
            .uriVariableExpressions(uriVariableExpressions)
            .extractPayload(false))
).handle(Ws.marshallingOutboundGateway()
            .destinationProvider(destinationProvider)
            .marshaller(marshaller)
            .unmarshaller(unmarshaller)
            .messageFactory(messageFactory)
            .encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
            .faultMessageResolver(faultMessageResolver)
            .headerMapper(headerMapper)
            .ignoreEmptyResponses(true)
            .interceptors(interceptor)
            .messageSenders(messageSender)
            .requestCallback(requestCallback)
            .uriVariableExpressions(uriVariableExpressions)).handle(Ws.marshallingOutboundGateway(template)
            .uri(uri)
            .encodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT)
            .headerMapper(headerMapper)
            .ignoreEmptyResponses(true)
            .requestCallback(requestCallback)
            .uriVariableExpressions(uriVariableExpressions))
)出站 URI 配置
对于 Spring Web 服务支持的所有 URI 方案(参见 URI 和传输),都提供了替换。
以下示例显示了如何定义它:<uri-variable/>
<ws:outbound-gateway id="gateway" request-channel="input"
        uri="https://springsource.org/{thing1}-{thing2}">
    <ws:uri-variable name="thing1" expression="payload.substring(1,7)"/>
    <ws:uri-variable name="thing2" expression="headers.x"/>
</ws:outbound-gateway>
<ws:outbound-gateway request-channel="inputJms"
        uri="jms:{destination}?deliveryMode={deliveryMode}&priority={priority}"
        message-sender="jmsMessageSender">
    <ws:uri-variable name="destination" expression="headers.jmsQueue"/>
    <ws:uri-variable name="deliveryMode" expression="headers.deliveryMode"/>
    <ws:uri-variable name="priority" expression="headers.jms_priority"/>
</ws:outbound-gateway>如果提供 ,则不支持变量替换,并且如果提供变量,则会发生配置错误。DestinationProvider
控制 URI 编码
默认情况下,在发送请求之前,URL 字符串被编码(请参阅 UriComponentsBuilder)到 URI 对象。
在某些具有非标准 URI 的方案中,不需要执行编码。
该元素提供了一个属性。
要禁用 URL 编码,请将此属性设置为 (默认情况下为 )。
如果您希望对某些 URL 进行部分编码,则可以通过在 中使用 an 来实现,如下例所示:<ws:outbound-gateway/>encoding-modeNONETEMPLATE_AND_VALUESexpression<uri-variable/>
<ws:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encoding-mode="NONE">
          <http:uri-variable name="param"
            expression="T(org.apache.commons.httpclient.util.URIUtil)
                                             .encodeWithinQuery('Hello World!')"/>
</ws:outbound-gateway>| 如果设置了 ,则忽略 。 DestinationProviderencoding-mode | 
| 如果设置了 ,则忽略 。 DestinationProviderencoding-mode | 
WS 消息头
Spring 集成 Web 服务网关会自动映射 SOAP 操作头。
默认情况下,通过使用DefaultSoapHeaderMapper,它与 Spring 集成之间相互复制。MessageHeaders
您可以传入自己的特定于 SOAP 的头映射器的实现,因为网关具有支持这样做的属性。
除非由 的 或 属性明确指定,否则不会将任何用户定义的 SOAP 标头复制到 SOAP 消息或从 SOAP 消息复制。requestHeaderNamesreplyHeaderNamesDefaultSoapHeaderMapper
使用 XML 命名空间进行配置时,可以使用 和 属性设置这些属性,还可以通过设置属性来提供自定义映射器。mapped-request-headersmapped-reply-headersheader-mapper
| 映射用户定义的标头时,值还可以包含简单的通配符模式(如 或 )。
例如,如果需要复制所有用户定义的标头,则可以使用通配符: 。myheader*myheader | 
从版本 4.1 开始,(超类)允许为 和 属性(除了现有的 和 )配置令牌,以映射所有用户定义的 Headers。AbstractHeaderMapperDefaultSoapHeaderMapperNON_STANDARD_HEADERSrequestHeaderNamesreplyHeaderNamesSTANDARD_REQUEST_HEADERSSTANDARD_REPLY_HEADERS
| 我们建议使用以下组合,而不是使用通配符 ():。
这样做可以避免将 Headers 映射到回复。 *STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERSrequest | 
从版本 4.3 开始,您可以通过在模式前面加上 .
否定模式获得优先级,因此 does not map 、 或 .
它确实映射了标准标头、 和 .
(请注意,它包含在非否定和否定形式中。
因为 negated values 优先,所以不会映射。!STANDARD_REQUEST_HEADERS,thing1,thing*,!thing2,!thing3,qux,!thing1thing1thing2thing3thing4quxthing1thing1
| 如果您有一个用户定义的标头,该标头以您希望映射的开头,则可以使用 .
然后映射 A。 !\STANDARD_REQUEST_HEADERS,\!myBangHeader!myBangHeader | 
入站 SOAP 标头(入站网关的请求标头和出站网关的回复标头)映射为对象。
您可以通过访问 来浏览内容:SoapHeaderElementSource
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <auth>
            <username>user</username>
            <password>pass</password>
        </auth>
        <bar>BAR</bar>
        <baz>BAZ</baz>
        <qux>qux</qux>
    </soapenv:Header>
    <soapenv:Body>
        ...
    </soapenv:Body>
</soapenv:Envelope>如果 is , 则 , , 和 标头 已映射,但未映射。mapped-request-headersauth, ca*authcatcanqux
以下示例演示如何从名为 的标头获取名为 的值 :userauth
...
SoapHeaderElement header = (SoapHeaderElement) headers.get("auth");
DOMSource source = (DOMSource) header.getSource();
NodeList nodeList = source.getNode().getChildNodes();
assertEquals("username", nodeList.item(0).getNodeName());
assertEquals("user", nodeList.item(0).getFirstChild().getNodeValue());
...从版本 5.0 开始,支持用户定义的标头类型,并将它们填充为 .
以下示例显示了如何执行此操作:DefaultSoapHeaderMapperjavax.xml.transform.Source<soapenv:Header>
Map<String, Object> headers = new HashMap<>();
String authXml =
     "<auth xmlns='http://test.auth.org'>"
           + "<username>user</username>"
           + "<password>pass</password>"
           + "</auth>";
headers.put("auth", new StringSource(authXml));
...
DefaultSoapHeaderMapper mapper = new DefaultSoapHeaderMapper();
mapper.setRequestHeaderNames("auth");上述示例的结果是以下 SOAP 信封:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <auth xmlns="http://test.auth.org">
            <username>user</username>
            <password>pass</password>
        </auth>
    </soapenv:Header>
    <soapenv:Body>
        ...
    </soapenv:Body>
</soapenv:Envelope>| 映射用户定义的标头时,值还可以包含简单的通配符模式(如 或 )。
例如,如果需要复制所有用户定义的标头,则可以使用通配符: 。myheader*myheader | 
| 我们建议使用以下组合,而不是使用通配符 ():。
这样做可以避免将 Headers 映射到回复。 *STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERSrequest | 
| 如果您有一个用户定义的标头,该标头以您希望映射的开头,则可以使用 .
然后映射 A。 !\STANDARD_REQUEST_HEADERS,\!myBangHeader!myBangHeader | 
MTOM 支持
封送入站和出站 Web 服务网关直接通过封送处理程序的内置功能(例如,提供选项)支持连接。
从版本 5.0 开始,简单的 Web 服务网关可以直接使用入站和出站实例进行操作,这些实例具有用于操作附件的 API。
当您需要发送带有附件的 Web 服务消息(来自服务器的回复或客户端请求)时,您应该直接使用 并将带有附件的 作为发送到网关的请求或回复通道。
以下示例显示了如何执行此操作:Jaxb2MarshallermtomEnabledMimeMessageWebServiceMessageFactoryWebServiceMessagepayload
WebServiceMessageFactory messageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
MimeMessage webServiceMessage = (MimeMessage) messageFactory.createWebServiceMessage();
String request = "<test>foo</test>";
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new StringSource(request), webServiceMessage.getPayloadResult());
webServiceMessage.addAttachment("myAttachment", new ByteArrayResource("my_data".getBytes()), "plain/text");
this.webServiceChannel.send(new GenericMessage<>(webServiceMessage));