spring web service 2

spring-ws服务端

MessageDispatcher

spring-ws服务端的核心是MessageDispatcher,它接收并转发webservice请求到@Endpoint上去。spring-ws处理XML极其灵活,一个endpoint可以处理DOM家族的W3C DOM,JDOM,dom4j,XOM,也可以处理性能较好的SAX和StAX,还可以处理通过XPath从消息中获取信息,甚至是像JAXB,Castor,XMLBeans,JiBX,XStream的编组技术实现对象与XML的互相转换。

MessageDispatcher的处理流程图

sequence.png

  1. 通过搜索EndpointMappings找到合适的endpoint,执行调用链(pre-processors, post-processors, and endpoints) ;
  2. 搜索Adaptor,MessageDispatcher委派Adaptor调用endpoint;
  3. 原路径返回响应消息。

消息转发运行在message context上,并不传输特定的输入输出流,因此特定的传输需要读入到MessageContext中。HTTP传输是通过一个Spring Web的HandlerIntercepor,WebServiceMessageReceiverHandlerAdapter来实现的,通过MessageDispatcherServlet来转发请求。

传输

spring-ws支持多种传输协议,一般使用HTTP传输,也可以支持JMS和email。

MessageDispatcherServlet

MessageDispatcherServlet是一个标准的Servlet,与spring web的DispatcherServlet的使用方式相同,它是MessageDispather的包装实现。

MessageDispatcherServlet可以通过设置transformWsdlLocations属性为true来动态发布WSDL。

嵌入式HTTP服务器

spring-ws提供了一种基于JRE1.6的HTTP服务器的传输方式。这种方式使用比较简单,不需要任何外部的依赖,只需要定义一个服务器实例来处理请求即可。HTTP的一个关键工厂Bean是:SimpleHttpServerFactoryBean

spring-ws中两个处理htpp的重要类:WsdlDefinitionHttpHandlerWebServiceMessageReceiverHttpHandler

  • WsdlDefinitionHttpHandler负责处理获取WsdlDefinition的GET请求
  • WebServiceMessageReceiverHttpHandler通过WebServiceMessageFactory(通常是SaajSoapMessageFactory)和WebServiceMessageReceiver(通常是SoapMessageDispatcher)来处理webservice请求。

简单的配置实例:

<beans>

    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>

    <bean id="messageReceiver" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
        <property name="endpointMappings" ref="endpointMapping"/>
    </bean>

    <bean id="endpointMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="defaultEndpoint" ref="stockEndpoint"/>
    </bean>

    <bean id="httpServer" class="org.springframework.remoting.support.SimpleHttpServerFactoryBean">
        <property name="contexts">
            <map>
                <entry key="/StockService.wsdl" value-ref="wsdlHandler"/>
                <entry key="/StockService" value-ref="soapHandler"/>
            </map>
        </property>
    </bean>

    <bean id="soapHandler" class="org.springframework.ws.transport.http.WebServiceMessageReceiverHttpHandler">
        <property name="messageFactory" ref="messageFactory"/>
        <property name="messageReceiver" ref="messageReceiver"/>
    </bean>

    <bean id="wsdlHandler" class="org.springframework.ws.transport.http.WsdlDefinitionHttpHandler">
        <property name="definition" ref="wsdlDefinition"/>
    </bean>
</beans>

XMPP传输

spring-ws2.0开始引入了XMPP(Jabber),基于Smack类库。

spring-ws XMPP使用方式类似于其他协议,WebServiceTemplate通过XmppMessageSende发送消息, MessageDispatcher转发消息给XmppMessageReceiver

简单配置实例:

<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="messagingReceiver" class="org.springframework.ws.transport.xmpp.XmppMessageReceiver">
        <property name="messageFactory" ref="messageFactory"/>
        <property name="connection" ref="connection"/>
        <property name="messageReceiver" ref="messageDispatcher"/>
    </bean>

    <bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
        <property name="endpointMappings">
            <bean
              class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
                <property name="defaultEndpoint">
                    <bean class="com.example.MyEndpoint"/>
                </property>
            </bean>
        </property>
    </bean>

</beans>

Endpoints

Endpoints是spring-ws服务端的核心概念,spring-ws通过Endpoints来定义服务端动作,来接收处理XML请求,并生成响应XML。spring-ws处理和响应XML方式有很多种方式。

可以通过@Endpoint注解来创建endpoint,每一个endpoint都可以定义多个处理请求的方法(支持前面章节提到的所有xml),一般通过@PayloadRoot可以指定每一个方法处理哪一类的消息,

实例:

package samples;

import org.w3c.dom.Element;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.soap.SoapHeader;

@Endpoint                                                                                      
public class AnnotationOrderEndpoint {

  private final OrderService orderService;

  @Autowired                                                                                   
  public AnnotationOrderEndpoint(OrderService orderService) {
      this.orderService = orderService;
  }

  @PayloadRoot(localPart = "order", namespace = "http://samples")                              
  public void order(@RequestPayload Element orderElement) {                                    
    Order order = createOrder(orderElement);
    orderService.createOrder(order);
  }

  @PayloadRoot(localPart = "orderRequest", namespace = "http://samples")                       
  @ResponsePayload
  public Order getOrder(@RequestPayload OrderRequest orderRequest, SoapHeader header) {        
    checkSoapHeaderForSomething(header);
    return orderService.getOrder(orderRequest.getId());
  }

  ...

}
  • order方法通过@RequestPayload注解的Element为请求参数,是一个DOM的Element,该方法void即没有响应。
  • getOrder请求参数是OrderRequest,OrderReqeust应当是一个通过@XmlRootElement注解的JAXB2对象,参数SoapHeader表示请求报文里面需要包含SOAP头信息。ResponsePayload表示getOrder会有个Order类型的响应。

XML配置方式的spring项目,需要配置启用webserivce的驱动

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:sws="http://www.springframework.org/schema/web-services"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/web-services
      http://www.springframework.org/schema/web-services/web-services.xsd">

  <sws:annotation-driven />

</beans>

@Configuration配置方式,则增加@EnableWs注解即可

@EnableWs
@Configuration
public class SpringWsConfig  extends WsConfigurerAdapter {

    // @Bean definitions go here
    
     @Override
  public void addInterceptors(List<EndpointInterceptor> interceptors) {
    interceptors.add(new MyInterceptor());
  }

  @Override
  public void addArgumentResolvers(List<MethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(new MyArgumentResolver());
  }
    
     // More overridden methods ...

}

Endpoints中的处理消息的方法

通过@RequestPayload注解将请求消息映射到载体中。

下表展示了消息处理支持的参数类型,以及是否应该被@RequestPayload注解修饰。

Name Supported parameter types @RequestPayload required? Additional notes
TrAX javax.xml.transform.Source and sub-interfaces (DOMSource, SAXSource, StreamSource, and StAXSource) Yes Enabled by default.
W3C DOM org.w3c.dom.Element Yes Enabled by default
dom4j org.dom4j.Element Yes Enabled when dom4j is on the classpath.
JDOM org.jdom.Element Yes Enabled when JDOM is on the classpath.
XOM nu.xom.Element Yes Enabled when XOM is on the classpath.
StAX javax.xml.stream.XMLStreamReader and javax.xml.stream.XMLEventReader Yes Enabled when StAX is on the classpath.
XPath Any boolean, double, String, org.w3c.Node, org.w3c.dom.NodeList, or type that can be converted from a String by a Spring 3 conversion service, and that is annotated with @XPathParam. No Enabled by default, see the section called XPathParam.
Message context org.springframework.ws.context.MessageContext No Enabled by default.
SOAP org.springframework.ws.soap.SoapMessage, org.springframework.ws.soap.SoapBody, org.springframework.ws.soap.SoapEnvelope, org.springframework.ws.soap.SoapHeader, and org.springframework.ws.soap.SoapHeaderElements when used in combination with the @SoapHeader annotation. No Enabled by default.
JAXB2 Any type that is annotated with javax.xml.bind.annotation.XmlRootElement, and javax.xml.bind.JAXBElement. Yes Enabled when JAXB2 is on the classpath.
OXM Any type supported by a Spring OXM Unmarshaller. Yes Enabled when the unmarshaller attribute of <sws:annotation-driven/> is specified.

代码示例:

public void handle(@RequestPayload Element element)
public void handle(@RequestPayload DOMSource domSource, SoapHeader header)
public void handle(@RequestPayload MyJaxb2Object requestObject, @RequestPayload Element element, Message messageContext)

如需扩展自定义参数类型,则需要参见DefaultMethodEndpointAdapterMethodArgumentResolver

@XPathParam补充说明

通过XPath标注指定节点,取得指定节点的值,以便完成相应的操作。

package samples;

import javax.xml.transform.Source;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.Namespace;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.XPathParam;

@Endpoint
public class AnnotationOrderEndpoint {

  private final OrderService orderService;

  public AnnotationOrderEndpoint(OrderService orderService) {
    this.orderService = orderService;
  }

  @PayloadRoot(localPart = "orderRequest", namespace = "http://samples")
  @Namespace(prefix = "s", uri="http://samples")
  public Order getOrder(@XPathParam("/s:orderRequest/@id") int orderId) {
    Order order = orderService.getOrder(orderId);
    // create Source from order and return it
  }

}

使用@XPathParam注解的情况下,XPath支持的数据类型

  • boolean or Boolean
  • double or Double
  • String
  • Node
  • NodeList

消息处理方法的返回类型

又返回消息的处理方法,需要明确指定返回类型,并使用@ResponsePayload注解该方法。

下表展示了支持的返回类型,以及是否应该被@ResponsePayload注解标注。

Name Supported return types @ResponsePayload required? Additional notes
No response void No Enabled by default.
TrAX javax.xml.transform.Source and sub-interfaces (DOMSource, SAXSource, StreamSource, and StAXSource) Yes Enabled by default.
W3C DOM org.w3c.dom.Element Yes Enabled by default
dom4j org.dom4j.Element Yes Enabled when dom4j is on the classpath.
JDOM org.jdom.Element Yes Enabled when JDOM is on the classpath.
XOM nu.xom.Element Yes Enabled when XOM is on the classpath.
JAXB2 Any type that is annotated with javax.xml.bind.annotation.XmlRootElement, and javax.xml.bind.JAXBElement. Yes Enabled when JAXB2 is on the classpath.
OXM Any type supported by a Spring OXM Marshaller. Yes Enabled when the marshaller attribute of <sws:annotation-driven/> is specified.

Endpoint mappings

Endpoint mapping负责映射请求到对应的endpoints上。

每一个EndpointMapping都会提供一个EndpointInvocationChain,即endpoint的调用链。EndpointInvocationChain持有endpoint的对应请求,以及请求和响应的拦截器列表。当一个请求进来时,MessageDispacher会让对应的endpoint mapping来检查请求并创建合适的EndpointInvocationChain,然后MessageDispacher调用endpoint和调用链上的所有拦截器。

Interceptors拦截器,虽然是endpoint mapping的可选配置,但是它可以提供非常丰富的自定义功能。比如可以通过拦截器使得一个endpoint不仅仅支持基础消息处理,还可以按需制定SOAP消息头。

大部分的endpoint mapping都继承自AbstractEndpointMapping,在AbstractEndpointMapping中定义了一个interceptors的属性,持有了调用链中可供使用的拦截器列表。

每一个endpoint可以处理一个或多个请求,这个特性由MethodEndpoitMapping负责完成。如以下两个endpoint mapping可以直接是请求指向方法(需要通过<sws:annotation-driven/>配置使之生效):

  • PayloadRootAnnotationMethodEndpointMapping,通过使用@PayloadRoot注解和localPartnamespace标注方法,使得持有指定根元素名称的消息可以请求到。
  • SoapActionAnnotationMethodEndpointMapping,通过使用@SoapAction注解来标注方法支持指定的SOAP动作,使得持有指定SOAPAction消息头的请求可以调用到。

WS-Addressing

WS-Addressing用来指定和传输无关的路由机制。通过SOAP消息头中的ToAction来指明SOAP消息的目的地址和动作。同时WS-Addressing也允许定义消息返回地址(处理正常响应和错误的地址,默认是没有消息返回地址,即消息原路返回或者没有返回)和一个与消息关联的唯一messageID。

在spring-ws中,WS-Addressing是一个endpoint mapping的实现,通过映射,可以将WS-Addressing的actions和endpoint关联在一起,与SoapActionAnnotationMethodEndpointMapping类似。

spring-ws对WS-Addressing的实现是AnnotationActionMethodMapping类,它与SoapActionAnnotationMethodEndpointMapping类似,但是没有继续使用SOAP Action的消息头,而是使用WS-Addressing的消息头,通过@Action注解来标注方法,使用方式与@PayloadRoot@SoapAction注解类似。

package samples;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.addressing.server.annotation.Action

@Endpoint
public class AnnotationOrderEndpoint {
    private final OrderService orderService;

    public AnnotationOrderEndpoint(OrderService orderService) {
        this.orderService = orderService;
    }

    @Action("http://samples/RequestOrder")
    public Order getOrder(OrderRequest orderRequest) {
        return orderService.getOrder(orderRequest.getId());
    }

    @Action("http://samples/CreateOrder")
    public void order(Order order) {
        orderService.createOrder(order);
    }

}

另外,在使用@Action注解时,如果类上使用了@Address注解,请求进来时会匹配To属性。

给指定消息返回地址返回消息时,还需要设置messageSenders属性,可以在MessageSender中实现,类似于WebServiceTemplate中实现的一样。

EndpointIntercepor

所有的拦截前都需要实现org.springframework.ws.server.EndpointInterceptor接口,该接口只定义了四个方法,一个处理进入真正的endpoit前的请求,一个处理响应消息,一个处理错误,最后一个在请求响应处理流程结束后执行。

package org.springframework.ws.server;

import org.springframework.ws.context.MessageContext;
public interface EndpointInterceptor {
    /**
     * 真正进入endpoint之前执行,可以提前结束请求,并自定义响应
     */
    boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception;

    /**
     * 在响应的时候执行,只有endpoint成功执行,并返回时才会执行
     */
    boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception;

    /**
     * 出现错误时执行
     */
    boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception;

    /**
     * 在请求和响应流程结束后执行
     * @since 2.0.2
     */
    void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception;
}

XML中拦截器的配置示例

<sws:interceptors>
  <bean class="samples.MyGlobalInterceptor"/>
  <sws:payloadRoot namespaceUri="http://www.example.com">
    <bean class="samples.MyPayloadRootInterceptor"/>
  </sws:payloadRoot>
  <sws:soapAction value="http://www.example.com/SoapAction">
    <bean class="samples.MySoapActionInterceptor1"/>
    <ref bean="mySoapActionInterceptor2"/>
  </sws:soapAction>
</sws:interceptors>

<bean id="mySoapActionInterceptor2" class="samples.MySoapActionInterceptor2"/>

@Configuration拦截器配置方式

@Configuration
@EnableWs
public class MyWsConfiguration extends WsConfigurerAdapter {

  @Override
  public void addInterceptors(List<EndpointInterceptor> interceptors) {
    interceptors.add(new MyPayloadRootInterceptor());
  }

}

sping-ws提供了一些标准的拦截器实现。

关于日志的两个拦截器

  • PayloadLoggingIntercepor,只会记录payload消息的日志。
  • SoapEnvelopeLoggingIntercepor,记录整个SOAP报文,包括SOAP报文头。

这两个拦截器都有logRequest和logResponse两个属性,可以通过设为为false,禁止记录对应日志。

PayloadValidatingInterceptor

sping-ws契约先行的一个好处就是可以对请求和响应的XML进行验证。PayloadValidatingInterceptor可以通过引用一个多个W3C XML或者RELAX NG的schemas,来验证请求或者响应,亦可同时验证二者。

XML配置示例

<bean id="validatingInterceptor"
        class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
    <property name="schema" value="/WEB-INF/orders.xsd"/>
    <property name="validateRequest" value="false"/>
    <property name="validateResponse" value="true"/>
</bean>

PayloadTransformingInterceptor

该拦截器基于XSLT,可以将payload转换成其他XML格式,在多版本的webservice中可以发挥较大的作用。

<bean id="transformingInterceptor"
        class="org.springframework.ws.server.endpoint.interceptor.PayloadTransformingInterceptor">
    <property name="requestXslt" value="/WEB-INF/oldRequests.xslt"/>
    <property name="responseXslt" value="/WEB-INF/oldResponses.xslt"/>
</bean>

异常处理

spring-ws通过EndpointExceptionResolver来处理endpoint的异常信息。MessageDispacher会自动捕获endpoint的异常解析器,不需要做显式的配置。

package org.springframework.ws.server;

import org.springframework.ws.context.MessageContext;

/**
 * Defines the interface for objects than can resolve exceptions thrown during endpoint execution.
 *
 * @author Arjen Poutsma
 * @since 1.0.0
 */
public interface EndpointExceptionResolver {

    /**
     * Try to resolve the given exception that got thrown during on endpoint execution.
     *
     * @param messageContext current message context
     * @param endpoint       the executed endpoint, or null if none chosen at the time of the exception
     * @param ex             the exception that got thrown during endpoint execution
     * @return {@code true} if resolved; {@code false} otherwise
     */
    boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex);
}

EndpointExceptionResolver默认实现是SimpleSoapExceptionResolver,可以通过实现EndpointExceptionResolver接口,增加自定义解析器覆盖默认实现。

SoapFaultMappingExceptionResolver

该异常解析器比SimpleSoapExceptionResolver实现更复杂一些, 它可以获取抛出异常的类名并将其映射到SOAP Fault中。

需要错误码的时候,endpoint默认的键值是faultCode,faultString,locale。如果没设置faultString,将默认为异常信息,如果没有设置locale,默认是英文。

示例:

<beans>
    <bean id="exceptionResolver"
        class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
        <property name="defaultFault" value="SERVER"/>
        <property name="exceptionMappings">
            <value>
                org.springframework.oxm.ValidationFailureException=CLIENT,Invalid request
            </value>
        </property>
    </bean>
</beans>

表示捕获ValidationFailureException异常时,给客户端的响应是Invalid request。响应示例

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
       <SOAP-ENV:Fault>
           <faultcode>SOAP-ENV:Client</faultcode>
           <faultstring>Invalid request</faultstring>
       </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

其他异常仍然是默认错误响应:带有异常信息的服务端异常。

spring-ws错误定义

package org.springframework.ws.soap.server.endpoint;

import java.util.Locale;
import javax.xml.namespace.QName;

/**
 * Defines properties for a SOAP Fault. Used by the {@code SoapFaultDefinitionEditor} and the
 * {@code SoapFaultMappingExceptionResolver}.
 *
 * @author Arjen Poutsma
 * @see SoapFaultDefinitionEditor
 * @see SoapFaultMappingExceptionResolver
 * @since 1.0.0
 */
public class SoapFaultDefinition {

    public static final QName CLIENT = new QName("CLIENT");

    public static final QName RECEIVER = new QName("RECEIVER");

    public static final QName SENDER = new QName("SENDER");

    public static final QName SERVER = new QName("SERVER");

    private QName faultCode;

    private String faultStringOrReason;

    private Locale locale = Locale.ENGLISH;

}

SoapFaultAnnotationExceptionResolver

spring-ws支持在异常类上通过@SoapFault注解,表名当异常抛出时需要返回。在上下文中配置了SoapFaultAnnotationExceptionResolver@SoapFault注解才可以生效。

@SopaFualt注解中包含了faultCode,faultString,locale

package org.springframework.ws.soap.server.endpoint.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.xml.namespace.QName;

/**
 * Marks an exception class with the fault elements that should be returned whenever this exception is thrown.
 *
 * @author Arjen Poutsma
 * @see org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver
 * @since 1.0.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface SoapFault {

    FaultCode faultCode();

    String customFaultCode() default "";

    String faultStringOrReason() default "";

    String locale() default "en";


}

示例

package samples;

import org.springframework.ws.soap.server.endpoint.annotation.FaultCode;
import org.springframework.ws.soap.server.endpoint.annotation.SoapFault;

@SoapFault(faultCode = FaultCode.SERVER)
public class MyBusinessException extends Exception {

    public MyClientException(String message) {
        super(message);
    }
}

当抛出一个携带“Oops!”的MyBisunessException时,响应报文如下:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
       <SOAP-ENV:Fault>
           <faultcode>SOAP-ENV:Server</faultcode>
           <faultstring>Oops!</faultstring>
       </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

服务端测试

服务端测试主要有两种方法

  • 单元测试,为测试endpoint提供模拟(EasyMock,JMock等)响应。这种方式的好处似乎测试简单,缺点是并没有真正的将XML消息发送到调用链上。
  • 集成测试

服务端集成测试

从spring-ws2.0开始引入集成测试的概念。

集成测试的相关特性位于org.springframework.ws.test.server包中,具体类MockWebServiceClient。期基本思想是客户端创建请求,并发送到MessageDispacherServletMessageDispatcherServlet转发到对应的endpoint上,endpoint处理请求并创建响应,客户端接口响应,比验证是否与注册的期望响应一致。

MockWebServiceClient的典型使用方式如下:

  • 通过MockWebServiceClient.createClient(ApplicationContext) 或者MockWebServiceClient.createClient(WebServiceMessageReceiver, WebServiceMessageFactory)创建MockWebServiceClient实例。
  • 调用sendRequest(RequestCreator)发送请求消息,RequestCreator默认使用spring-ws提供实现RequestCreators
  • 调用andExpect(ResponseMatcher)设置期望响应,ResponseMatcher 默认使用spring-ws提供的实现ResponseMatchers ,复杂响应可以对andExpect(ResponseMatcher)方法进行链式调用。

RequestCreatorRequestCreators

package org.springframework.ws.test.server;

import java.io.IOException;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;

public interface RequestCreator {
    WebServiceMessage createRequest(WebServiceMessageFactory var1) throws IOException;
}

MockWebServiceClient在请求endpoint前需要创建请求消息,RequestCreator就是完成创建请求的策略。RequestCreator的默认实现是RequestCreators。可以自定义实现RequestCreator,通过message工厂来生成请求消息,但这并没有必要,因为RequestCreators提供了一个 withPayload()方法,该方法可以根据给定的payload来生成RequestCreator,因此通常只需要导入RequestCreators既可。

ResponseMatcherResponseMatchers

package org.springframework.ws.test.server;

import java.io.IOException;
import org.springframework.ws.WebServiceMessage;

public interface ResponseMatcher {
    void match(WebServiceMessage var1, WebServiceMessage var2) throws IOException, AssertionError;
}

当请求到达endpoint处理后,MockWebServiceClient会收到响应,并验证响应是否符合预期,验证过程通过ResponseMatcher来完成。可以自定义实现ResponseMatcher,响应与预期不一致时抛出AssertionError ,同样这并么有必要,因为ResponseMatchers已经提供了标准实现。

ResponseMatchers已经提供的响应匹配如下:

ResponseMatchers method Description
payload() Expects a given response payload.
validPayload() Expects the response payload to validate against given XSD schema(s).
xpath() Expects a given XPath expression to exist, not exist, or evaluate to a given value.
soapHeader() Expects a given SOAP header to exist in the response message.
noFault() Expects that the response message does not contain a SOAP Fault.
mustUnderstandFault(), clientOrSenderFault(), serverOrReceiverFault(), and versionMismatchFault() Expects the response message to contain a specific SOAP Fault.

复杂响应的andExpect()调用链示例

mockClient.sendRequest(...).
 andExpect(payload(expectedResponsePayload)).
 andExpect(validPayload(schemaResource));

其他文章

spring web service 1
spring web service 3
maven配置文件settings.xml详解
Nginx转发请求过程解析
Nginx中的负载均衡算法
Nginx upstream指令配置说明
Nginx中虚拟服务器server指令配置说明
Nginx中proxy_pass/proxy_redirect/proxy_set_header配置说明
Nginx中ngx_http_core_module相关指令配置说明
Java自带JVM监控工具jstat使用详细说明
Java自带JVM监控工具jps使用详细说明
Java自带故障分析工具jmap工具使用说明
Java自带故障分析工具jhat工具使用说明

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容