Spring学习笔记26

Spring-WS集成()

5.处理端点异常

事情不会一帆风顺。传输的消息有可能不能转化成Java对象或消息根本就不是合法的XML,因此服务端点就有可能抛出一个异常——我们应该怎么处理它呢?

如果处理消息时出现异常,我们需要向客户返回一个SOAP错误。不过,SOAP并不识别Java异常,而基于SOAPweb service通常都使用SOAP错误来表明失败。所以,我们需要将由web serviceSpring-WS抛出的java异常转化成SOAP错误。

Spring-WS提供了SoapFaultMappingExceptionResolver,它负责处理在消息处理过程中出现的任何未捕获异常,并产生一个对应的SOAP错误返回给客户。在服务端,我们需要如下配置它:

<bean id="endpointExceptionResolver"

    class="org.springframework.ws.soap.server.endpoint.

       SoapFaultMappingExceptionResolver">

    <property name="exceptionMappings">

       <props>

           <prop key="org.springframework.oxm.

              UnmarshallingFailureException">

              SENDER, Invaild message received</prop>

           <prop key="org.springframework.oxm.

              ValidationFailureException">

              SENDER, Invaild message received</prop>

       </props>

    </property>

    <property name="defaultFault" value="RECEIVER, Server error" />

</bean>

exceptionMappings属性配置了一个或多个SOAP错误与java异常的映射规则。每个<prop>的值都是一个Java异常,它都需要被转换成SOAP错误。每个<prop>值由两部分组成,第一部分表明错误类型;第二部分是描述错误的字符串。

       SOAP错误有两种类型:senderreceiverSender错误一般表示客户端的错误。Receiver错误表明是web service从客户端接收消息,但在处理消息时出错。

       举例来说,如果一个服务接收到一个不能被转换成java对象的XML消息,那么marshaler就会抛出org.springframework.oxm.UnmarshallingFailureExce-

ption异常。因此发送方(sender)创建的该XML,所以这是一个sender错误。因此我们将该消息设置为“无效消息”。ValidateFailureException异常与之类似。

       任何没有显式地在exceptionMappings属性中配置映射的异常都将按defaultFault属性中定义的映射规则处理。上面的代码中,我们假定如果抛出的异常不匹配任何映射异常,那么我们视之为一个接收方(receiver)错误,所以,我们配置了接收方错误和错误信息:“server error”。

6. 提供WSDL文件

       最后我们来看poker hand evaluation例子的WSDL文件的写法。我们已经创建了contract的数据部分作为XSD。那么现在我们选用EvaluateHandRequestEvaluateHandResponse作为组成web service消息的XML元素。选用这两个名字是有目的的,因为我们可以利用Spring-WS提供的惯例优先原则来自动地创建WSDL

       首先,我们需要配置Spring-WSDynamicWsdl11Definition,它会与MessageDispatcherServlet一同从XML Schema创建WSDL。这很容易实现,因为我们定义过XSD,下面展示如何配置DynamicWsdl11Definition

<bean id="poker" class="org.springframework.ws.wsdl.wsdl11.

    DynamicWsdl11Definition">

    <property name="builder">

       <bean class="org.springframework.ws.wsdl.wsdl11.builder.

           XsdBasedSoap11Wsdl4jDefinitionBuilder" >

           <property name="schema" value="/PokerTypes.xsd" />

           <property name="portTypeName" value="Poker" />

           <property name="locationUri"

              value="http://localhost:8080/Poker-WS/services" />

       </bean>

    </property>

</bean>

DynamicWsdl11Definition读取一个XSD(这里是PokerTypes.xsd),遍历schema文件来查找任何以RequestResponse名字结尾的元素定义,因为它认定RequestResponse后缀分别表明被发送到web service和从web service操作发出的消息,并在WSDL中创建一个相应的<wsdl:operation>元素。

       本例中,DynamicWsdl11Definition将会读取PokerTypes.xsd文件,并将EvaluateHandRequestEvaluateHandResponse元素分别作为EvaluateHand操作的输入和输出消息。因此,配置如下:

<wsdl:portType name="Poker">

    <wsdl:operation name="EvaluateHand">

       <wsdl:input message="schema:EvaluateHandRequest"

           name="EvaluateHandRequest">

       </wsdl:input>

       <wsdl:output message="schema:EvaluateHandResponse"

           name="EvaluateHandResponse">

       </wsdl:output>

    </wsdl:operation>

</wsdl:portType>

值得注意的是,<wsdl:portType>由绑定在DynamicWsdl11DefinitionportTypeName属性中的值来命名。DynamicWsdl11Definition的最后一个属性是locationUri,它表明服务的地址。localhost表明它是运行在本机,/services表明它将匹配<servlet-mapping>中的配置。除此之外,我们还需要在web.xml中添加一个新的<servlet-mapping>,这样MessageDispatcherServlet才能提供WSDL。配置如下:

<servlet-mapping>

       <servlet-name>poker</servlet-name>

       <url-pattern>*.wsdl</url-pattern>

</servlet-mapping>

到此为止,我们已经配置过了MessageDispatcherServlet来自动生成WSDL文件。但现在的问题是这个WSDL文件在哪里呢?

       自动创建的WSDLhttp://localhost:8080/Poker-WS/poker.wsdl处。因为MessageDispatcherServlet会被映射到*.wsdl,所以它会为每个匹配的请求尝试去创建WSDL。但是它怎么知道为poker servicepoker.wsdl上创建WSDL呢?答案就在于MessageDispatcherServlet遵循的惯例。值得注意的是,我们前面声明过DynamicWsdl11Definition bean来获取pokerID值。当MessageDispatcherServlet接收到一个请求时,它会在Spring context中寻找命名为pokerWSDL bean。本例中就是DynamicWsdl11Definition

使用预定义WSDL

DynamicWsdl11Definition大多数情况下都不需要你手动编写WSDL,但是在某些情况下你还是需要定制你自己的WSDL。本例中你需要手动创建WSDL并把它绑定到Spring中:

<bean id="poker"

    class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">

    <property name="wsdl" value="/PokerService.wsdl" />

</bean>

SimpleWsdl11Definition并不会创建WSDL,它只会通过wsdl属性提供WSDL

       预定义WSDL的唯一问题在于它是以静态方式定义的,这对于指定服务地址的WSDL就会是一个问题。例如,考虑下么的WSDL代码:

<wsdl:service name="PokerService">

    <wsdl:port binding="tns:PokerBinding" name="PokerPort">

       <wsdlsoap:address

           location="http://localhost:8080/Poker-WS/services" />

    </wsdl:port>

</wsdl:service>

这里由http://localhost:8080/Poker-WS/services定义了服务的地址。如果你需要在另一个服务器上部署,那么这个地址就有可能需要变更。你可以每次手动地修改这个值,但是这个过程容易出错。

       但是MessageDispatcherServlet知道它被部署的地方,而且它也知道请求的URL。因此,你可以让MessageDispatcherServlet重写来完成这个地址值变更过程。你需要的就是设置名为transformWsdlLocations<init-param>true,例如:

<servlet>

    <servlet-name>poker</servlet-name>

    <servlet-class>org.springframework.ws.transport.http.

       MessageDispatcherServlet</servlet-class>

    <init-param>

       <param-name>transformWsdlLocations</param-name>

       <param-value>true</param-value>

    </init-param>

</servlet>

transformWsdlLocation被设置成true时,MessageDispatcherServlet将重写SimpleWsdl11Definition提供的WSDL来匹配请求URL

7. 部署服务

       我们已经配置了contract,编写了端点,并且所有的Spring-WS bean都已经准备就绪了。现在我们需要把这些打包成一个WAR包并将其部署。

       使用Spring-WS来构建一个web service只是它的一个方面。Spring-WS还提供了一个客户API。该API基于与服务器端相同的消息驱动机制。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值