此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1! |
本章介绍Spring Integration对Web服务的支持,包括:
您需要将此依赖项包含在项目中:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-ws</artifactId>
<version>6.3.2-SNAPSHOT</version>
</dependency>
compile "org.springframework.integration:spring-integration-ws:6.3.2-SNAPSHOT"
出站 Web 服务网关
若要在向通道发送消息时调用 Web 服务,有两个选项,这两个选项都基于 Spring Web Services 项目构建:和 。
前者接受 or 作为消息有效负载。
后者支持 and 接口的任何实现。
两者都需要 Spring Web 服务 ,以确定要调用的 Web 服务的 URI。
以下示例显示了用于调用 Web 服务的两个选项:SimpleWebServiceOutboundGateway
MarshallingWebServiceOutboundGateway
String
javax.xml.transform.Source
Marshaller
Unmarshaller
DestinationProvider
simpleGateway = new SimpleWebServiceOutboundGateway(destinationProvider);
marshallingGateway = new MarshallingWebServiceOutboundGateway(destinationProvider, marshaller);
使用命名空间支持(稍后介绍)时,只需设置一个 URI。
在内部,分析器配置固定的 URI 实现。
但是,如果需要在运行时动态解析 URI,则可以提供从注册表查找 URI 等行为。
有关此策略的更多信息,请参阅 Spring Web Services DestinationProvider Javadoc。DestinationProvider DestinationProvider |
从版本 5.0 开始,您可以提供 and 外部实例,您可以为任何自定义属性配置该实例,包括 (它允许应用程序处理不符合要求的服务)。SimpleWebServiceOutboundGateway
MarshallingWebServiceOutboundGateway
WebServiceTemplate
checkConnectionForFault
使用命名空间支持(稍后介绍)时,只需设置一个 URI。
在内部,分析器配置固定的 URI 实现。
但是,如果需要在运行时动态解析 URI,则可以提供从注册表查找 URI 等行为。
有关此策略的更多信息,请参阅 Spring Web Services DestinationProvider Javadoc。DestinationProvider DestinationProvider |
入站 Web 服务网关
若要在收到 Web 服务调用时向通道发送消息,同样有两个选项:和 。
前者从中提取 a 并将其设置为消息有效负载。
后者支持 和 接口的实现。
如果传入的 Web Service 消息是 SOAP 消息,则 SOAP 操作标头将添加到转发到请求通道的 SOAP 的标头中。
以下示例显示了这两个选项:SimpleWebServiceInboundGateway
MarshallingWebServiceInboundGateway
javax.xml.transform.Source
WebServiceMessage
Marshaller
Unmarshaller
Message
simpleGateway = new SimpleWebServiceInboundGateway();
simpleGateway.setRequestChannel(forwardOntoThisChannel);
simpleGateway.setReplyChannel(listenForResponseHere); //Optional
marshallingGateway = new MarshallingWebServiceInboundGateway(marshaller);
//set request and optionally reply channel
这两个网关都实现了 Spring Web 服务接口,因此可以按照标准的 Spring Web 服务配置来配置它们。MessageEndpoint
MessageDispatcherServlet
有关如何使用这些组件的更多详细信息,请参阅 Spring Web 服务参考指南中介绍创建 Web 服务的章节。 介绍对象/XML 映射的章节也同样适用。
要将 和 配置添加到 Spring WS 基础结构中,您应该在 和 目标实现之间添加定义,就像添加普通 Spring WS 应用程序一样。
为此(从 Spring 集成的角度来看),Spring WS 提供了以下方便的实现:SimpleWebServiceInboundGateway
MarshallingWebServiceInboundGateway
EndpointMapping
MessageDispatcherServlet
MessageEndpoint
EndpointMapping
-
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 映射算法引用和/或 Bean 定义。SimpleWebServiceInboundGateway
MarshallingWebServiceInboundGateway
有关详细信息,请参阅终结点映射。
Web 服务命名空间支持
若要配置出站 Web 服务网关,请使用命名空间中的元素,如以下示例所示:outbound-gateway
ws
<int-ws:outbound-gateway id="simpleGateway"
request-channel="inputChannel"
uri="https://example.org"/>
此示例不提供“reply-channel”。
如果 Web 服务返回非空响应,则包含该响应的响应将发送到请求消息标头中定义的回复通道。
如果不可用,则会引发通道解析异常。
如果要将回复发送到另一个频道,请在“outbound-gateway”元素上提供“reply-channel”属性。Message REPLY_CHANNEL |
默认情况下,当您调用在对请求使用 String 有效负载后返回空响应的 Web 服务时,不会发送任何回复。
因此,您无需设置“reply-channel”或在请求中设置标头。
如果您确实希望以 ,可以将“ignore-empty-responses”属性设置为 。
这样做仅适用于对象,因为使用 或 对象会导致 null 响应,因此永远不会生成回复。Message Message REPLY_CHANNEL Message Message false String Source Document Message |
若要设置入站 Web 服务网关,请使用该元素,如以下示例所示: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"/>
大多数实现也实现了接口。
使用这样的 时,只有属性是必需的。
即使在使用 时,也可以为出站网关提供参考。Marshaller Unmarshaller Marshaller marshaller Marshaller request-callback |
对于任一出站网关类型,您都可以指定一个属性,而不是 (恰好需要其中之一)。
然后,您可以引用任何 Spring Web Services 实现(例如,在运行时从注册表中查找 URI)。destination-provider
uri
DestinationProvider
对于任一出站网关类型,还可以使用对任何 Spring Web Services 实现的引用来配置该属性。message-factory
WebServiceMessageFactory
对于简单的入站网关类型,您可以将属性设置为将整个负载转发,而不仅仅是将其有效负载作为转发到请求通道。
这样做可能很有用,例如,当自定义变压器直接与extract-payload
false
WebServiceMessage
Message
WebServiceMessage
从版本 5.0 开始,reference 属性允许您注入任何可能的自定义属性。web-service-template
WebServiceTemplate
此示例不提供“reply-channel”。
如果 Web 服务返回非空响应,则包含该响应的响应将发送到请求消息标头中定义的回复通道。
如果不可用,则会引发通道解析异常。
如果要将回复发送到另一个频道,请在“outbound-gateway”元素上提供“reply-channel”属性。Message REPLY_CHANNEL |
默认情况下,当您调用在对请求使用 String 有效负载后返回空响应的 Web 服务时,不会发送任何回复。
因此,您无需设置“reply-channel”或在请求中设置标头。
如果您确实希望以 ,可以将“ignore-empty-responses”属性设置为 。
这样做仅适用于对象,因为使用 或 对象会导致 null 响应,因此永远不会生成回复。Message Message REPLY_CHANNEL Message Message false String Source Document Message |
大多数实现也实现了接口。
使用这样的 时,只有属性是必需的。
即使在使用 时,也可以为出站网关提供参考。Marshaller Unmarshaller Marshaller marshaller Marshaller request-callback |
Web Service Java DSL 支持
以下代码片段显示了 Web 服务命名空间支持中显示的网关的等效配置:
@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 字符串将编码为 URI 对象(请参阅 UriComponentsBuilder
)。
在某些具有非标准 URI 的方案中,不希望执行编码。
该元素提供属性。
若要禁用对 URL 的编码,请将此属性设置为(默认情况下为 )。
如果要对某些 URL 进行部分编码,可以使用 within a 来实现,如以下示例所示:<ws:outbound-gateway/>
encoding-mode
NONE
TEMPLATE_AND_VALUES
expression
<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>
如果设置了 ,则忽略。DestinationProvider encoding-mode |
如果设置了 ,则忽略。DestinationProvider encoding-mode |
WS 消息头
Spring Integration Web 服务网关会自动映射 SOAP 操作标头。
默认情况下,使用 DefaultSoapHeaderMapper
将其复制到 Spring Integration 或从 Spring Integration 复制。MessageHeaders
您可以传入自己的特定于 SOAP 的标头映射器的实现,因为网关具有支持这样做的属性。
除非 的 或属性明确指定,否则不会将任何用户定义的 SOAP 标头复制到 SOAP 消息或从 SOAP 消息复制。requestHeaderNames
replyHeaderNames
DefaultSoapHeaderMapper
使用 XML 命名空间进行配置时,可以使用 and 属性设置这些属性,也可以通过设置属性来提供自定义映射器。mapped-request-headers
mapped-reply-headers
header-mapper
映射用户定义的标头时,这些值还可以包含简单的通配符模式(如 或 )。
例如,如果需要复制所有用户定义的标头,则可以使用通配符: 。myheader* myheader |
从版本 4.1 开始,(超类)允许为 and 属性配置令牌(除了现有的 和 )以映射所有用户定义的标头。AbstractHeaderMapper
DefaultSoapHeaderMapper
NON_STANDARD_HEADERS
requestHeaderNames
replyHeaderNames
STANDARD_REQUEST_HEADERS
STANDARD_REPLY_HEADERS
我们建议使用以下组合,而不是使用通配符 (): 。
这样做可以避免将标头映射到回复。* STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS request |
从版本 4.3 开始,可以通过在模式前面加上 来否定标头映射中的模式。
否定的模式具有优先级,因此诸如 does not map 、 或 .
它确实映射了标准标头、 和 。
(请注意,它包含在非否定和否定形式中。
由于否定值优先,因此未映射。!
STANDARD_REQUEST_HEADERS,thing1,thing*,!thing2,!thing3,qux,!thing1
thing1
thing2
thing3
thing4
qux
thing1
thing1
如果您有一个用户定义的标头,并且以您希望映射的开头,则可以使用 来转义它,如下所示: 。
然后映射 A。! \ STANDARD_REQUEST_HEADERS,\!myBangHeader !myBangHeader |
入站 SOAP 标头(入站网关的请求标头和出站网关的应答标头)映射为对象。
您可以通过访问以下内容来浏览内容:SoapHeaderElement
Source
<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>
如果 是 、 、 和 标头,则映射,但未映射。mapped-request-headers
auth, ca*
auth
cat
can
qux
下面的示例演示如何从名为 : 的标头获取命名的值user
auth
...
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 开始,支持用户定义的标头类型,并将它们填充为 .
以下示例演示如何执行此操作:DefaultSoapHeaderMapper
javax.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 |
我们建议使用以下组合,而不是使用通配符 (): 。
这样做可以避免将标头映射到回复。* STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS request |
如果您有一个用户定义的标头,并且以您希望映射的开头,则可以使用 来转义它,如下所示: 。
然后映射 A。! \ STANDARD_REQUEST_HEADERS,\!myBangHeader !myBangHeader |
MTOM 支持
封送入站和出站 Web 服务网关直接通过封送器的内置功能支持附件(例如,提供选项)。
从版本 5.0 开始,简单的 Web 服务网关可以直接使用入站和出站实例进行操作,这些实例具有用于操作附件的 API。
当您需要发送带有附件的 Web 服务消息(来自服务器的回复或客户端请求)时,您应该直接使用并发送带有附件的邮件作为网关的请求或回复通道。
以下示例演示如何执行此操作:Jaxb2Marshaller
mtomEnabled
MimeMessage
WebServiceMessageFactory
WebServiceMessage
payload
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));