一个定义良好的应用不允许直接访问内部对象。在Spring的MVC中用户通过控制器(controller)来与应用交互。controller会依次将用户请求转换成对内部对象的调用。Spring WS和Spring MVC原理相似,一个web service客户通过一个或多个消息端点与应用交互。
一个消息端点是一个类,负责从客户端获取XML消息,然后基于消息内容调用相应的内部对象执行相应操作。对于poker hand服务来说,消息端点将处理<EvaluateHandRequest>消息。一旦消息被处理完毕,端点将返回另一个XML消息作为响应。本例中,响应的XML就是一个<EvaluateHandResponse>文档。Spring-WS定义了几个抽象类用于创建消息端点,如AbstractDom4jPayloadEndPoint等。
大多数情况下,这些抽象类是相似的,你可以选择任意一个。但是AbstractMarshallingPayloadEndpoint有些不同,它支持XML消息向java对象的汇集(marshaling)和从java对象的unmarshaling。
下面让我们看看AbstractMarshallingPayloadEndpoint,首先来看看如何搭建一个直接处理XML消息的端点。
1. 构建基于JDOM的消息端点
poker hand evaluation这个web service以<EvaluateHandRequest>消息作为输入,产生<EvaluateHandResponse>作为输出。所以,我们需要创建一个服务端点来处理<EvaluateHandRequest>元素并产生<EvaluateHandResponse>元素。Spring提供的抽象类中的任何一个都可以满足上面的要求,这里我们选择AbstractJDomPayloadEndpoint,然后再编写EvaluateHandJDomEndpoint类继承AbstractJDomPayloadEndpoint处理<EvaluateHandRequest>消息。
2. 汇集消息payload
如前所述,AbstractMarshallingPayloadEndpoint有点不同于其他的抽象端点类。我们不会向它传递保存了信息的XML Element元素,而是传递给它一个对象让它来处理。一个marshaling端点会与一个unmarshaler协同工作将输入的XML消息转化成POJO,而端点返回的POJO会被unmarshaler转化成一个XML消息返回给客户。这极大地简化了端点的实现,因为它不需要包含任何处理XML的代码。
Spring-WS的一大部分是OXM抽象层,它提供了几种OXM实现包括:JAXB等。需要指出的是,这里的EvaluateHandMarshallingEndpoint并不知道被传递给invokeInternal方法的Object对象从哪里来。它只接收一个Object对象作为参数,因此我们可以像其他任何POJO对象一样对它进行单元测试。