首页 | 资讯动态 | linux基础 | 系统管理 | 网络管理 | 编程开发 | linux数据库 | 服务器技术 | linux相关 | linux认证 | 嵌入式 | 下载中心 | 专题 | linux招聘 | 镜像站
OKLinux中文技术站
·设为首页
·加入收藏
·联系我们
系统管理: 中文环境 系统管理 桌面应用 内核技术 | Linux基础: 基础入门 安装配置 常用命令 经验技巧 软件应用 | Linux数据库: Mysql Postgre Oracle DB2 Sybase other
网络管理: 网络安全 网络应用 Linux服务器 环境配置 黑客安全 | 编程开发: PHP CC++ Python Perl Shell 嵌入式开发 java jsp | PHP技术: PHP基础 PHP技巧 PHP应用 PHP文摘
Linux资讯 Linux招聘 Linux专题 Apache | Linux相关: 硬件相关 Linux解决方案 Linux认证 企业应用 其它Unix | 相关下载: 资料下载 参考手册 开发工具 服务器类 软路由 其它
 技术搜索:
会员中心 注册会员 高级搜索  
  → 当前位置:首页>编程开发>php>php应用>正文

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

http://www.oklinux.cn  2005-04-12  来源: yesky.com   会员收藏  游客收藏  【 】 

  我们成功地与 Weather 服务取得了联系,并显示了结果。但是如果出现错误,得不到预期的结果,该怎么办?ext/soap 可以显示客户机与服务器之间交换的 SOAP 消息,能够帮助我们确定问题所在。
  
  只有使用 trace 选项创建 SoapClient 时,才要使用跟踪功能。我们在 options 数组参数中设置 trace 选项,将该参数传递给 SoapClient 构造函数。我们将构造函数的使用改为:
  
  $soapClient = new SoapClient("http://localhost:9080/" .
  "ItsoWebService2RouterWeb/wsdl/itso/session/WeatherForecastEJB.wsdl",
  array('trace' => 1));
  
  并在调用 goForecast 之后调用 trace 方法:
  
  echo "Request :<br>", htmlspecialchars($soapClient->__getLastRequest()), "<br>";
  echo "Response :<br>", htmlspecialchars($soapClient->__getLastResponse()), "<br>";
  
  一定要使用 htmlspecialchars 内置函数对 trace 输出进行编码,因为它将 SOAP xml 分界符转换成特殊字符,如 <,这样可以避免浏览器将其解释成标记。
  
  下面是某个请求的 trace 输出:
  
  <?xml version="1.0" encoding="UTF-8"?>
  <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:ns1="http://session.itso">
  <SOAP-ENV:Body>
  <ns1:getForecast>
  <ns1:startDate>2004-11-30T13:41:59</ns1:startDate>
  <ns1:days>0</ns1:days>
  </ns1:getForecast>
  </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>
  
  对应的应答是:
  
  <?xml version="1.0" encoding="UTF-8"?>
  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
  <getForecastResponse xmlns="http://session.itso">
  <getForecastReturn xmlns:ns-239399687="http://mapping.itso">
  <ns-239399687:condition>sunny</ns-239399687:condition>
  <ns-239399687:date>2004-11-30T00:00:00.000Z</ns-239399687:date>
  <ns-239399687:windDirection>W</ns-239399687:windDirection>
  <ns-239399687:windSpeed>18</ns-239399687:windSpeed>
  <ns-239399687:temperatureCelsius>6</ns-239399687:temperatureCelsius>
  <ns-239399687:dbflag>1</ns-239399687:dbflag>
  </getForecastReturn>
  </getForecastResponse>
  </soapenv:Body>
  </soapenv:Envelope>
  
  如果在开启跟踪功能的情况下运行客户机来收集这些输出,那么需要将 days 参数设置为 0,只有这样做,SOAP 应答才会输出较少的行。但是我们遇到了没有预料到的行为。我们本来期望 getForecastResponse 和以前一样是一个 Weather 对象数组,但是它应该只有一个元素,而不是 4 个元素。然而,它被转换成了一个简单的 Weather 对象,我们必须根据这种行为进行编码,就像您在最终的示例 PHP 客户机代码中看到的那样。这与 Java 客户机的行为有所不同,在客户机行为中,getForecast 总是返回 Weather 对象数组,无论服务器响应中有多少个 Weather 对象。SoapClient::_getTypes() 输出并没有为我们理解这种差异提供足够的细节,因此我们要求助于 WSDL 文档来了解完整的接口规范。
  
  解释 WSDL
  
  我们已经成功地调用了 Weather 服务,但是还没有看过它的 WSDL 文档。WSDL 中的细节要比 SoapClient 公开的多。我们如何知道应该在 startDate 参数中放什么呢?我们应该期望从返回的数据中实际得到什么?要回答这些问题,必须更深入地分析 WSDL。
  
  可以从下载部分下载 Weather Forecast 应用程序的 WSDL。如果使用不同的 Web 服务,只需要在浏览器中打开相应的 WSDL 文档即可。
  
  getForecast 操作的 WSDL 是:
  
  <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>
  
  处理 SOAP 错误
  
  如果运行客户机时出现错误怎么办?与其他语言(如 Java)一样,PHP 5 新增加了一种异常机制。ext/soap 使用这种新的机制,以 SoapFault 对象的形式返回错误。比方说,可以用下面这种形式将代码包装起来:
  
  try {
  ... some SOAP operation
  } catch (SoapFault $soapFault) {
  echo $soapFault;
  }
  
  注意,与 Java 有所不同,PHP 语言的 try - catch 块不能包含 finally

上一篇:PHP5中使用Web服务访问J2EE应用程序(1)   下一篇:入门教程:学习使用PHP数组


收藏于收藏夹】 【评论】 【推荐】 【打印】 【关闭
相关文档
·PHP5中使用Web服务访问J2EE应用程序(1)
·内嵌式的语言PHP 应用技巧七则
·PHP应用程序的性能优化及简要的介绍
·一步一步教你PHPMyAdmin安装图解教程
·分析PHP比ASP优秀的七个理由
·教您如何应用PHP开发出安全的应用程序
·举例说明:在PHP中运行XPath查询
·PHP应用分页显示制作详细讲解
·实例分析:实现一个PHP WAV接合方案
·Windows服务器安装多套PHP的解决方案
·如何使用动态共享对象的模式来安装PHP
·PHP5学习笔记第一节面向对象编程
·用PHP实现XML备份MySQL数据库
·用PHP实现GB2312和Unicode间的编码转换
·用PHP编程语言开发动态WAP页面
·PHP也可以当成Shell Script使用
发表评论
密码: 匿名评论
评论内容:

(不超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规)
 
  最新文档
·Linux系统上把PHP编译进Apache静态内核
·关于PHP逗点连接符与引号问题
·php有关于正则表达式的详细说明
·通过gd库为图片添加透明水印
·第二节--PHP5 的对象模型
·用php对文件上传处理过程的进一步说明
·PHP分页显示制作详细讲解
·Linux主机重编译PHP支持GD库
·php+ImageMagick+imagick API 配置指南
·php抓取和分析
·第一节--面向对象编程
·php的预定义变量
  阅读排行
·Linux系统上把PHP编译进Apache静态内核
·WASP使用方法简介(3)
·Linux编程之提升PHP执行速度全攻略分析
·Linux主机重编译PHP支持GD库
·MySQL (C API)VC实例及代码下载 (1)
·Windows服务器安装多套PHP的解决方案
·用PHP编程语言开发动态WAP页面
·FleaPHP -- 中国人自己的PHP开发框架
·如何使用动态共享对象的模式来安装PHP
·PHP应用分页显示制作详细讲解
·用php或js获取图片大小,高宽尺寸
·教您如何应用PHP开发出安全的应用程序
·为什么PHP令人不爽(对于大型系统)
·PHP也可以当成Shell Script使用
·winbinder开发php桌面程序
网摘收藏: