Web Services Support
本章介绍 Spring Integration 对 Web 服务的支持,包括:
This chapter describes Spring Integration’s support for web services, including:
你需要将此依赖项包含在你的项目中:
You need to include this dependency into your project:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-ws</artifactId>
<version>{project-version}</version>
</dependency>
compile "org.springframework.integration:spring-integration-ws:{project-version}"
Outbound Web Service Gateways
要在向通道发送消息时调用 Web 服务,你有两个选择,这两个选择都建立在 Spring Web Services 项目上:SimpleWebServiceOutboundGateway
和 MarshallingWebServiceOutboundGateway
。前者接受 String
或 javax.xml.transform.Source
作为消息有效负载。后者支持任何 Marshaller
和 Unmarshaller
接口的实现。两者都需要一个 Spring Web Services DestinationProvider
,以确定要调用的 Web 服务的 URI。以下示例展示了调用 Web 服务的两种选择:
To invoke a web service when you send a message to a channel, you have two options, both of which build upon the Spring Web Services project: SimpleWebServiceOutboundGateway
and MarshallingWebServiceOutboundGateway
.
The former accepts either a String
or javax.xml.transform.Source
as the message payload.
The latter supports any implementation of the Marshaller
and Unmarshaller
interfaces.
Both require a Spring Web Services DestinationProvider
, to determine the URI of the web service to be called.
The following example shows both options for invoking a web service:
simpleGateway = new SimpleWebServiceOutboundGateway(destinationProvider);
marshallingGateway = new MarshallingWebServiceOutboundGateway(destinationProvider, marshaller);
当使用名称空间支持 (described later) 时,你只需要设置一个 URI。在内部,解析器会配置一个固定的 URI |
When using the namespace support (described later), you need only set a URI.
Internally, the parser configures a fixed URI |
从版本 5.0 开始,您可以为 SimpleWebServiceOutboundGateway
和 MarshallingWebServiceOutboundGateway
提供一个外部 WebServiceTemplate
实例,您可以为它配置任何自定义属性,包括 checkConnectionForFault
(它允许您的应用程序处理不一致的服务)。
Starting with version 5.0, you can supply the SimpleWebServiceOutboundGateway
and MarshallingWebServiceOutboundGateway
with an external WebServiceTemplate
instance, which you can configure for any custom properties, including checkConnectionForFault
(which allows your application to deal with non-conforming services).
有关内部工作原理的更多详细信息,请参阅 Spring Web Services 参考指南中介绍 client access 的章节和介绍 Object/XML mapping 的章节。
For more detail on the inner workings, see the Spring Web Services reference guide’s chapter covering client access and the chapter covering Object/XML mapping.
Inbound Web Service Gateways
在接收 Web 服务调用时将消息发送到通道,您还有两个选项:SimpleWebServiceInboundGateway
和 MarshallingWebServiceInboundGateway
。前者从 WebServiceMessage
中提取 javax.xml.transform.Source
并将其设置为消息有效负载。后者支持 Marshaller
和 Unmarshaller
接口的实现。如果传入的 Web 服务消息是 SOAP 消息,则将 SOAP 操作头添加到转发到请求通道的 Message
头中。以下示例显示了两个选项:
To send a message to a channel upon receiving a web service invocation, you again have two options: SimpleWebServiceInboundGateway
and MarshallingWebServiceInboundGateway
.
The former extracts a javax.xml.transform.Source
from the WebServiceMessage
and sets it as the message payload.
The latter supports implementation of the Marshaller
and Unmarshaller
interfaces.
If the incoming web service message is a SOAP message, the SOAP action header is added to the headers of the Message
that is forwarded onto the request channel.
The following example shows both options:
simpleGateway = new SimpleWebServiceInboundGateway();
simpleGateway.setRequestChannel(forwardOntoThisChannel);
simpleGateway.setReplyChannel(listenForResponseHere); //Optional
marshallingGateway = new MarshallingWebServiceInboundGateway(marshaller);
//set request and optionally reply channel
两个网关都实现了 Spring Web Services MessageEndpoint
接口,因此它们可以使用 MessageDispatcherServlet
按照标准 Spring Web Services 配置进行配置。
Both gateways implement the Spring Web Services MessageEndpoint
interface, so they can be configured with a MessageDispatcherServlet
as per standard Spring Web Services configuration.
有关如何使用这些组件的更多详细信息,请参阅 Spring Web Services 参考指南中介绍 creating a web service 的章节。介绍 Object/XML mapping 的章节也同样适用。
For more detail on how to use these components, see the Spring Web Services reference guide’s chapter covering creating a web service. The chapter covering Object/XML mapping is also applicable again.
要将 SimpleWebServiceInboundGateway
和 MarshallingWebServiceInboundGateway
配置添加到 Spring WS 基础设施,您应在 MessageDispatcherServlet
和目标 MessageEndpoint
实现之间添加 EndpointMapping
定义,就像对于普通的 Spring WS 应用程序一样。出于此目的(从 Spring 集成角度来看),Spring WS 提供了以下方便的 EndpointMapping
实现:
To add the SimpleWebServiceInboundGateway
and MarshallingWebServiceInboundGateway
configurations to the Spring WS infrastructure, you should add the EndpointMapping
definition between MessageDispatcherServlet
and the target MessageEndpoint
implementations, as you would for a normal Spring WS application.
For this purpose (from the Spring Integration perspective), Spring WS provides the following convenient EndpointMapping
implementations:
-
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 映射算法引用 SimpleWebServiceInboundGateway
和/或 MarshallingWebServiceInboundGateway
bean 定义。
You must specify the beans for these classes in the application context and reference the SimpleWebServiceInboundGateway
and/or MarshallingWebServiceInboundGateway
bean definitions according to the WS mapping algorithm.
有关详细信息,请参阅 endpoint mappings。
See the endpoint mappings for more information.
Web Service Namespace Support
要配置出站 Web 服务网关,请使用 ws
命名空间中的 outbound-gateway
元素,如下例所示:
To configure an outbound web service gateway, use the outbound-gateway
element from the ws
namespace, as the following example shows:
<int-ws:outbound-gateway id="simpleGateway"
request-channel="inputChannel"
uri="https://example.org"/>
此示例不提供“回复频道”。如果 Web 服务返回一个非空响应,则包含该响应的 |
This example does not provide a 'reply-channel'.
If the web service returns a non-empty response, the |
默认情况下,当你调用一个在使用字符串有效负载时返回空响应的网络服务, |
By default, when you invoke a web service that returns an empty response after using a String payload for the request |
要设置入站 Web 服务网关,请使用 inbound-gateway
元素,如下例所示:
To set up an inbound Web Service Gateway, use the inbound-gateway
element, as the following example shows:
<int-ws:inbound-gateway id="simpleGateway"
request-channel="inputChannel"/>
要使用 Spring OXM 转换器或非转换器,您必须提供 bean 引用。以下示例显示如何为出站转换网关提供 bean 引用:
To use Spring OXM marshallers or unmarshallers, you must provide bean references. The following example shows how to provide a bean reference for an outbound marshalling gateway:
<int-ws:outbound-gateway id="marshallingGateway"
request-channel="requestChannel"
uri="https://example.org"
marshaller="someMarshaller"
unmarshaller="someUnmarshaller"/>
以下示例显示了如何为入站转换网关提供 bean 引用:
The following example shows how to provide a bean reference for an inbound marshalling gateway:
<int-ws:inbound-gateway id="marshallingGateway"
request-channel="requestChannel"
marshaller="someMarshaller"
unmarshaller="someUnmarshaller"/>
大多数 |
Most |
对于任一类型的出站网关,你可以指定 destination-provider
属性,而不是 uri
(其中确需一项)。随后你可以引用任何 Spring Web Services DestinationProvider
实现(例如,在运行时从注册表中查找 URI)。
For either outbound gateway type, you can specify a destination-provider
attribute instead of the uri
(exactly one of them is required).
You can then reference any Spring Web Services DestinationProvider
implementation (for example, to lookup the URI from a registry at runtime).
对于任一类型的出站网关,还可以使用对任何 Spring Web Services WebServiceMessageFactory
实现的引用来配置 message-factory
属性。
For either outbound gateway type, the message-factory
attribute can also be configured with a reference to any Spring Web Services WebServiceMessageFactory
implementation.
对于简单的入站网关类型,你可以将 extract-payload
属性设置为 false
,以便将整个 WebServiceMessage
转发,而不是将其有效负载作为 Message
转发到请求通道。这样做可能很有用,例如,当定制转换器直接适用于 WebServiceMessage
时。
For the simple inbound gateway type, you can set the extract-payload
attribute to false
to forward the entire WebServiceMessage
instead of just its payload as a Message
to the request channel.
Doing so might be useful, for example, when a custom transformer works against the WebServiceMessage
directly.
从版本 5.0 开始,web-service-template
引用属性允许你注入具有任何可能的定制属性的 WebServiceTemplate
。
Starting with version 5.0, the web-service-template
reference attribute lets you inject a WebServiceTemplate
with any possible custom properties.
Web Service Java DSL Support
在 Web Service Namespace Support 中展示的网关的等效配置在以下代码段中展示:
The equivalent configuration for the gateways shown in Web Service Namespace Support are shown in the following snippets:
@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
)。示例:
Other properties can be set on the endpoint specs in a fluent manner (with the properties depending on whether an external WebServiceTemplate
has been provided for outbound gateways).
Examples:
.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))
)
Outbound URI Configuration
对于 Spring Web Services 支持的所有 URI 方案(参见 URIs and Transports),均提供了 <uri-variable/>
替换。以下示例展示如何定义它:
For all URI schemes supported by Spring Web Services (see URIs and Transports) <uri-variable/>
substitution is provided.
The following example shows how to define it:
<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
,则不支持变量替换,并且如果你提供变量,就会发生配置错误。
If you supply a DestinationProvider
, variable substitution is not supported and a configuration error occurs if you provide variables.
Controlling URI Encoding
在将请求发送出去之前,URL 字符串默认编码为(参见 UriComponentsBuilder
)URI 对象。在一些具有非标准 URI 的场景中,最好不要执行编码。 <ws:outbound-gateway/>
元素提供了一个 encoding-mode
属性。要禁用对 URL 的编码,请将此属性设置为 NONE
(默认情况下,它为 TEMPLATE_AND_VALUES
)。如果你希望对某些 URL 部分进行编码,你可以通过在 <uri-variable/>
中使用 expression
来执行此操作,如下面的示例所示:
By default, the URL string is encoded (see UriComponentsBuilder
) to the URI object before sending the request.
In some scenarios with a non-standard URI, it is undesirable to perform the encoding.
The <ws:outbound-gateway/>
element provides an encoding-mode
attribute.
To disable encoding the URL, set this attribute to NONE
(by default, it is TEMPLATE_AND_VALUES
).
If you wish to partially encode some of the URL, you can do so by using an expression
within a <uri-variable/>
, as the following example shows:
<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>
如果你设置 |
If you set |
WS Message Headers
Spring Integration Web 服务网关自动映射 SOAP 操作标头。在默认情况下,它会使用 DefaultSoapHeaderMapper
来将标头从 Spring Integration MessageHeaders
复制到 Spring Integration MessageHeaders
,反之亦然。
The Spring Integration web service gateways automatically map the SOAP action header.
By default, it is copied to and from Spring Integration MessageHeaders
by using the DefaultSoapHeaderMapper
.
你可以传入你自己的 SOAP 特定头映射程序的实现,因为网关具有支持此操作的属性。
You can pass in your own implementation of SOAP-specific header mappers, as the gateways have properties to support doing so.
除非显式指定 DefaultSoapHeaderMapper
的 requestHeaderNames
或 replyHeaderNames
属性,否则任何用户定义的 SOAP 头都不会复制到 SOAP 消息中或从 SOAP 消息中复制。
Unless explicitly specified by the requestHeaderNames
or replyHeaderNames
properties of the DefaultSoapHeaderMapper
, any user-defined SOAP headers are not copied to or from a SOAP Message.
当你使用 XML 命名空间进行配置时,可以使用 mapped-request-headers
和 mapped-reply-headers
属性设置这些属性,你可以通过设置 header-mapper
属性提供一个定制的映射器。
When you use the XML namespace for configuration, you can set these properties by using the mapped-request-headers
and mapped-reply-headers
attributes, you can provide a custom mapper by setting the header-mapper
attribute.
当映射用户自定义头部时,值也可以包含简单的通配符号模式(例如 |
When mapping user-defined headers, the values can also contain simple wildcard patterns (such |
从版本 4.1 开始,AbstractHeaderMapper
(一个 DefaultSoapHeaderMapper
超类)允许在 requestHeaderNames
和 replyHeaderNames
属性中配置 NON_STANDARD_HEADERS
令牌(除了现有的 STANDARD_REQUEST_HEADERS
和 STANDARD_REPLY_HEADERS
)以映射所有用户定义的头。
Starting with version 4.1, the AbstractHeaderMapper
(a DefaultSoapHeaderMapper
superclass) lets the NON_STANDARD_HEADERS
token be configured for the requestHeaderNames
and replyHeaderNames
properties (in addition to existing STANDARD_REQUEST_HEADERS
and STANDARD_REPLY_HEADERS
) to map all user-defined headers.
与其使用通配符号 ( |
Rather than using the wildcard ( |
从版本 4.3 开始,你可以通过在模式前加上 !
来取消头映射中的模式。取消的模式具有优先级,因此诸如 STANDARD_REQUEST_HEADERS,thing1,thing*,!thing2,!thing3,qux,!thing1
的列表不会映射 thing1
、thing2
或 thing3
。它确实映射标准头、thing4
和 qux
。(注意 thing1
同时包含在未取消和已取消的形式中。由于已取消的值优先,因此 thing1
未被映射。)
Starting with version 4.3, you can negate patterns in the header mappings by preceding the pattern with !
.
Negated patterns get priority, so a list such as STANDARD_REQUEST_HEADERS,thing1,thing*,!thing2,!thing3,qux,!thing1
does not map thing1
, thing2
, or thing3
.
It does map the standard headers, thing4
, and qux
.
(Note that thing1
is included in both non-negated and negated forms.
Because negated values take precedence, thing1
is not mapped.)
如果你有一个以 !
开头的你要映射的用户自定义头部,那么你可以使用 \
对其进行转义,如下所示:STANDARD_REQUEST_HEADERS,\!myBangHeader
。然后映射到 !myBangHeader
。
If you have a user-defined header that begins with !
that you do wish to map, you can escape it with \
, as follows: STANDARD_REQUEST_HEADERS,\!myBangHeader
.
A !myBangHeader
is then mapped.
入站 SOAP 头(入站网关的请求头和出站网关的应答头)映射为 SoapHeaderElement
对象。你可以通过访问 Source
来浏览内容:
Inbound SOAP headers (request headers for the inbound gateway and reply headers for the outbound gateway) are mapped as SoapHeaderElement
objects.
You can explore the contents by accessing the 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
。
If mapped-request-headers
is auth, ca*
, the auth
, cat
, and can
headers are mapped, but qux
is not mapped.
以下示例展示了如何从名为 auth
的头中获取名为 user
的值:
The following example shows how to get a value named user
from a header named 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>
的子节点。以下示例展示了如何执行此操作:
Starting with version 5.0, the DefaultSoapHeaderMapper
supports user-defined headers of type javax.xml.transform.Source
and populates them as child nodes of the <soapenv:Header>
.
The following example shows how to do so:
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 规范:
The result of the preceding examples is the following SOAP envelope:
<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>
MTOM Support
规范边界传入和传出 Web 服务网关直接通过规范器的内置功能支持附件(例如,Jaxb2Marshaller
提供 mtomEnabled
选项)。从版本 5.0 开始,简单的 Web 服务网关可以直接操作传入和传出 MimeMessage
实例,该实例有一个 API 用于操作附件。当您需要发送带附件的 Web 服务消息(无论是服务器回复还是客户端请求)时,您都应直接使用 WebServiceMessageFactory
并发送带有附件的 WebServiceMessage
作为网关请求或回复通道中的`payload`。以下示例演示如何执行此操作:
The marshalling inbound and outbound web service gateways support attachments directly through built-in functionality of the marshaller (for example, Jaxb2Marshaller
provides the mtomEnabled
option).
Starting with version 5.0, the simple web service gateways can directly operate with inbound and outbound MimeMessage
instances, which have an API to manipulate attachments.
When you need to send web service message with attachments (either a reply from a server or a client request) you should use the WebServiceMessageFactory
directly and send a WebServiceMessage
with attachments as a payload
to the request or reply channel of the gateway.
The following example shows how to do so:
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));