PHP5中使用Web服务访问J2EE应用程序(3)

发表于:2007-06-21来源:作者:点击数: 标签:
解释 WSDL 我们已经成功地调用了 Weather 服务,但是还没有看过它的 WSDL 文档。WSDL 中的细节要比 SoapClient 公开的多。我们如何知道应该在 startDate 参数中放什么呢?我们应该期望从返回的数据中实际得到什么?要回答这些问题,必须更深入地分析 WSDL。

   


   解释 WSDL

  我们已经成功地调用了 Weather 服务,但是还没有看过它的 WSDL 文档。WSDL 中的细节要比 SoapClient 公开的多。我们如何知道应该在 startDate 参数中放什么呢?我们应该期望从返回的数据中实际得到什么?要回答这些问题,必须更深入地分析 WSDL。

  可以从下载部分下载 Weather Forecast 应用程序的 WSDL。如果使用不同的 Web 服务,只需要在浏览器中打开相应的 WSDL 文档即可。

  getForecast 操作的 WSDL 是:

clearcase/" target="_blank" >cc66 width="90%" align=center bgColor=#dadacf border=1>
<wsdl:operation name="getForecast">
<wsdl:input message="intf:getForecastRequest" name="getForecastRequest"/>
<wsdl:output message="intf:getForecastResponse" name="getForecastResponse"/>
</wsdl:operation>

  其中的 getForecastRequest 消息被定义为:

<wsdl:message name="getForecastRequest">
<wsdl:part element="intf:getForecast" name="parameters"/>
</wsdl:message>

  而 getForecast 结构被定义为:

<element name="getForecast">
<complexType>
<sequence>
<element name="startDate" nillable="true" type="xsd:dateTime"/>
<element name="days" type="xsd:int"/>
</sequence>
</complexType>
</element>

  于是我们知道该函数需要两个参数,xsd:dateTime 类型的 startDate 和整数类型的 days。这与我们所了解的 SoapClient::_getTypes 函数完全匹配,但是现在我们还知道 startDate 可以为空(nillable)。毫无疑问,如果我们简化输入参数,那么该函数将如下所示:

$forecastResponse = $soapClient->getForecast(array('startDate'=>Null, 'days'=>3));

  如果明确指定今天的日期,结果会与所指定的完全一致。

  如果希望制定其他起始日期怎么办呢?XML Schema将 dateTime 定义成一种基本类型,按照 ISO 8601 标准格式化,比如“2004-12-01T00:00:00”。假设希望了解三天之后的天气预报,可以使用内置函数 strtotime("+3 days") 获得需要的日期,该函数与 time() 函数相同,都返回标准 UNIX 格式的日期时间,即表示从公元纪年开始到现在的秒数的一个整数。我们知道 XML Schema 要求日期采用具有字符串字段的 ISO 8601 格式进行编码,于是在示例客户机中编写了 timeToIso8601 函数,将整数日期转换成 SOAP 编码定义的格式。但我们吃惊地发现,其实并不需要这样做,ext/soap 非常聪明地将整数日期转化成了需要的字符串字段格式。无论传递的是整数还是预格式化的字符串,都没有关系,最终传送的 SOAP 消息都是一样的。

  响应中的日期又如何呢?在回程中,ext/soap 从 SOAP 响应获得了 dateTime 字段,但是没有做任何格式转换。我们希望它返回一个整数,以表示从公元纪年到现在的秒数,但实际上得到的是按照 ISO 8601 格式化的字符串。于是我们使用 strtotime 函数将其转化成整数,然后使用 strftime 格式化该整数,以便于表示。

  Weather Service 按日期提供预报,但它忽略了 dateTime 编码中的时间成分。所以我们没有考虑这方面的调整,如果从运行在不同时区内的服务中请求天气预报,那么可能必须这样做。如果希望进一步了解时区转换,请参阅参考资料中给出的描述 ISO 8601 标准的文章。

  现在再回到响应格式上来。上一节中曾经提到 getForecast 返回数据的不一致性。WSDL 描述告诉我们 getForecast 返回一个 getForecastResponse 对象,getForecastResponse 可以包含无限多个称为 Weather 的复杂类型的列表:

<element name="getForecastResponse">
<complexType>
<sequence>
<element maxOccurs="unbounded" name="getForecastReturn" type="tns2:Weather"/>
</sequence>
</complexType>
</element>

<complexType name="Weather">
<sequence>
<element name="condition" nillable="true" type="xsd:string"/>
<element name="date" nillable="true" type="xsd:dateTime"/>
<element name="windDirection" nillable="true" type="xsd:string"/>
<element name="windSpeed" type="xsd:int"/>
<element name="temperatureCelsius" type="xsd:int"/>
<element name="dbflag" type="xsd:boolean"/>
</sequence>
</complexType>

  WSDL 不允许出现单元素数组这种特例。不幸的是,当响应只包含一个 Weather 对象时,ext/soap 没有考虑 WSDL 中应用于 getForecastResponse 的 <sequence> 标签,因为这种行为在客户机代码中造成了不必要的复杂性。

  最后,WSDL 文档还告诉 SOAP 客户机可以从网络中的哪个地方找到该服务:

<wsdl:service name="WeatherForecastEJBService">
<wsdl:port binding="intf:WeatherForecastEJBSoapBinding"
name="WeatherForecastEJB">
<wsdlsoap:address location=
"http://localhost:9080/ItsoWebService2RouterWeb/services/WeatherForecastEJB"/>
</wsdl:port>
</wsdl:service>

原文转自:http://www.ltesting.net