hessian的使用

4 篇文章 0 订阅
1 篇文章 0 订阅

转自:http://blog.sina.com.cn/s/blog_46d93f190102uz6a.html

HessianPHP_v2.0.3.zip, 在php作客户端,java作服务器端时,使用注意事项:

1.需要在php.ini中配置CURL模块:
extension=php_curl.dll

2.php传中文给java, 和java返回中文给php,都有中文乱码问题:
1)php和java文件本身都采用UTF-8编码
2)在php.ini中开启mbstring模块:
extension=php_mbstring.dll
同时配置:
mbstring.internal_encoding = UTF-8

因为:
Hessian2Writer.php文件:
 

     function  writeStringData ($string){
              returnHessianUtils::writeUTF8($string);
       }

HessianUtils.php文件:
       publicstatic function isInternalUTF8(){
              $encoding= ini_get(' mbstring.internal_encoding ');
              if(!$encoding)
                     returnfalse;
              return$encoding == 'UTF-8';
       }

3).response返回设置为UTF-8:
header("Content-Type: text/html; charset=UTF-8");

或者,统一改php.ini文件:
mbstring.http_output = UTF-8
;启用字符转换功能
output_handler= mb_output_handler

4)默认配置:
HessianFactory.php
define('HESSIAN_PHP_VERSION','2.0');   --------->hessian2.0协议

              $this->transports= array(
                     'CURL'=> 'HessianCURLTransport',   ----------->传输协议
                     'curl'=> 'HessianCURLTransport',
                     'http'=> 'HessianHttpStreamTranspo rt'
              );


3.java返回值问题:
1).java端返回( 自定义的 )对象,在php端为 stdClassObject ,它具有一个属性 [__type] => org.model.User

2).而对于普通对象,例如java的Date对象,在php就是DateTime对象:
[birthday] =>  DateTimeObject  ([date] => 2012-07-27 15:27:31 [timezone_type] => 1 [timezone]=> +00:00 )

3).java的List, Set, Map,在php就是Array.
List为php的序号数组:
[productList1] => Array (
         [0]=> stdClass Object ( [__type] => org.model.Product [name]=> 布匹 [price] => 300 )
)
Map为php的名称数组:
[productMap] => Array (
         [布匹]=> stdClass Object ( [__type] => org.model.Product [name]=> 布匹 [price] => 300 )
)

java的返回值,php端不需要做任何特殊映射,可以直接采用->x->y的方式去取值显示.

4).同一个对象,即放在List中,又放在Map中,返回值中为什么只显示一处有值?
这其实是HessianPHP_v2.0.3.zip的一个bug.
hessian协议中为了减少重复对象的序列化,采用了引用的方式,参见:
Hessian 2.0 序列化协议规范
http://wenku.baidu.com/view/3832199951e79b8968022641.html

经过debug调试,发现:
需要修改Hessian2Parser.php中
function untypedMap($code, $num){
//                      if(HessianRef::isRef($key))$key =&$this->objectlist->reflist[$key->index];
//                      if(HessianRef::isRef($value))$value =&$this->objectlist->reflist[$value->index];
                     if(HessianRef::isRef($key))$key =  $this->refmap->objectlist[$value->index] ;
                     if(HessianRef::isRef($value))$value =  $this->refmap->objectlist[$value->index] ;

}
同样下面方法也需要修改:
function typedMap($code, $num)
{
...
}

测试结果:
objectstdClass Object ( [__type] => User [name] =>yangwenchao杨文超 [country] => CHINA [birthday] => DateTimeObject ( [date] => 2012-07-28 09:02:32 [timezone_type] => 1[timezone] => +00:00 ) [productList1] => Array ( [0]=>  stdClassObject ( [__type] => Product [name] => 布匹 [price] => 300)  )[productList2] => Array ( ) [productList3] => [productMap]=> Array ( [布匹一] =>  stdClassObject ( [__type] => Product [name] => 布匹 [price] => 300)  [布匹二]=> stdClassObject ( [__type] => Product [name] => 布匹 [price] => 300)  ))

4.php向java传参问题:

5.关于类型映射:
php是无类型的,默认情况下远程的Object都会变成php的stdClass这样的万能对象。持有这样的对象进行访问的时候,关于对象的属性name,price等信息需要尝试指定。(工作正常)

但是如果把远程Object映射成php本地的自定义的phpObject以后,就可以用一个对象的模子class来框住对象的实体形式,而且编辑器还可以支持语法提示功能。

采用这种方式,在解析返回值时,可以得到便利,在向Java传递对象作为参数时,也可以提供一些便利。

$options = new HessianOptions();

$options->typeMap['Person'] = '*.Person';

$options->typeMap['CalendarHandler'] = 'com.caucho.hessian.io.CalendarHandle';

$options->parseFilters['@CalendarHandler'] = array('CalendarHandler','calendarToDateTime');

$options->writeFilters['@Person'] = array('CalendarHandler','writePerson');

参见例子:
AdvancedExample   Advancedtype mapping and filtering
http://code.google.com/p/hessianphp/wiki/AdvancedExample


如果不采用自动映射方式,php向java传参时,只能采用php原生的stdClass来传值:
               $person= new stdClass();           
               $person->__type= 'org.model.Person';//参照java返回值的形式,添加上__type属性,其实无效.
               $person->id= 1;
               $person->firstName= '杨';
               $person->lastName= '文超';
               //$person->birthDate= '';             
             
               $user= $proxy->getUserABC($person);

在java端,总是抛出warning,显然,java端无视了参数$person->__type的意义:
java.lang.ClassNotFoundException: stdClass
2012-7-28 11:13:22 com.caucho.hessian.io.SerializerFactorygetDeserializer
警告:  Hessian/Burlap:'stdClass' is an unknown class inWebappClassLoader
   context:/springhessian
   delegate:false
   repositories:
       /WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@1adc30

去掉warning的解决办法:
$options->typeMap['stdClass'] ='org.model.Person';

              $options= new HessianOptions();
        $options->typeMap['stdClass']='org.model.Person';           
            
               $url="http://localhost:8080/springhessian/remoting/hessianService"; 
               $proxy= new HessianClient($url,$options); 
               echo"
"; 

             
                $person= new stdClass();            
               $person->__type= 'org.model.Person';
               $person->id= 1;
               $person->firstName= '杨';
               $person->lastName= '文超';
               //$person->birthDate= '';             
             
               $user= $proxy->getUserABC($person);

工作正常。

但是这种方法,只能应对一个类型参数,如果有两个类型的参数,如org.model.Person和org.model.Company,就又无法正常工作了,因为stdClass不知道到底需要映射到哪一个Java类型上。

所以,在php向java传参时,需要在php中自定义若干个与java相对应的类型,配合
$options->typeMap['Person'] ='org.model.Person';
来一起完成参数类型映射功能。
例如:
class
  Person {
        var $id;

        var $firstName;

        var $lastName;

        var $birthDate;
}

$p = new Person();

$p->firtName = 'John';

$p->lastName = 'Sheppard';

$options   =   new   HessianOptions ();
$options
-> typeMap [ 'Person' ]   =   'com.sample.hessian.Person' ;
$proxy = new HessianClient($url, $options);
$result = $proxy->add($p);
print_r($result);



另外:

$options->typeMap['Person']='com.sample.hessian.Person';->精确指定,可用于解析返回值,也可用于传参
$options->typeMap['Person']='*.Person';  ------>采用通配,只适用于解析返回值,不能用于传参



6.关于类型自动映射的,回调处理:
$options->parseFilters['@CalendarHandler'] = array('CalendarHandler','calendarToDateTime');

$options->writeFilters['@Person'] = array('CalendarHandler','writePerson');



对于包装类型,有两种方式处理:一是原生构建层级关系,二是采用回调去除包装


一是原生构建层级关系:
$p = new Person();

$p->firstName = 'John';

$p->lastName = 'Sheppard';

$p->birthDate = new CalendarHandler(new DateTime('1970-06-14 12:00:00'));
... send the object


二是采用回调去除包装

$options->parseFilters['@CalendarHandler'] = array('CalendarHandler','calendarToDateTime');

$options->writeFilters['@Person'] = array('CalendarHandler','writePerson');



建议尽量不要有包装类型,如果一定有,采用“原生层级类型”比较容易理解一些。



7.原生传值:

    public User getUserList(List list);  -------->List  ------>对应于php的数字array

    public User getUserSet(Set set);  -------->Set ------>对应于php的名字array
    public User getUserMap(Map map);  -------->Map ------>对应于php的名字array



        //$parameter = array('杨', '文超'); //数字array        

        //$parameter = array('firstName'=>'杨', 'lastName'=>'文超');//名字array   

        $parameter = array('firstName'=>'杨', 'lastName'=>'文超');  //名字array        

        //$user = $proxy->getUserList($parameter);

        //$user = $



再转一篇:

PHP调用hessian接口

转自:http://blog.sina.com.cn/s/blog_46d93f190102uz4e.html

公司因业务需求准备开放一些API接口让代理商使用,周末抽了些时间了解了一下这方面的技术后,决定采用caucho.com的Hessian实现(hessian使用方便又高效) 

测试环境 

  • WindowXP
  • JDK 1.6
  • Resin3.1.9
  • Spring2.0.8
  • hessian-3.0.20.jar(这个版本要与spring的对应,不要一味的追求最新版,我因为这个,不知是好还是坏的毛病吃了N多苦头)
  • HessianPHP-1.0.5-RC2
  • Apache2.2
  • PHP5.3.0

刚开始跑Java服务器端和客服端的测试都很顺利,但是当使用php5.3做为客户端访问Java时出现了好几个问题 
Php代码    收藏代码
  1. include_once '../dist/Hessian.php' 
  2. include_once '../dist/HessianClient.php' 
  3.   
  4. Hessian :: mapRemoteType('com.hisupplier.showroom.webservice.QueryParams''QueryParams');  
  5. Hessian :: mapRemoteType('com.hisupplier.showroom.webservice.ListResult''ListResult');  
  6. Hessian :: mapRemoteType('com.hisupplier.showroom.entity.Product''Product');  
  7. Hessian :: mapRemoteType('com.hisupplier.commons.page.Page''Page');  
  8.   
  9. try  
  10.     $params new QueryParams(114);  
  11.   
  12.     $url "http://guiyou.jiaming.com/webService" 
  13.     $proxy new HessianClient($url);  
  14.     echo "
    "
     
  15.     print_r($proxy->hello($params));  
  16.     echo "
    "
     
  17.     print_r($proxy->getProduct($params));   
  18.     echo "
    "
     
  19.     print_r($proxy->getList($params)); //要命的问题出在这里  
  20. catch (HttpError $ex)  
  21.     ...  
  22.  

Java代码    收藏代码
  1. public interface ShowroomAPI  
  2.     String hello(QueryParams params);  
  3.     ListResult getList(QueryParams params);  
  4.     Product getProduct(QueryParams params);  
  5.  

第1个问题  
因为php5.2.x版本后自带了DateTime类,和 HessianPHP中的发生冲突 
解决: 改文件DateTime.php为 HessianDateTime.php,类DateTime 为HessianDateTime 

第2个问题  
PHP Warning: date(): It is not safe to rely on the system'stimezone settings. You are *required* to use the date.timezonesetting or the date_default_timezone_set() function. In case youused any of those methods and you are still getting this warning,you most likely misspelled the timezone identifier. We selected'UTC' for '8.0/no DST' instead inG:\\php\\HessianPHP\\dist\\Hessian.php on line74 
解决: 将date()方法都改为date_default_timezone_set() 

第3个问题  
Php代码    收藏代码
  1. Exception: Hessian Parser, Malformed reply: expected Code: exception 'HessianError' with message 'Hessian Parser, Malformed reply: expected r' in E:\workspace\php-test\dist\Protocol.php:339 Stack trace:   
  2. #0 E:\workspace\php-test\dist\HessianClient.php(215): HessianParser->parseReply()   
  3. #1 E:\workspace\php-test\dist\Filter.php(159): HessianProxy->executeCall('getList'Array)   
  4. #2 E:\workspace\php-test\dist\Filter.php(73): ProxyFilter->execute(Object(HessianProxy), Object(FilterChain))   
  5. #3 E:\workspace\php-test\dist\Filter.php(191): FilterChain->doFilter(Object(HessianProxy))   
  6. #4 E:\workspace\php-test\dist\Filter.php(73): PHPErrorReportingFilter->execute(Object(HessianProxy), Object(FilterChain))   
  7. #5 E:\workspace\php-test\dist\HessianClient.php(182): FilterChain->doFilter(Object(HessianProxy))   
  8. #6 E:\workspace\php-test\dist\HessianClient5.php(94): HessianProxy->call('getList'Array)   
  9. #7 [internal function]: HessianClient->__call('getList'Array)   
  10. #8 E:\workspace\php-test\tests\test.php(23): HessianClient->getList(Object(QueryParams))   
  11. #9 {main}  

google,baidu了半天也没找到相关的文章,后来把apache和php分别降到2.0和5.1还是不行,最后快放弃了试了一下yahoo,哦!mygod佛祖保佑阿门,让我找了一了篇文章
引用

Chunked http responses cause a protocol parseerror 

Http.php is written to perform an HTTP POST using HTTP/1.1 whichmeans that 
the Hessian client must support a HTTP header of"Transfer-Encoding: 
chunked". 

Protocol::parseReply() is written asfollows: 

if($this->read(1) != 'r') { 
return new HessianError('Hessian Parser, Malformed reply:expected 
r',HESSIAN_PARSER_ERROR,0,$this->stream); 


which will fail because the first line of a chunked response willcontain 
the chunk length. Protocol::parseReply() needs to be written tosupport 
chunking. 

At the moment the workaround I have is to set HTTP/1.0 inHttp::POST.

解决: 把Http.php中的1.1改为1.0 
在Http.php第200行: $out = "POST $this->urlHTTP/1.1\r\n"; 

原来是因为http/1.1中Transfer-Encoding:chunked编码的包是分段发送的,我最后一个方法$proxy->getList($params)Java服务器端返回的数据量太大了,php这里没接收完整引起的。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值