2

Spring 集成对 Web 服务的支持

 1 year ago
source link: https://blog.51cto.com/u_15326439/5938519
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Spring 集成对 Web 服务的支持_ide

本章描述了 Spring 集成对 Web 服务的支持,包括:

  • 出站 Web 服务网关
  • 入站 Web 服务网关
  • Web 服务命名空间支持
  • 出站 URI 配置
  • WS 消息头
  • MTOM 支持

您需要将此依赖项包含在项目中:

<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-ws</artifactId>
<version>6.0.0</version>
</dependency>

出站 Web 服务网关

要在向通道发送消息时调用 Web 服务,您有两个选项,这两个选项都基于 Spring Web 服务项目构建:和 。 前者接受 或 作为消息有效负载。 后者支持 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 开始,您可以为 和 提供一个外部实例,您可以为任何自定义属性配置该实例,包括(允许应用程序处理不符合标准的服务)。​​SimpleWebServiceOutboundGateway​​​​MarshallingWebServiceOutboundGateway​​​​WebServiceTemplate​​​​checkConnectionForFault​

有关内部工作的更多详细信息,请参阅 Spring Web 服务参考指南中介绍客户端访问的章节和涵盖对象/XML 映射的章节。

入站 Web 服务网关

要在收到 Web 服务调用时向通道发送消息,您还有两个选项:和 。 前者从中提取 并将其设置为消息有效负载。 后者支持 和 接口的实现。 如果传入的 Web 服务消息是 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 映射算法引用 and/或 Bean 定义。​​SimpleWebServiceInboundGateway​​​​MarshallingWebServiceInboundGateway​

有关详细信息,请参阅终结点映射。

Web 服务命名空间支持

若要配置出站 Web 服务网关,请使用命名空间中的元素,如以下示例所示:​​outbound-gateway​​​​ws​

<int-ws:outbound-gateway id="simpleGateway"
request-channel="inputChannel"
uri="https://example.org"/>

此示例不提供“回复通道”。 如果 Web 服务返回非空响应,则包含该响应的响应将发送到请求消息标头中定义的回复通道。 如果不可用,则会引发通道解析异常。 如果要将回复发送到另一个通道,请在“出站网关”元素上提供“回复通道”属性。​​Message​​​​REPLY_CHANNEL​

默认情况下,当您调用在对请求使用 String 有效负载后返回空响应的 Web 服务时,不会发送任何回复。 因此,您无需在请求中设置“回复通道”或标头。 如果您确实希望以 的形式接收空响应,则可以将“忽略空响应”属性设置为 。 这样做仅适用于对象,因为使用 a 或 对象会导致空响应,因此永远不会生成回复。​​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 服务实现(例如,在运行时从注册表中查找 URI)。​​destination-provider​​​​uri​​​​DestinationProvider​

对于任一出站网关类型,还可以使用对任何 Spring Web 服务实现的引用来配置该属性。​​message-factory​​​​WebServiceMessageFactory​

对于简单入站网关类型,您可以将属性设置为 将整个(而不仅仅是其有效负载)作为 转发到请求通道。 这样做可能很有用,例如,当自定义转换器直接针对​​extract-payload​​​​false​​​​WebServiceMessage​​​​Message​​​​WebServiceMessage​

从版本 5.0 开始,引用属性允许您注入任何可能的自定义属性。​​web-service-template​​​​WebServiceTemplate​

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 字符串被编码(请参阅 UriComponentsBuilder)到 URI 对象。 在某些具有非标准 URI 的情况下,不希望执行编码。 该元素提供一个属性。 要禁用对 URL 进行编码,请将此属性设置为 (默认情况下为 )。 如果要对某些 URL 进行部分编码,可以使用 in in 来执行此操作,如以下示例所示:​​<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​

WS 消息头

Spring 集成 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 开始,(超类)允许为 和 属性(除了现有和)配置令牌,以映射所有用户定义的标头。​​AbstractHeaderMapper​​​​DefaultSoapHeaderMapper​​​​NON_STANDARD_HEADERS​​​​requestHeaderNames​​​​replyHeaderNames​​​​STANDARD_REQUEST_HEADERS​​​​STANDARD_REPLY_HEADERS​

我们建议使用以下组合,而不是使用通配符 (): 这样做可避免将标头映射到回复。​​*​​​​STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS​​​​request​

从版本 4.3 开始,您可以通过在标头映射前面加上 来否定标头映射中的模式。 否定模式获得优先级,因此诸如 not 映射 、 或 的列表。 它确实映射了标准标头、 和 。 (请注意,这包含在非否定形式和否定形式中。 因为否定值优先,所以不会映射。​​!​​​​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>

MTOM 支持

封送入站和出站 Web 服务网关通过封送器的内置功能直接支持附件(例如,提供选项)。 从版本 5.0 开始,简单的 Web 服务网关可以直接使用入站和出站实例进行操作,这些实例具有用于操作附件的 API。 当您需要发送带有附件的 Web 服务消息(来自服务器的回复或客户端请求)时,您应该直接使用 并将带有附件的 a 作为 发送到网关的请求或回复通道。 以下示例演示如何执行此操作:​​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));

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK