构成 Spring Web 服务的各种组件(二)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构成 Spring Web 服务的各种组件(二)相关的知识,希望对你有一定的参考价值。
6. 在客户端上使用 Spring Web 服务
Spring-WS提供了一个客户端Web服务API,允许对Web服务进行一致的XML驱动访问。它还迎合了编组程序和取消编组程序的使用,以便服务层代码可以专门处理 Java 对象。
该包提供了使用客户端访问 API 的核心功能。它包含简化Web服务的使用的模板类,就像Spring核心对JDBC所做的那样。Spring 模板类的共同设计原则是提供辅助方法来执行常见操作,并且对于更复杂的用法,委托给用户实现的回调接口。Web 服务模板遵循相同的设计。这些类提供了各种方便的方法org.springframework.ws.client.core
JdbcTemplate
- 发送和接收 XML 消息
- 在发送之前将对象封送到 XML
- 允许多种运输选择
6.1. 使用客户端 API
本节介绍如何使用客户端 API。有关如何使用服务器端 API,请参阅 使用 Spring-WS 创建 Web 服务。
6.1.1.WebServiceTemplate
这是 Spring-WS 中客户端 Web 服务访问的核心类。它包含用于发送对象和接收响应消息作为 or 的方法。此外,它可以在通过传输发送对象之前将对象封送到 XML,并再次将任何响应 XML 取消封送到对象中。WebServiceTemplate
Source
Source
Result
URI 和传输
该类使用 URI 作为消息目标。可以在模板本身上设置属性,也可以在模板上调用方法时显式提供 URI。URI 解析为 ,负责跨传输层发送 XML 消息。可以使用类的 or 属性设置一个或多个邮件发件人。WebServiceTemplate
defaultUri
WebServiceMessageSender
messageSender
messageSenders
WebServiceTemplate
HTTP 传输
有两种用于通过 HTTP 发送消息的接口实现。默认实现是 ,它使用 Java 本身提供的工具。另一种方法是使用 Apache HttpComponents HttpClient。如果需要更高级且易于使用的功能(如身份验证、HTTP 连接池等),请使用后者。WebServiceMessageSender
HttpUrlConnectionMessageSender
HttpComponentsMessageSender
若要使用 HTTP 传输,请将 设置为 like 或为其中一个方法提供参数。defaultUri
http://example.com/services
uri
以下示例演示如何使用 HTTP 传输的默认配置:
<beans>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="defaultUri" value="http://example.com/WebService"/>
</bean>
</beans>
以下示例演示如何覆盖默认配置以及如何使用 Apache HttpClient 通过 HTTP 身份验证进行身份验证:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="credentials">
<bean class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg value="john:secret"/>
</bean>
</property>
</bean>
</property>
<property name="defaultUri" value="http://example.com/WebService"/>
</bean>
联医系统传输
为了通过JMS发送消息,Spring Web Services提供了.这个类使用Spring框架的功能将JMS转换为JMS,在或上发送它,并接收响应(如果有的话)。JmsMessageSender
WebServiceMessage
Message
Queue
Topic
要使用 ,您需要将 or 参数设置为 JMS URI,该 URI 至少由前缀和目标名称组成。JMS URI 的一些示例包括:、 和 。有关此 URI 语法的更多信息,请参阅 Javadoc for JmsMessageSender。JmsMessageSender
defaultUri
uri
jms:
jms:SomeQueue
jms:SomeTopic?priority=3&deliveryMode=NON_PERSISTENT
jms:RequestQueue?replyToName=ResponseName
默认情况下,发送 JMS ,但您可以使用 JMS URI 上的参数覆盖它以使用,例如 。请注意,这是首选类型,因为 不支持附件和字符编码。JmsMessageSender
BytesMessage
TextMessages
messageType
jms:Queue?messageType=TEXT_MESSAGE
BytesMessages
TextMessages
以下示例显示如何将 JMS 传输与 ActiveMQ 连接工厂结合使用:
<beans>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
</bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
</property>
<property name="defaultUri" value="jms:RequestQueue?deliveryMode=NON_PERSISTENT"/>
</bean>
</beans>
电子邮件传输
Spring Web Services 还提供了电子邮件传输,您可以使用它通过 SMTP 发送 Web 服务消息,并通过 POP3 或 IMAP 检索它们。客户端电子邮件功能包含在类中。此类从请求创建电子邮件,并通过 SMTP 发送。然后,它等待响应消息到达传入的 POP3 或 IMAP 服务器。MailMessageSender
WebServiceMessage
要使用 ,请将 or 参数设置为 URI,例如 or 。确保邮件发件人正确配置了 ,前者指示用于发送请求的服务器(通常是 SMTP 服务器),后者指示要轮询响应的服务器(通常为 POP3 或 IMAP 服务器)。MailMessageSender
defaultUri
uri
mailto
mailto:john@example.com
mailto:server@localhost?subject=SOAP%20Test
transportUri
storeUri
以下示例演示如何使用电子邮件传输:
<beans>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.mail.MailMessageSender">
<property name="from" value="Spring-WS SOAP Client <client@example.com>"/>
<property name="transportUri" value="smtp://client:s04p@smtp.example.com"/>
<property name="storeUri" value="imap://client:s04p@imap.example.com/INBOX"/>
</bean>
</property>
<property name="defaultUri" value="mailto:server@example.com?subject=SOAP%20Test"/>
</bean>
</beans>
XMPP 运输
Spring Web Services 2.0引入了XMPP(Jabber)传输,您可以使用它通过XMPP发送和接收Web服务消息。客户端 XMPP 功能包含在类中。此类从请求创建 XMPP 消息,并通过 XMPP 发送该消息。然后,它会侦听响应消息到达。XmppMessageSender
WebServiceMessage
要使用 ,请将 or 参数设置为 URI,例如 。发送方还需要 才能工作,可以使用 .XmppMessageSender
defaultUri
uri
xmpp
xmpp:johndoe@jabber.org
XMPPConnection
org.springframework.ws.transport.xmpp.support.XmppConnectionFactoryBean
以下示例演示如何使用 XMPP 传输:
<beans>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="connection" class="org.springframework.ws.transport.xmpp.support.XmppConnectionFactoryBean">
<property name="host" value="jabber.org"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.xmpp.XmppMessageSender">
<property name="connection" ref="connection"/>
</bean>
</property>
<property name="defaultUri" value="xmpp:user@jabber.org"/>
</bean>
</beans>
消息工厂
除了消息发送者之外,还需要 Web 服务消息工厂。SOAP 有两个消息工厂:和 。如果未指定消息工厂(通过设置属性),则默认情况下 Spring-WS 使用 。WebServiceTemplate
SaajSoapMessageFactory
AxiomSoapMessageFactory
messageFactory
SaajSoapMessageFactory
6.1.2. 发送和接收WebServiceMessage
包含许多发送和接收 Web 服务消息的便捷方法。有接受并返回 a 的方法,也有返回 .此外,还有一些方法可以将对象封送和取消封送到 XML。下面的示例将简单的 XML 消息发送到 Web 服务:WebServiceTemplate
Source
Result
import java.io.StringReader;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;
public class WebServiceClient
private static final String MESSAGE =
"<message xmlns=\\"http://tempuri.org\\">Hello, Web Service World</message>";
private final WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
public void setDefaultUri(String defaultUri)
webServiceTemplate.setDefaultUri(defaultUri);
// send to the configured default URI
public void simpleSendAndReceive()
StreamSource source = new StreamSource(new StringReader(MESSAGE));
StreamResult result = new StreamResult(System.out);
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
// send to an explicit URI
public void customSendAndReceive()
StreamSource source = new StreamSource(new StringReader(MESSAGE));
StreamResult result = new StreamResult(System.out);
webServiceTemplate.sendSourceAndReceiveToResult("http://localhost:8080/AnotherWebService",
source, result);
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="webServiceClient" class="WebServiceClient">
<property name="defaultUri" value="http://localhost:8080/WebService"/>
</bean>
</beans>
前面的示例使用 将“Hello, World”消息发送到位于(在方法的情况下)的 Web 服务,并将结果写入控制台。注入了缺省 URI,之所以使用该 URI,是因为 Java 代码中没有显式提供 URI。WebServiceTemplate
http://localhost:8080/WebService
simpleSendAndReceive()
WebServiceTemplate
请注意,该类一旦配置,就是线程安全的(假设它的所有依赖项也是线程安全的,Spring-WS 附带的所有依赖项都是这种情况),因此多个对象可以使用同一个共享实例。它公开了一个零参数构造函数和 Bean 属性,您可以使用这些构造函数和 Bean 属性(通过使用 Spring 容器或纯 Java 代码)。或者,考虑从 Spring-WS 的便利基类派生,该基类公开了方便的 Bean 属性以实现轻松配置。(您不必扩展此基类。它仅作为便利类提供。WebServiceTemplate
WebServiceTemplate
WebServiceTemplate
messageFactory
messageSender
WebServiceGatewaySupport
6.1.3. 发送和接收 POJO — 编组和解组
为了便于发送纯 Java 对象,有许多方法将 a 作为消息数据内容的参数。类中的方法将请求对象到 XML 的转换委托给 ,并将响应 XML 到对象的转换委托给 。(有关编组和取消编组器的更多信息,请参阅 Spring 框架参考文档。通过使用封送器,应用程序代码可以专注于正在发送或接收的业务对象,而不关心它如何表示为 XML 的详细信息。若要使用编组功能,必须使用类的 and 属性设置编组器和取消编组器。WebServiceTemplate
send(..)
Object
marshalSendAndReceive(..)
WebServiceTemplate
Marshaller
Unmarshaller
marshaller
unmarshaller
WebServiceTemplate
6.1.4. 使用WebServiceMessageCallback
为了适应在消息上设置 SOAP 标头和其他设置,该接口允许您在创建消息之后但在发送消息之前访问消息。下面的示例演示如何在通过封送对象创建的消息上设置 SOAP 操作标头:WebServiceMessageCallback
public void marshalWithSoapActionHeader(MyObject o)
webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback()
public void doWithMessage(WebServiceMessage message)
((SoapMessage)message).setSoapAction("http://tempuri.org/Action");
);
请注意,您还可以使用 来设置 SOAP 操作标头。 |
WS-寻址
除了服务器端WS-Addressing支持之外,Spring Web Services在客户端也支持此规范。
要在客户端上设置 WS 寻址标头,可以使用 。此回调将所需的操作标头作为参数。它还具有用于指定 WS 寻址版本和标头的构造函数。如果未指定,则标头默认为正在建立的连接的 URL。org.springframework.ws.soap.addressing.client.ActionCallback
To
To
下面的示例将标头设置为 :Action
http://samples/RequestOrder
webServiceTemplate.marshalSendAndReceive(o, new ActionCallback("http://samples/RequestOrder"));
6.1.5. 使用WebServiceMessageExtractor
该接口是一个低级回调接口,您可以完全控制从收到的 .在与服务资源的基础连接仍处于打开状态时,在提供的 上调用该方法。以下示例显示了 in 操作:WebServiceMessageExtractor
Object
WebServiceMessage
WebServiceTemplate
extractData(..)
WebServiceMessageExtractor
WebServiceMessageExtractor
public void marshalWithSoapActionHeader(final Source s)
final Transformer transformer = transformerFactory.newTransformer();
webServiceTemplate.sendAndReceive(new WebServiceMessageCallback()
public void doWithMessage(WebServiceMessage message)
transformer.transform(s, message.getPayloadResult());
,
new WebServiceMessageExtractor()
public Object extractData(WebServiceMessage message) throws IOException
// do your own transforms with message.getPayloadResult()
// or message.getPayloadSource()
);
6.2. 客户端测试
在测试 Web 服务客户端(即使用 访问 Web 服务的类)时,有两种可能的方法:WebServiceTemplate
- 编写单元测试,模拟类、接口或完整的客户端类。
WebServiceTemplate
WebServiceOperations
这种方法的优点是很容易实现。缺点是,您并没有真正测试通过网络发送的 XML 消息的确切内容,尤其是在模拟整个客户端类时。 - 编写集成测试,测试消息的内容。
第一种方法可以通过模拟框架轻松实现,例如EasyMock,JMock等。下一节重点介绍如何使用 Spring Web Services 2.0 中引入的测试功能编写集成测试。
6.2.1. 编写客户端集成测试
Spring Web Services 2.0引入了对创建Web服务客户端集成测试的支持。在此上下文中,客户端是使用 访问 Web 服务的类。WebServiceTemplate
集成测试支持位于包中。该包中的核心类是 .基本思想是 Web 服务模板连接到此模拟服务器并向其发送请求消息,然后模拟服务器根据注册的期望对其进行验证。如果满足预期,模拟服务器将准备一条响应消息,该消息将发送回模板。org.springframework.ws.test.client
MockWebServiceServer
的典型用法是:。MockWebServiceServer
- 通过调用 、 或 创建实例。
MockWebServiceServer
MockWebServiceServer.createServer(WebServiceTemplate)
MockWebServiceServer.createServer(WebServiceGatewaySupport)
MockWebServiceServer.createServer(ApplicationContext)
- 通过调用 来设置请求期望,可能使用 中提供的默认实现(可以静态导入)。可以通过链接呼叫来设置多个期望。
expect(RequestMatcher)
RequestMatcher
RequestMatchers
andExpect(RequestMatcher)
- 通过调用 来创建适当的响应消息,可能使用 中提供的默认实现(可以静态导入)。
andRespond(ResponseCreator)
ResponseCreator
ResponseCreators
- 像往常一样使用,直接或通过客户端代码。
WebServiceTemplate
- 致电以确保满足所有期望。
MockWebServiceServer.verify()
请注意,(和相关类)提供了“流畅”的 API,因此您通常可以使用 IDE 中的代码完成功能来指导您完成设置模拟服务器的过程。 |
另请注意,在单元测试中,您可以依赖 Spring Web Services 中提供的标准日志记录功能。有时,检查请求或响应消息以找出特定测试失败的原因可能很有用。有关详细信息,请参阅消息日志记录和跟踪。 |
例如,请考虑以下 Web 服务客户端类:
public class CustomerClient extends WebServiceGatewaySupport
public int getCustomerCount()
CustomerCountRequest request = new CustomerCountRequest();
request.setCustomerName("John Doe");
CustomerCountResponse response =
(CustomerCountResponse) getWebServiceTemplate().marshalSendAndReceive(request);
return response.getCustomerCount();
扩展,这为它提供了一个属性。 |
|
使用 提供的 by 将请求对象封送到 SOAP 消息中,并将其发送到 Web 服务。响应对象被解组为 . |
以下示例显示了 的典型测试:CustomerClient
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("integration-test.xml")
public class CustomerClientIntegrationTest
@Autowired
private CustomerClient client;
private MockWebServiceServer mockServer;
@Before
public void createServer() throws Exception
mockServer = MockWebServiceServer.createServer(client);
@Test
public void customerClient() throws Exception
Source requestPayload = new StringSource(
"<customerCountRequest xmlns=http://springframework.org/spring-ws>" +
"<customerName>John Doe</customerName>" +
"</customerCountRequest>");
Source responsePayload = new StringSource(
"<customerCountResponse xmlns=http://springframework.org/spring-ws>" +
"<customerCount>10</customerCount>" +
"</customerCountResponse>");
mockServer.expect(payload(requestPayload)).andRespond(withPayload(responsePayload));
int result = client.getCustomerCount();
assertEquals(10, result);
mockServer.verify();
导入和静态导入和 . | |
此测试使用 Spring 框架中提供的标准测试工具。这不是必需的,但通常是设置测试的最简单方法。 | |
使用 配置并连接到此测试中。 | |
在方法中,我们使用工厂方法创建一个。 | |
我们通过调用静态导入的 a 来定义期望(请参阅使用 RequestMatcher 和 RequestMatchers)。 我们还通过使用静态导入提供的调用来设置响应(请参阅使用 ResponseCreator 和 ResponseCreators)。 测试的这一部分可能看起来有点混乱,但 IDE 的代码完成功能非常有用。键入 后,IDE 可以为您提供可能的请求匹配策略列表,前提是静态导入 。这同样适用于 ,前提是您静态导入 。 | |
我们调用 ,因此使用 .到目前为止,模板已设置为“测试模式”,因此此方法调用不会建立真正的 (HTTP) 连接。我们还根据方法调用的结果做出一些 JUnit 断言。 | |
我们调用 ,验证是否实际收到了预期的消息。 |
6.2.2. 使用 和RequestMatcher
RequestMatchers
为了验证请求消息是否满足某些期望,请使用策略接口。此接口定义的协定如下:MockWebServiceServer
RequestMatcher
public interface RequestMatcher
void match(URI uri,
WebServiceMessage request)
throws IOException,
AssertionError;
您可以编写自己的此接口实现,在消息不符合您的期望时引发异常,但您当然不必这样做。该类提供了标准实现,供您在测试中使用。通常静态导入此类。AssertionError
RequestMatchers
RequestMatcher
该类提供以下请求匹配器:RequestMatchers
| 描述 |
| 期望任何类型的请求。 |
| 需要给定的请求有效负载。 |
| 期望请求有效负载根据给定的 XSD 架构进行验证。 |
| 期望给定的 XPath 表达式存在、不存在或计算为给定值。 |
| 期望请求消息中存在给定的 SOAP 标头。 |
| 需要与给定 URL 的连接。 |
您可以通过链接调用来设置多个请求期望:andExpect()
mockServer.expect(connectionTo("http://example.com")).
andExpect(payload(expectedRequestPayload)).
andExpect(validPayload(schemaResource)).
andRespond(...);
有关 提供的请求匹配器的更多信息,请参阅 Javadoc。RequestMatchers
6.2.3. 使用 和ResponseCreator
ResponseCreators
当请求消息经过验证并满足定义的期望时,将创建响应消息供 使用。服务器使用策略接口来实现此目的:MockWebServiceServer
WebServiceTemplate
ResponseCreator
public interface ResponseCreator
WebServiceMessage createResponse(URI uri,
以上是关于构成 Spring Web 服务的各种组件(二)的主要内容,如果未能解决你的问题,请参考以下文章
HTTP -- 认识HTTP和HTTP相关组件(网络模型游览器Web服务器CDNWAFWeb ServiceHTMLWeb页面的构成)