基于Zend_Soap的webservice及其多语言通信(java)(一)
看了一下ZF手册中的关于Zend_Soap的说明,感觉很晕,不知所云,是不是个人理解有问题,那就不得而知了,总觉得没有动手做过的就算看了再多文档也不顶事,于是做了一个关于复杂对象传输的例子,对于那些简单对字符窜做的东西基本不实用,所以直接做个可以用到项目中的。
对于复杂对象的传输这里决不仅指的是数组,还有自定义对象(stdclass),有人说php数组可以解决复杂数据结构的问题用自定义对象不是多此一举,原则上是这样,但是如果涉及到多语言通信的话,问题就会暴露出来,这个我们先放一下,在说完这个实例后再谈。
Zend_Soap中的自定义对象的关键点在于annotation,annotation在java中用的较多,不知道php中是不是这么叫,总知是一个参数类型的说明,看例子。
<?php
class Role{
/**
* @return string
*/
public function getDesc() {
return $this->desc;
}
/**
* @return string
*/
public function getParentid() {
return $this->parentid;
}
/**
* @return string
*/
public function getRoleid() {
return $this->roleid;
}
/**
* @return string
*/
public function getRolename() {
return $this->rolename;
}
/**
* @param string $desc
*/
public function setDesc($desc) {
$this->desc = $desc;
}
/**
* @param string $parentid
*/
public function setParentid($parentid) {
$this->parentid = $parentid;
}
/**
* @param string $roleid
*/
public function setRoleid($roleid) {
$this->roleid = $roleid;
}
/**
* @param string $rolename
*/
public function setRolename($rolename) {
$this->rolename = $rolename;
}
/**
* @var string
*/
public $roleid;
/**
* @var string
*/
public $rolename;
/**
* @var string
*/
public $parentid;
/**
* @var string
*/
public $desc;
}
这里定义了一个Role对象,并用标明了各个成员变量的类型,注意这种annotaion是不能省略的.
下面再给一个复合的数据结构的定义。
<?php
require_once 'Priority.php';
class RolePriority{
/**
* @return Priority[]
*/
public function getPrioritys() {
return $this->prioritys;
}
/**
* @return string
*/
public function getRoleid() {
return $this->roleid;
}
/**
* @return string
*/
public function getRolename() {
return $this->rolename;
}
/**
* @param Priority[] $prioritys
*/
public function setPrioritys($prioritys) {
$this->prioritys = $prioritys;
}
/**
* @param string $roleid
*/
public function setRoleid($roleid) {
$this->roleid = $roleid;
}
/**
* @param string $rolename
*/
public function setRolename($rolename) {
$this->rolename = $rolename;
}
/**
* @var string
*/
public $rolename;
/**
* @var string
*/
public $roleid;
/**
* @var Priority[]
*/
public $prioritys;
}
这样,根据需求,一个webservice可能要设计很多这样的数据结构,这里就省略了,做法大同小异而已。
在定义完这些对象以后,我们要定义一个webservice的接口文件,也就是要这个webservice去做什么。这里定义一个名叫Gateway的文件,当然根据ZF的命名规则,这个是要加前缀的,具体怎么回事,请参考zf文档,这里不细说。
<?php
require_once 'CommonMsg.php';
require_once 'MsgResp.php';
require_once 'User.php';
require_once 'UserPriority.php';
require_once 'Userole.php';
require_once 'RolePriority.php';
require_once 'Role.php';
require_once 'Priority.php';
class Custom_Soap_Gateway{
/**
* @param string
* @param string
* @param string
* @return MsgResp
*/
public function logonUser($username, $password,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($username&&$password&&$key)
{
$user->userid ='1';
$user->sex='男';
$user->username='***';
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='login successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return MsgResp
*/
public function logoutUser($username,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($username&&$key)
{
$user->userid ='1';
$user->sex='男';
$user->username='***';
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='logout successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return Userole
*/
public function getUserRole($username,$key)
{
$userole =new Userole();
for($i=0;$i<10;$i++)
{
$role =new Role();
$role->roleid =$i;
$role->parentid='-1';
$role->rolename="role_$i";
$role->desc='xixi';
$userole->roles[$i]=$role;
}
$userole->userid='1';
$userole->username='***';
return $userole;
}
/**
* @param array
* @param string
* @return MsgResp
*/
public function modifyUser($userinfo,$key)
{
$msgResp =new MsgResp();
$user =new User();
if($userinfo&&$key)
{
$user->userid =$userinfo[0];
$user->sex =$userinfo[1];
$user->username =$userinfo[2];
}
$msgResp->user =$user;
$msgResp->code='0000';
$msgResp->msg='modify successfully';
return $msgResp;
}
/**
* @param string
* @param string
* @return UserPriority
*/
public function getUserPriority($username,$key)
{
$userPriority =new UserPriority();
if($username&&$key)
{
for($i=0;$i<10;$i++)
{
$priority =new Priority();
$priority->prid=$i;
$priority->operation="opti_$i";
$userPriority->prioritys[$i]=$priority;
}
$userPriority->userid='1';
$userPriority->username='***';
}
return $userPriority;
}
}
这里直接就给了个处理文件,返回值写死了,但做法是一样的,定义的几个方法会暴露于交互接口。
在Action中的调用处理,咱们这里就直接写了不做动态的写法。
<?php
/**
*
* @author Administrator
*
*/
class admin_SoapController extends Zend_Controller_Action {
private $_WSDL_URI="http://localhost/ZFDEMO/admin/soap/index?wsdl";
public function preDispatch() {
}
public function indexAction() {
if (isset ( $_GET ['wsdl'] )) {
//return the WSDL
$this->hadleWSDL();
} else {
//handle SOAP request
$this->handleSOAP ();
}
}
public function clientAction()
{
error_reporting( E_ALL | E_STRICT );
try {
$client = new Zend_Soap_Client('http://localhost/ZFDEMO/admin/soap/index?wsdl');
$rs_logout = $client->logoutUser('***','123456');
$rs_logon =$client->logonUser('***','123456','key');
$rs_userole =$client->getUserRole('***','123456');
$rs_priority =$client->getUserPriority('***','123456');
$userinfo =array(
'0'=>'1',
'1'=>'***',
'2'=>'男'
);
$rs_moduser =$client->modifyUser($userinfo,'11111');
Zend_Debug::dump($rs_logout,'logout user info',true);
Zend_Debug::dump($rs_moduser,'modify user info',true);
Zend_Debug::dump($rs_logon,'logon user info',true);
Zend_Debug::dump($rs_userole,'userole info',true);
Zend_Debug::dump($rs_priority,'user property info',true);
} catch (SoapFault $s) {
echo $s->faultstring;
die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring);
} catch (Exception $e) {
echo $e->getMessage();
die('ERROR: ' . $e->getMessage());
}
}
private function hadleWSDL() {
$autodiscover = new Zend_Soap_AutoDiscover ('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
$autodiscover->setUri('http://localhost/ZFDEMO/admin/soap/index');
$autodiscover->setClass ('Custom_Soap_Gateway');
$autodiscover->handle ();
}
private function handleSOAP() {
try{
$soap = new Zend_Soap_Server( $this->_WSDL_URI );
$soap->setClass('Custom_Soap_Gateway');
$soap->registerFaultException(array('Custom_Soap_SoapException'));
$soap->handle();
}catch(Exception $e)
{
echo $e->getMessage();
}
}
}
注意 http://localhost/ZFDEMO/admin/soap/index?wsdl 这个url实际上指向的就是indexAction,它的处理方法当然是hadleWSDL(), 其作用是通过我们的接口类自动生成wsdl的文件,并将其指向soap_server进行处理($autodiscover->setUri('http://localhost/ZFDEMO/admin/soap/index');),我们直接在IE上输入此URL得到wsdl的完整内容。
代码
<definitions name="Custom_Soap_Gateway" targetNamespace="http://localhost/ZFDEMO/admin/soap/index">
−
<types>
−
<xsd:schema targetNamespace="http://localhost/ZFDEMO/admin/soap/index">
−
<xsd:complexType name="User">
−
<xsd:all>
<xsd:element name="userid" type="xsd:string"/>
<xsd:element name="username" type="xsd:string"/>
<xsd:element name="sex" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
−
<xsd:complexType name="MsgResp">
−
<xsd:all>
<xsd:element name="user" type="tns:User"/>
<xsd:element name="code" type="xsd:string"/>
<xsd:element name="msg" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
−
<xsd:complexType name="ArrayOfRole">
−
<xsd:complexContent>
−
<xsd:restriction base="soap-enc:Array">
<xsd:attribute ref="soap-enc:arrayType" wsdl:arrayType="tns:Role[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
−
<xsd:complexType name="Role">
−
<xsd:all>
<xsd:element name="roleid" type="xsd:string"/>
<xsd:element name="rolename" type="xsd:string"/>
<xsd:element name="parentid" type="xsd:string"/>
<xsd:element name="desc" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
−
<xsd:complexType name="Userole">
−
<xsd:all>
<xsd:element name="username" type="xsd:string"/>
<xsd:element name="userid" type="xsd:string"/>
<xsd:element name="roles" type="tns:ArrayOfRole"/>
</xsd:all>
</xsd:complexType>
−
<xsd:complexType name="ArrayOfPriority">
−
<xsd:complexContent>
−
<xsd:restriction base="soap-enc:Array">
<xsd:attribute ref="soap-enc:arrayType" wsdl:arrayType="tns:Priority[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
−
<xsd:complexType name="Priority">
−
<xsd:all>
<xsd:element name="prid" type="xsd:string"/>
<xsd:element name="type" type="xsd:string"/>
<xsd:element name="url" type="xsd:string"/>
<xsd:element name="module" type="xsd:string"/>
<xsd:element name="operation" type="xsd:string"/>
<xsd:element name="desc" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
−
<xsd:complexType name="UserPriority">
−
<xsd:all>
<xsd:element name="username" type="xsd:string"/>
<xsd:element name="userid" type="xsd:string"/>
<xsd:element name="prioritys" type="tns:ArrayOfPriority"/>
</xsd:all>
</xsd:complexType>
</xsd:schema>
</types>
−
<portType name="Custom_Soap_GatewayPort">
−
<operation name="logonUser">
<documentation>@param string</documentation>
<input message="tns:logonUserIn"/>
<output message="tns:logonUserOut"/>
</operation>
−
<operation name="logoutUser">
<documentation>@param string</documentation>
<input message="tns:logoutUserIn"/>
<output message="tns:logoutUserOut"/>
</operation>
−
<operation name="getUserRole">
<documentation>@param string</documentation>
<input message="tns:getUserRoleIn"/>
<output message="tns:getUserRoleOut"/>
</operation>
−
<operation name="modifyUser">
<documentation>@param array</documentation>
<input message="tns:modifyUserIn"/>
<output message="tns:modifyUserOut"/>
</operation>
−
<operation name="getUserPriority">
<documentation>@param string</documentation>
<input message="tns:getUserPriorityIn"/>
<output message="tns:getUserPriorityOut"/>
</operation>
</portType>
−
<binding name="Custom_Soap_GatewayBinding" type="tns:Custom_Soap_GatewayPort">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
−
<operation name="logonUser">
<soap:operation soapAction="http://localhost/ZFDEMO/admin/soap/index#logonUser"/>
−
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</input>
−
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</output>
</operation>
−
<operation name="logoutUser">
<soap:operation soapAction="http://localhost/ZFDEMO/admin/soap/index#logoutUser"/>
−
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</input>
−
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</output>
</operation>
−
<operation name="getUserRole">
<soap:operation soapAction="http://localhost/ZFDEMO/admin/soap/index#getUserRole"/>
−
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</input>
−
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</output>
</operation>
−
<operation name="modifyUser">
<soap:operation soapAction="http://localhost/ZFDEMO/admin/soap/index#modifyUser"/>
−
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</input>
−
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</output>
</operation>
−
<operation name="getUserPriority">
<soap:operation soapAction="http://localhost/ZFDEMO/admin/soap/index#getUserPriority"/>
−
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</input>
−
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/ZFDEMO/admin/soap/index"/>
</output>
</operation>
</binding>
−
<service name="Custom_Soap_GatewayService">
−
<port name="Custom_Soap_GatewayPort" binding="tns:Custom_Soap_GatewayBinding">
<soap:address location="http://localhost/ZFDEMO/admin/soap/index"/>
</port>
</service>
−
<message name="logonUserIn">
<part name="username" type="xsd:string"/>
<part name="password" type="xsd:string"/>
<part name="key" type="xsd:string"/>
</message>
−
<message name="logonUserOut">
<part name="return" type="tns:MsgResp"/>
</message>
−
<message name="logoutUserIn">
<part name="username" type="xsd:string"/>
<part name="key" type="xsd:string"/>
</message>
−
<message name="logoutUserOut">
<part name="return" type="tns:MsgResp"/>
</message>
−
<message name="getUserRoleIn">
<part name="username" type="xsd:string"/>
<part name="key" type="xsd:string"/>
</message>
−
<message name="getUserRoleOut">
<part name="return" type="tns:Userole"/>
</message>
−
<message name="modifyUserIn">
<part name="userinfo" type="soap-enc:Array"/>
<part name="key" type="xsd:string"/>
</message>
−
<message name="modifyUserOut">
<part name="return" type="tns:MsgResp"/>
</message>
−
<message name="getUserPriorityIn">
<part name="username" type="xsd:string"/>
<part name="key" type="xsd:string"/>
</message>
−
<message name="getUserPriorityOut">
<part name="return" type="tns:UserPriority"/>
</message>
</definitions>
得到结果如下:
logout user info object(stdClass)#44 (3) {
["user"] => object(stdClass)#45 (3) {
["userid"] => string(1) "1"
["username"] => string(9) "***"
["sex"] => string(3) "男"
}
["code"] => string(4) "0000"
["msg"] => string(19) "logout successfully"
}
modify user info object(stdClass)#70 (3) {
["user"] => object(stdClass)#71 (3) {
["userid"] => string(1) "1"
["username"] => string(3) "男"
["sex"] => string(9) "***"
}
["code"] => string(4) "0000"
["msg"] => string(19) "modify successfully"
}
logon user info object(stdClass)#46 (3) {
["user"] => object(stdClass)#47 (3) {
["userid"] => string(1) "1"
["username"] => string(9) "***"
["sex"] => string(3) "男"
}
["code"] => string(4) "0000"
["msg"] => string(18) "login successfully"
}
userole info object(stdClass)#48 (3) {
["username"] => string(9) "***"
["userid"] => string(1) "1"
["roles"] => array(10) {
[0] => object(stdClass)#49 (4) {
["roleid"] => string(1) "0"
["rolename"] => string(6) "role_0"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[1] => object(stdClass)#50 (4) {
["roleid"] => string(1) "1"
["rolename"] => string(6) "role_1"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[2] => object(stdClass)#51 (4) {
["roleid"] => string(1) "2"
["rolename"] => string(6) "role_2"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[3] => object(stdClass)#52 (4) {
["roleid"] => string(1) "3"
["rolename"] => string(6) "role_3"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[4] => object(stdClass)#53 (4) {
["roleid"] => string(1) "4"
["rolename"] => string(6) "role_4"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[5] => object(stdClass)#54 (4) {
["roleid"] => string(1) "5"
["rolename"] => string(6) "role_5"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[6] => object(stdClass)#55 (4) {
["roleid"] => string(1) "6"
["rolename"] => string(6) "role_6"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[7] => object(stdClass)#56 (4) {
["roleid"] => string(1) "7"
["rolename"] => string(6) "role_7"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[8] => object(stdClass)#57 (4) {
["roleid"] => string(1) "8"
["rolename"] => string(6) "role_8"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
[9] => object(stdClass)#58 (4) {
["roleid"] => string(1) "9"
["rolename"] => string(6) "role_9"
["parentid"] => string(2) "-1"
["desc"] => string(4) "xixi"
}
}
}
user property info object(stdClass)#59 (3) {
["username"] => string(9) "***"
["userid"] => string(1) "1"
["prioritys"] => array(10) {
[0] => object(stdClass)#60 (6) {
["prid"] => string(1) "0"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_0"
["desc"] => NULL
}
[1] => object(stdClass)#61 (6) {
["prid"] => string(1) "1"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_1"
["desc"] => NULL
}
[2] => object(stdClass)#62 (6) {
["prid"] => string(1) "2"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_2"
["desc"] => NULL
}
[3] => object(stdClass)#63 (6) {
["prid"] => string(1) "3"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_3"
["desc"] => NULL
}
[4] => object(stdClass)#64 (6) {
["prid"] => string(1) "4"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_4"
["desc"] => NULL
}
[5] => object(stdClass)#65 (6) {
["prid"] => string(1) "5"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_5"
["desc"] => NULL
}
[6] => object(stdClass)#66 (6) {
["prid"] => string(1) "6"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_6"
["desc"] => NULL
}
[7] => object(stdClass)#67 (6) {
["prid"] => string(1) "7"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_7"
["desc"] => NULL
}
[8] => object(stdClass)#68 (6) {
["prid"] => string(1) "8"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_8"
["desc"] => NULL
}
[9] => object(stdClass)#69 (6) {
["prid"] => string(1) "9"
["type"] => NULL
["url"] => NULL
["module"] => NULL
["operation"] => string(6) "opti_9"
["desc"] => NULL
}
}
}


浙公网安备 33010602011771号