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应用服务器上。