Spring Web Service支持多种传输协议来和SOAP进行绑定, 包括http, jms和email.最普遍的就是http协议了. 类似Spring MVC, Spring-WS也提供一个前端控制器MessageDispathcerServlet来处理来自客户端的请求, 但它的主要作用也就是解析WSDL文件的地址, 并且将实际的请求委托给它包装的一个MessageDispatcher对象.下面是从其官方文档上截下来的时序图:
其实整个原理是很简单的:客户端封装一个SOAP请求通过http发送给服务端, 服务器根据收到的SOAP信息来确定由哪一个处理器(端点, EndPoint)来处理, 处理完后再封装一个SOAP信息返回给客户端.那么这里最核心的一个问题就是怎么通过收到的信息来确定由哪个EndPoint来处理, 最容易想到的就是通过SoapAction这个放在header中的参数来判定, 但是SOAP规范中SoapAction这个参数是可选的, 而且好像很多文章都不提倡选用这个参数. 在Spring-WS主要是根据收到的SOAP的Body中的xml的根元素的QName来判定的, 当然也提供了其它的如SoapAction, Uri等方式.下面我们结合上面那个时序图来简要说明一下Spring-WS的整个流程, 不过在这之前我们还是来了解几个很重要的概念:
1, WebServiceMessage: 代表一个xml的消息
2, WebServiceConnection: 代表客户端向服务端发送一个WebServiceMessage的点到点的连接, 显然, 这个对象就应该包括两个动作:接收从客户端发来的消息和发送给客户端返回消息
3, MessageContext: 它由两个部分组成: requeset和response, 它代表C/S的一组Q&A, 也就是说每一次请求都会新建这样一个对象来持有当前会话中的一组Q&A. 实际上, 在上面的流程图中所传递的对象(request)就是一个MessageContext对象, 直到endpoint处理这个对象, 才会将response注入到MessageContext中.
4, TransportContext: 协议上下文, 它持有一个WebServiceConnection, 可以通过TransportContextHolder拿到本地线程(ThreadLoacl)的TransportContext, 从而获得WebServiceConnection中的一些信息, 如http的HttpServletRequest.
下面我们对上图做个简要的分析:
1, 客户端发送一个SOAP请求到MessageDispatcherServlet, 如果是GET请求, 就委托给WsdlDefinitionHandlerAdapter对象将wsdl返回给客户(这一块以后再慢慢深究); 如果是POST请求, 则通过WebServiceMessageReceiverHandlerAdapter给当前的请求建立一个WebServiceConnection对象, 并将其封装在TransportContext中由TransportContextHolder放在本地线程(ThreadLoacl)中, 然后将请求交由MessageDispatcher这个事实上的处理器来处理.
2, MessageDispatcher拿到MessageContext对象, 首先根据用户的请求, 调用EndPointMapping的getEndPoint()方法来获得一个EndpointInvocationChain对象, 这个对象封装了一个EndPoint对象和一个拦截器EndpointInterceptor数组, 如果拦截器不为空则调用拦截器, 然后在Spring的上下文中寻找合适的EndPointAdapter来调用EndPoint对象, 注意: 这里的EndPoint对象可以是任何对象, 不需要实现任何接口, 你所要处理的信息会从EndPointAdapter这个接口中拿到(我想这是我看到的最实用的一个适配器模式的例子).
3, EndPointAdapter通过invoke(MessageContext messageContext, Object endpoint)这个接口使得endpoint可以处理messageContext这个对象, 然后将response注入到 messageContext对象中, 最后由WebServiceConnection写入到返回的客户的流中.
在写这篇文章的时候, 我不断的想, 整个图一看就懂, 到底这样写出来有没有什么意义.整个文章的感觉给人像是在跑流水线, 时不时还冒出两个对象, 又有点像做源代码分析, 给人一种四不像的感觉. 不过我想, 还是乐观一点比较好, 也许是自己不善于表达, 还是一步一步慢慢走下去吧, 时间长了, 也许就习惯了!
还是听首歌吧: 林志炫<<时间的味道>>, 真的很有味道哦!