公司因业务需求准备开放一些API接口让代理商使用,周末抽了些时间了解了一下这方面的技术后,决定采用caucho.com的Hessian实现(hessian使用方便又高效)
测试环境
Window XP
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代码
include_once '../dist/Hessian.php' ;
include_once '../dist/HessianClient.php' ;
Hessian :: mapRemoteType('com.hisupplier.showroom.webservice.QueryParams' , 'QueryParams' );
Hessian :: mapRemoteType('com.hisupplier.showroom.webservice.ListResult' , 'ListResult' );
Hessian :: mapRemoteType('com.hisupplier.showroom.entity.Product' , 'Product' );
Hessian :: mapRemoteType('com.hisupplier.commons.page.Page' , 'Page' );
try {
$params = new QueryParams(114);
$url = "http://guiyou.jiaming.com/webService" ;
$proxy = new HessianClient( $url );
echo "<br>" ;
print_r($proxy ->hello( $params ));
echo "<br>" ;
print_r($proxy ->getProduct( $params ));
echo "<br>" ;
print_r($proxy ->getList( $params )); //要命的问题出在这里
} catch (HttpError $ex ) {
...
}
Java代码
public interface ShowroomAPI {
String hello(QueryParams params);
ListResult<Product> getList(QueryParams params);
Product getProduct(QueryParams params);
}
第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's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used 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 in G://php//HessianPHP//dist//Hessian.php on line 74
解决: 将date() 方法都改为 date_default_timezone_set()
第3个问题
Php代码
Exception: Hessian Parser, Malformed reply: expected r Code: 2 exception 'HessianError' with message 'Hessian Parser, Malformed reply: expected r' in E:/workspace/php-test/dist/Protocol.php:339 Stack trace:
#0 E:/workspace/php-test/dist/HessianClient.php(215): HessianParser->parseReply()
#1 E:/workspace/php-test/dist/Filter.php(159): HessianProxy->executeCall('getList' , Array)
#2 E:/workspace/php-test/dist/Filter.php(73): ProxyFilter->execute(Object(HessianProxy), Object(FilterChain))
#3 E:/workspace/php-test/dist/Filter.php(191): FilterChain->doFilter(Object(HessianProxy))
#4 E:/workspace/php-test/dist/Filter.php(73): PHPErrorReportingFilter->execute(Object(HessianProxy), Object(FilterChain))
#5 E:/workspace/php-test/dist/HessianClient.php(182): FilterChain->doFilter(Object(HessianProxy))
#6 E:/workspace/php-test/dist/HessianClient5.php(94): HessianProxy->call('getList' , Array)
#7 [internal function ]: HessianClient->__call( 'getList' , Array)
#8 E:/workspace/php-test/tests/test.php(23): HessianClient->getList(Object(QueryParams))
#9 {main}
google, baidu了半天也没找到相关的文章,后来把apache和php分别降到2.0和5.1还是不行,最后快放弃了试了一下yahoo,哦!my god佛祖保佑阿门,让我找了一了篇文章
引用
Chunked http responses cause a protocol parse error
Http.php is written to perform an HTTP POST using HTTP/1.1 which means that
the Hessian client must support a HTTP header of "Transfer-Encoding:
chunked".
Protocol::parseReply() is written as follows:
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 will contain
the chunk length. Protocol::parseReply() needs to be written to support
chunking.
At the moment the workaround I have is to set HTTP/1.0 in Http::POST.
解决: 把Http.php中的1.1改为1.0
在Http.php第200行: $out = "POST $this->url HTTP/1.1/r/n";
第4个问题,由于BOM头引起,在调用过程中包含的文件有BOM,BOM在调用中先输出,引起Hessian失败,对于是UTF8编辑的文件,仔细检查包含文件中是否有BOM头的文件。下面有一段去BOM头的PHP代码,把这段代码保存在WEB文件目录下。直接执行可以查看是否有BOM头的文件,把$auto = 1; 则会自动删除BOM头。
<?php if (isset($_GET['dir'])){ //设置文件目录 $basedir=$_GET['dir']; }else{ $basedir = '.'; } $auto = 0; checkdir($basedir); function checkdir($basedir){ if ($dh = opendir($basedir)) { while (($file = readdir($dh)) !== false) { if ($file != '.' && $file != '..' && $file != '.svn'){ if (!is_dir($basedir."/".$file)) { echo "filename: $basedir/$file ".checkBOM("$basedir/$file").PHP_EOL; }else{ $dirname = $basedir."/".$file; checkdir($dirname); } } } closedir($dh); } } function checkBOM ($filename) { global $auto; $contents = file_get_contents($filename); $charset[1] = substr($contents, 0, 1); $charset[2] = substr($contents, 1, 1); $charset[3] = substr($contents, 2, 1); if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) { if ($auto == 1) { $rest = substr($contents, 3); rewrite ($filename, $rest); return ("<font color=red>BOM found, automatically removed.</font><br />"); } else { return ("<font color=red>BOM found.</font><br />"); } } else return ("BOM Not Found.<br />"); } function rewrite ($filename, $data) { $filenum = fopen($filename, "w"); flock($filenum, LOCK_EX); fwrite($filenum, $data); fclose($filenum); } ?>
目前最新版本是HessianPHP_v2.0.3, 如果PHP版本是5.3以上最好选择HessianPHP_v2.0.3版本。
下载地址:http://nchc.dl.sourceforge.net/project/hessianphp/HessianPHP/HessianPHP%202/HessianPHP_v2.0.3.zip
使用教程:http://hessianphp.sourceforge.net/index.php?n=Main.QuickStart