Spring-WS是基于Spring MVC的,在Spring MVC中,所有請求都由DispatcherServlet操作,這個Servlet會將請求分配給處理請求的控制器。類似的,Spring-WS會在前臺使用MessageDispatcherServlet。它是DispatcherServlet的子類,用于將SOAP請求分配給Spring-WS端點。<servlet> <servlet-name>spring-ws</servlet-name> <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>spring-ws</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>后面會對這個配置進行修改,暫且先作為我們研究Spring-WS的起點
將消息映射到端點:MessageDispatcherServlet也使用了端點映射來決定由哪個端點接收輸入的XML消息。對于撲克評分服務,我們將使用Spring-WS的PayloadRootQNameEndpointMapping,在Spring中配置如下:<bean id="payloadMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping"><property name="endpointMap"> <map> <entry key="{http://www.springinaction.com/poker/schemas}EvaluateHandRequest" value-ref="evaluateHandEndpoint"/> </map> </property>PayloadRootQNameEndpointMapping首先會檢查消息載荷的限定名(QName),接著再通過查詢映射列表(通過endpointMap屬性配置的)找到輸入SOAP消息映射到的端點。
配置消息序列化器:在對象和XML消息之間進行轉換的關鍵是對象-XML 映射(OXM)。Spring-OXM是Spring-WS的一個子項目,提供對幾種常見OXM解決方案的抽象,其中包括JAXB和Castor XML. Spring-OXM的核心元素是Marshaller和Unmarshaller接口。Marshaller的實現可以根據Java對象生成XML元素。與之相反,Unmarshaller的實現則被用于根據XML元素構建Java對象。 AbstractMarshallingPayloadEndPoint在處理消息時會使用Spring-OXM的序列化器和反序列化器。當AbstractMarshallingPayloadEndPoint接收到消息時,會將這條XML消息交給Unmarshaller,反序列化成一個對象,并傳遞給invokeInternal()方法。接下來,在invokeInternal()完成處理后,返回的對象則被交給Marshaller,序列化成XML,并傳遞給客戶端。 幸運的是,你不必自己創建Marshaller 和 Unmarshaller的實現。Spring-OXM提供了幾個實現。見PPT(4) 我們為撲克評分服務選擇了Castor XML.所以,需要按下面的方法在Spring中配置CastorMarshaller: <bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller"> <property name="mappingLocation" value="classpath:mapping.xml" /></bean>不需要附加的配置,Castor XML就可以進行一些基本的XML序列化工作。但是,我們的OXM進行的工作比默認Castor XML可以處理的工作要更復雜一些。因此,需要使用一個Castor XML映射文件來配置CastorMarshaller。mappingLoaction 屬性指定了Castor XML映射文件的位置。這里,我們將mappingLoaction設置為在應用程序跟classpath中查找名字是mapping.xml的映射文件。 (見spring in action P245 程序清單9.4)
配置端點異常:我們需要一種方法能夠將Web服務或Spring-WS拋出的任何Java異常轉換成SOAP錯誤。為了實現這個目標,Spring-WS提供了SoapFaultMappingExceptionResolver。見PPT5,SoapFaultMappingExceptionResolver可以處理發生在消息處理過程中的任何未捕捉異常,并生成一個相應的SOAP錯誤返回給客戶端。在Spring中的配置:<bean id="endpointExceptionResolver" class="org.springframework.ws.soap.serer.endpoint.SoapFaultMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.springframework.oxm.UnmarshallingFailureException"> SENDER,Invalid message received </prop> <prop key="org.springframework.oxm.ValidationFailureException"> SENDER,Invalid message received </prop> </props> </property> <property name="defaultFault" value="RECEIVER,Server error" /> </bean> 可以為exceptionMapping屬性配置一個或多個SOAP錯誤定義(被映射到Java異常的)。每個<prop>的Key是需要轉換成SOAP錯誤的Java異常,<prop>的值是一個由兩部分內容構成的值,第一部分是錯誤的類型,第二部分是描述錯誤的字符串。
提供WSDL文件:你應該注意到我為構成Web服務消息的XML元素選擇的名稱:EvaluateHandRequest和EvaluateHandResponse。這些名字不是任意選擇的。選擇他們的目的是利用Spring-WS中的配置慣例,自動為撲克評分服務創建WSDL。 為了完成這個工作,需要配置Spring-WS的DynamicWsdlllDefinition。它是一個特殊的Bean,MessageDispatcherServlet可以使用它從XML模式生成WSDL。這將非常方便,因為我們已經為契約的數據部分定義了一些XML模式。下面如何配置DynamicWsdlllDefinition:
<bean id="poker" class="org.springframework.ws.wsdl.wsdlll.DynamicWsdlllDefinition">
<property name="builter">
<bean class="org.springframework.ws.wsdl.wsdlll.builder.XsdBasedSoapllWsdl4jDefinitionBuilder">
<property name="schema" value="/PokerTypes.xsd" />
<property name="portTypeName" value="Poker" />
<property name="locationUri" value="http://localhost:8080/Poker-WS/services" />
</bean>
</property>
</bean>
DynamicWsdlllDefinition通過讀取XML模式的定義來進行工作,在這里用schema屬性指定了PokerTypes.xsd。DynamicWsdlllDefintion會遍歷整個模式文件,查找所有名字以Request和Response結尾元素定義。它假設這些后綴用于指示發向或發自Web服務的消息,并且會在生成的WSDL中創建相應的<wsdl:operation>元素,見PPT6。最后一個DynamicWsdlllDefinition的屬性是 locationUri.這個屬性告訴客戶端服務可以在哪里發現。PPT8中的框圖分解了locationUri屬性中的URL。 談論到<servlet-mapping>,我們需要在Web.xml中添加一個新的<servlet-mapping>,以便 MessageDispatcherServlet可以提供WSDL定義。
<servlet-mapping>
<servlet-name>poker</servlet-name>
<url-pattern>*.wsdl</url-pattern>
</servlet-mapping>
部署服務:現在可以打包這個Web服務應用程序并進行部署了。因為這個項目選擇了使用Maven 2,所以只需要簡單的輸入下面的命令就可以創建可部署的WAR文件: % mvn package deploy 一旦Maven執行完畢,在目標目錄中就會生成一個Poker-WS.war文件,它適合于部署到大多數Web應用服務器上。