`
phpxiaoxin
  • 浏览: 251217 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

php调用java发布的webservice

阅读更多

java 使用 spring webservice 发布的 service,由php使用SoapClient调用。

遇到有一个奇怪的现象,java调用发布的webservice,没有问题,使用工具SOAP UI调用,没有问题,

同样的php代码调用google的天气服务没问题,调用我们的wsdl就不行。

经过摸索调试,发现如下问题,以及解决的过程。

 

首先发布的wsdl如下:

 

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://www.phpxiaoxin.com/doorway" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.phpxiaoxin.com/doorway" targetNamespace="http://www.phpxiaoxin.com/doorway">
  <wsdl:types>
    <s:schema xmlns:dw="http://www.phpxiaoxin.com/doorway" xmlns:s="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.phpxiaoxin.com/doorway">
      <s:complexType name="Error">
        <s:attribute name="Code" type="s:string" use="required"/>
        <s:attribute name="Message" type="s:string" use="required"/>
      </s:complexType>
      <s:simpleType name="Status">
        <s:restriction base="s:string">
          <s:enumeration value="Successful"/>
          <s:enumeration value="Failed"/>
        </s:restriction>
      </s:simpleType>
      <s:complexType abstract="true" name="BaseRequest">
        <s:attribute name="Token" type="s:string" use="required"/>
        <s:attribute name="UserName" type="s:string" use="required"/>
        <s:attribute name="Password" type="s:string" use="required"/>
      </s:complexType>
      <s:complexType abstract="true" name="BaseResponse">
        <s:sequence>
          <s:element minOccurs="0" name="Error" type="dw:Error"/>
        </s:sequence>
        <s:attribute name="Token" type="s:string" use="required"/>
        <s:attribute name="Status" type="dw:Status" use="required"/>
      </s:complexType>
      <s:complexType name="StatusResponse">
        <s:complexContent>
          <s:extension base="dw:BaseResponse"/>
        </s:complexContent>
      </s:complexType>
        <s:attribute name="RatePlanCode" type="s:string" use="required"/>
        <s:attribute name="RoomTypeCode" type="s:string" use="required"/>
        <s:attribute name="NumberOfUnits" type="s:int" use="required"/>
        <s:attribute name="HotelCode" type="s:string" use="required"/>
        <s:attribute name="DistributorReservationId" type="s:string" use="required"/>
      </s:complexType>
      <s:element name="PingRequest">
        <s:complexType>
          <s:complexContent>
            <s:extension base="dw:BaseRequest">
              <s:attribute name="Echo" type="s:string" use="required"/>
            </s:extension>
          </s:complexContent>
        </s:complexType>
      </s:element>
      <s:element name="PingResponse">
        <s:complexType>
          <s:complexContent>
            <s:extension base="dw:StatusResponse">
              <s:attribute name="Echo" type="s:string" use="required"/>
            </s:extension>
          </s:complexContent>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="PingResponse">
    <wsdl:part element="tns:PingResponse" name="PingResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="PingRequest">
    <wsdl:part element="tns:PingRequest" name="PingRequest">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Doorway">
    <wsdl:operation name="Ping">
      <wsdl:input message="tns:PingRequest" name="PingRequest">
    </wsdl:input>
      <wsdl:output message="tns:PingResponse" name="PingResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="DoorwaySoap11" type="tns:Doorway">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="Ping">
      <soap:operation soapAction=""/>
      <wsdl:input name="PingRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="PingResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HotelDoorwayService">
    <wsdl:port binding="tns:DoorwaySoap11" name="DoorwaySoap11">
      <soap:address location="/soap/doorway/"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

 

其中定义了一个方法"Ping" 输入为PingRequest 和 PingResponse 其中PingRequest包含一个echo的属性,并集成一个BaseRequest的对象。

 

下面是使用php调用的代码:

 

<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$wsdl="http://10.10.10.10:8888/doorway/soap/doorway/doorway.wsdl";
$soap=new SoapClient($wsdl, array( 'trace'=>true,'cache_wsdl'=>WSDL_CACHE_NONE, 'soap_version'   => SOAP_1_1));
$method="Ping";
$params = array('Token'=>'E30ED3AA-65DE-48F9-BEA4-BA021B119625','UserName'=>'cccc','Password'=>'pppp', 'Echo'=>'hello');
try{
$result=$soap->$method($params);
}catch(Exception $e) {
    echo "Exception: " . $e->getMessage();
}
//$result为stdClass类型,因此不能使用 echo $result的方式输出,会报错的。
echo $result->Echo;
?>

 

最初我们调用的时候获取到的错误是找不到Ping方法,这个后来不确定是如何解决的。

后来加了SoapClient 的调用参数WSDL_CACHE_NONE让soap调用的时候不缓存wsd,以避免服务器修改了wsdl无法及时更新。设置此参数后,每次调用,都会重新load wsdl文件,因此监控java的log,将会拿到一个get请求,起初我们以为是调用wsdl的请求,后来发现,他是拿wsdl的请求。

 

过了这关后,会遇到如下错误:Unable to parse URL

 

这个原因经过google之后发现问题出在wsdl上面:<soap:address location="/soap/doorway/"/>

这里有的wsdl会:<soap:address location=""/>

这种方式使用java调用是没有问题的,但是使用php调用就是不行。再加上错误的提示信息,可以理解为,SoapClient没有智能的解析这个location,因此无法调用到soap的地址(这里称之为地址,其实我也不知道是什么意思,要想搞懂的可以看wsdl的协议。)

 

按照往上介绍的方法,在SoapClient调用里面增加参数:location =>"http://www.phpxiaoxin.com/soap/doorway"

但这种方法显然是不太好的,更好的方法是在生成的wsdl中就将location参数直接设置成绝对的url地址不要是相对的,也不要是空。

 

另外需要注意一个细节就是soap_version,分为:SOAP_1_1,SOAP_1_2 这两者发送的header是不一样的,一个是:text/xml一个是soap/xml,有的时候不兼容,就会将请求拒绝掉。

 

最后还有一个问题就是组装调用方法参数:

所调用方法应该组装的参数,主要看方法对应的wsdl中的input,对于Ping方法来说,就是PingRequest。

pingRequest继承了一个BaseRequest,那么相当于PingRequest有:token、username、password,以及自身的echo,因此将这些属性直接组装成array塞进去就ok了。

 

这里没有实验过一个方法对应多个输入对象应该如何处理,大家可以自己去试。而对已简单到String类型的输入参数来说,我这边的param为:$params = array('arg0'=>"hello111");

不过我的这个我使用的是另外一个wsdl,其输入参数的wsdl为(使用spring+cxf+aegis数据绑定生成):

 

<xsd:complexType name="sayHello">
    <xsd:sequence>
    <xsd:element minOccurs="0" name="arg0" nillable="true" type="xsd:string"/>
    </xsd:sequence>
</xsd:complexType>
 

大家可以看看对应关系。是否能看出点什么规律。而对于复杂的对象,则可以层层的array进行嵌套。可以参开这个文章:PHP SOAP如何传入复杂对象

 

 

最后提醒一下:

php使用webservice的时候,需要确认开启了php_soap、php_curl的扩展(php.ini)

关于php的soap client 以及其option参数,可以参考官网:http://www.php.net/manual/en/soapclient.soapclient.php

 

使用php最好配置上xdebug以便可以调试,看到对象的值,相当明了,

SoapClient里面有发送的request的xml一看就知道是否有问题,以及问题出在哪里。

详情可以看一下xdebug等文章。

 

再就是php调用的时候我增加了try,catch,并且将exception输出,这样输出的结果似乎比直接跑异常要详细。

因此建议大家遇到问题的时候可以catch一下,以便能够看到详细的异常信息。

 

另外如果有对spring发布webservice以及spring+cxf发布webservice有问题的也可以找相关文章看一下。这里就不贴地址了。我也曾经介绍过cxf的。

 

总结一下,出错的缘由,由于本次webservice使用了手写xsd的方式,先手工写出了xsd,然后再生成的接口和对象,因此导致location设置不兼容。

 

 

 

参考:

unable-parse-url

nusoap-how-to-change-content-type-of-request

终于解决了PHP调用SOAP过程中的种种问题

 

分享一个xml在线格式化的工具:http://www.shell-tools.net/index.php?op=xml_format

分享到:
评论

相关推荐

    Java调用php的webservice

    ### Java调用PHP的Webservice知识点详解 #### 一、Webservice简介 Webservice是一种用于不同应用程序之间进行通信的技术标准,通常使用XML作为数据交换格式。它可以被部署在不同的平台上,并且可以使用不同的编程...

    php调用java写的webservice

    在PHP调用Java Web服务的场景中,通常使用SOAP协议,因为Java的JAX-WS(Java API for XML Web Services)框架提供了SOAP Web服务的实现。PHP可以通过使用SoapClient类来访问SOAP Web服务。以下是一些关键步骤: 1. ...

    php调用webservice及myeclipse创建webservice实例

    本实例专注于PHP调用Web服务以及使用MyEclipse创建Web服务的详细过程,这对于初学者来说是一个很好的学习资源。 首先,让我们深入理解PHP调用Web服务的概念。Web服务通常基于SOAP(Simple Object Access Protocol)...

    Android调用Java WebService的实现方法.pdf

    在Android开发中,获取网络上的数据是一种常见需求。...这两者各有优缺点,前者简单易用...但对于需要处理大量数据的大型应用,使用Java、.NET或PHP等开发的Web Service进行网络数据交互,能够提供更大的灵活性和扩展性。

    php调用Java axis2发布的webservice

    2.1 用java建一个简单的工程sayHi,在里面编写一个简单的服务类sayHi,里面有一个函数sayHello. package Hi; publicclass sayHi { public String sayHello(String user,String weather) { return"Hi "+ user +". It'...

    phprpc_3.0.2_java,webservice

    这里提到的是Phprpc的3.0.2版本,针对Java平台,并且与Web服务(Webservice)相关。这通常意味着它可能提供了将Java应用程序作为Web服务公开的能力,或者可以与Web服务进行交互。 1. **Phprpc介绍**:Phprpc是一个...

    几种调用WebService的方法

    4. **PHP**:可以使用内置的`SoapClient`类来调用WebService。 每种编程语言都有其特定的库或框架支持WebService的调用,开发者应根据项目的具体需求选择合适的技术栈。 #### 结论 调用WebService的方法多种多样...

    PHP调用JAVA的WebService简单实例

    总结来说,这个例子展示了如何利用PHP调用JAVA编写的WebService,以及在服务端和客户端之间如何通过SOAP进行数据交换。在实际项目中,这种方式允许不同技术栈的应用之间进行通信,增加了系统的灵活性和可扩展性。

    调用WEBService参数

    这些服务可以被任何支持SOAP的客户端(如Java、.NET、PHP等)调用,实现跨平台的互操作性。 调用WebService的过程通常包括以下几个步骤: 1. **获取WSDL文档**:WSDL文档是WebService的接口定义,它描述了服务的...

    动态调用WebService.

    4. **SOAP客户端库**:大多数编程语言都有对应的SOAP客户端库,如Java的JAX-WS,Python的suds,PHP的SoapClient等,它们简化了动态调用Web Service的过程。开发者只需要提供WSDL地址,库会自动生成对应的调用方法。 ...

    PHP写的webservice可以供C#调用

    标题中的“PHP写的webservice可以供C#调用”意味着我们正在讨论如何使用PHP创建一个Web服务,这个服务可以通过SOAP协议被C#客户端所调用。Web服务是一种通过网络(通常是HTTP)提供功能的方式,允许不同系统之间的...

    java_webservice_myeclipse.rar

    2. 调用服务:客户端可以使用各种编程语言(如Java、.NET或PHP)的Web服务客户端库来解析WSDL,生成代理类,并通过代理类调用服务。 四、示例详解 在“java_webservice_myeclipse.rar”压缩包中,包含了详细的步骤...

    WebService服务使用Md5和SHA1加密验证登陆

    在WebService使用Md5和SHA1加密技术对用户密码进行加密处理,从而增加用户安全性。登陆判断同样通过Md5和SHA1加密密码然后和数据库经过加密密码进行比较来(它们可都是二进制滴哦!)验证用户是否存在 很好滴东西 ...

    AXIS发布webservice

    AXIS发布WebService是一个在IT行业中常见的任务,尤其在企业级应用集成或Web服务开发中扮演着重要角色。AXIS是一个开放源码的Java库,它提供了用于创建、部署和使用Web服务的工具和API。本篇文章将深入探讨AXIS如何...

    多语言调用WebService技术文档.doc

    - **PHP调用**:PHP有nusoap库,可以方便地构建和调用SOAP服务。 通过学习和掌握这些知识点,开发者能够构建和调用跨平台的WebService,解决实际工作中遇到的跨系统通信问题。无论是Windows程序员还是Linux开发者...

    PHP WebService实现

    本文主要探讨如何使用PHP构建基于SOAP(Simple Object Access Protocol)的Web Service,以及在PHP和Java中如何调用这些服务。 首先,我们需要搭建PHP的运行环境和开发环境。对于初学者,可以选择在Windows操作系统...

    转 主题:实战WebService I: XML-PRC篇(基于php)

    【标题】:“实战WebService I: XML-RPC篇(基于php)” 在Web服务的世界中,XML-RPC(XML Remote Procedure Call)是一种简单的协议,它允许客户端通过HTTP发送一个XML编码的函数调用到服务器,然后服务器执行这个...

    在Android中调用WebService实例

    我个人比较推荐的做法是使用Java或PHP等开发接口或者编写WebService进行数据库的增删该查,然后Android调用接口或者WebService进行数据的交互。本文就给大家讲解在Android中如何调用远程服务器端提供的WebService。 ...

Global site tag (gtag.js) - Google Analytics