微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

webservice的调用

首先说明一下,这个小程序是我自己用PHP写成的一个简单的webservice系统,包括服务端的程序和客户端的程序,无论是服务端还是客户端在使用起来都非常的简单方便,也可以很方便的移植到自己的项目里,我自己也已经在稍微改造后用在了自己的项目里,应用到生产环境2个多月以来都很稳定,没有出过什么问题。 

这个简单的webservice小程序有以下几个优点: 
1. 简单、易用,几乎没有什么学习成本 
2. 可扩展性很强,因为简单,所以你可以在这个基础上扩展出很多的东西,比如返回的数据格式上可以加上xml的支持等,这个就需要自己动手了 
3. 数据传输量小,服务端到客户端的数据传输采用gzip压缩的方式,极大的减小了数据的体积,我自己做的测试是,一份4.7M的html数据在压缩后只有113K 
4. 有一定的安全性,首先服务端和客户端之间的通讯会有密钥机制,同时又采取限定IP的方式保护了接口的安全。
当然,也有缺点:比如程序过于简单,没有对安全性和数据过过多的校验,这个在应用到生产环境之前一定要记得加强一下;客户端到服务端的请求认采用get形式,传输的数据量有限,这个我会考虑在以后的改进中改为post,同时数据也采用gzip压缩以后传输。 
好了,言归正传,下面介绍一下代码本身: 
首先是服务端,服务端有一个主要的class组成:apiServer.PHP 
PHP代码  

收藏代码

  1. <?PHP  
  2. /** 
  3.  * apiServer.PHP 
  4.  * 
  5.  * webservice主类 
  6.  * @filename apiServer.PHP 
  7.  * @version  v1.0 
  8.  * @update   2011-12-22 
  9.  * @author   homingway 
  10.  * @contact  [email protected] 
  11.  * @package  webservice 
  12.  */  
  13. define('API_AUTH_KEY',  'i8XsJb$fJ!87FblnW');  
  14. class apiServer{  
  15.   
  16.     //请求参数  
  17.     public $request = array();  
  18. //是否ip限制  
  19. public $ip_limit = true;  
  20. //允许访问的IP列表  
  21. public $ip_allow = array('127.0.0.1','192.168.0.99');  
  22. public $default_method = 'welcome.index';  
  23. public $service_method = //私有静态单例变量  
  24. private static $_instance = null;  
  25.      * 构造方法,处理请求参数 
  26.      */  
  27. function __construct(){  
  28.         $this->dealRequest();  
  29.     }  
  30.      * 单例运行 
  31. public static function getInstance(){  
  32.         if(self::$_instance === null){  
  33.             self::$_instance = new self();  
  34.         }  
  35. return self::$_instance;  
  36.      * 运行 
  37. function run(){  
  38.         //授权  
  39. if(!$this->checkAuth()){  
  40.             exit('3|Access Denied');  
  41.         $this->getApiMethod();  
  42. include_once(API_SERVICE_PATH.'/'.$this->service_method['service'].'.PHP');  
  43.         $serviceObject = new $this->service_method['service'];  
  44. if($this->request['param']){  
  45.             $result = call_user_func_array(array($serviceObject,$this->service_method['method']),$this->request['param']);  
  46.         } else {  
  47.             $result = call_user_func($this->service_method['method']));  
  48. if(is_array($result)){  
  49.             $result = json_encode($result);  
  50.         $result = gzencode($result);  
  51.         exit($result);  
  52.      * 检查授权 
  53. function checkAuth(){  
  54. //检查参数是否为空  
  55. if(!$this->request['time'] || !$this->request['method']   || !$this->request['auth']){  
  56.             return false;  
  57. //检查auth是否正确  
  58.         $server_auth = md5(md5($this->request['time'].'|'.$this->request['method'].'|'.API_AUTH_KEY));  
  59. if($server_auth != $this->request['auth']){  
  60. //ip限制  
  61. if($this->ip_limit){  
  62.             $remote_ip = $this->getIP();  
  63.             $intersect = array_intersect($remote_ip,$this->ip_allow);  
  64. if(emptyempty($intersect)){  
  65.                              }  
  66. return true;  
  67.      * 获取服务名和方法名 
  68. function getApiMethod(){  
  69. if(strpos($this->request['method'], '.') === false){  
  70.             $method = $this->default_method;  
  71.             $method = $this->request['method'];  
  72.         $tmp = explode('.'$method);  
  73.         $this->service_method = array('service'=>$tmp[0],'method'=>$tmp[1]);  
  74. return $this->service_method;  
  75.      * 获取和处理请求参数 
  76. function dealRequest(){  
  77.         $this->request['time'] = $this->_request('time');  
  78.         $this->request['method'] = $this->_request('method');  
  79.         $this->request['param'] = $this->_request('param');  
  80.         $this->request['auth'] = $this->_request('auth');  
  81.             $this->request['param'] = json_decode(urldecode($this->request['param']),true);  
  82.      * 获取request变量 
  83.      * @param string $item 
  84. function _request($item){  
  85. return isset($_REQUEST[$item]) ? trim($_REQUEST[$item]) : '';  
  86.      * 设置IP限制 
  87.      * @param bool $limit 
  88. function setIPLimit($limit=true){  
  89.         $this->ip_limit = $limit;  
  90.      * 获取客户端ip地址 
  91. function getIP(){  
  92.         $ip = if(isset($_SERVER['REMOTE_ADDR'])){  
  93.             $ip[] = $_SERVER['REMOTE_ADDR'];  
  94. if(isset($_SERVER['HTTP_VIA'])){  
  95.             $tmp = explode(', ',$_SERVER['HTTP_X_FORWARDED_FOR']);  
  96.             $ip = array_merge($ip,$tmp);  
  97.         $ip = array_unique($ip);  
  98. return $ip;  
  99. }  

然后在服务端的入口文件调用该class,并启动服务即可,如: 
 * server.PHP 
  •  * 自定义数据接口的入口 
  •  * @filename server.PHP 
  • //API的根目录  
  • define('API_PATH',dirname(__FILE__));  
  • //服务目录  
  • define('API_SERVICE_PATH',API_PATH.'/service');  
  • define('API_LIB_PATH',  API_PATH.'/lib');  
  • //服务核心class  
  • include_once(API_LIB_PATH.'/apiServer.PHP');  
  • //运行  
  • apiServer::getInstance()->run();  

  • 然后创建一个service的目录,里面就是自己的接口class,如welcome.PHP: 
     * welcome.PHP 
  •  * 功能代码 
  •  * @filename welcome.PHP 
  • class welcome{  
  • function index(){  
  • return 'hello service';  
  • 下面是客户端的主程序:apiclient.PHP 
     * apiclient.PHP 
  •  * webservice客户端程序 
  •  * @filename apiclient.PHP 
  • class apiclient{  
  • function send($url,$method,$param=array()){  
  •         $time = time();  
  •         $auth = md5(md5($time.'|'.$method.'|'.API_AUTH_KEY));  
  • if(!is_array($param) || emptyempty($param)){  
  •             $json_param = '';  
  •             $json_param = urlencode(json_encode($param));  
  •         $api_url = $url.'?method='.$method.'&time='.$time.'&auth='.$auth.'&param='.$json_param;  
  •         $content = file_get_contents($api_url);  
  • if(function_exists('gzdecode')){  
  •             $content = gzdecode($content);  
  •             $content = self::gzdecode($content);  
  • return $content;  
  • function gzdecode($data) {  
  •         $len = strlen ( $data );  
  • if ($len < 18 || strcmp ( substr ( $data, 0, 2 ), "\x1f\x8b" )) {  
  • return null; // Not GZIP format (See RFC 1952)  
  •         $method = ord ( substr ( $data, 2, 1 ) ); // Compression method  
  •         $flags = ord ( substr ( $data, 3,0); padding:0px; margin:0px; width:auto; border:0px">// Flags  
  • if ($flags & 31 != $flags) {  
  •             // Reserved bits are set -- NOT ALLOWED by RFC 1952  
  • return null;  
  • // NOTE: $mtime may be negative (PHP integer limitations)  
  •         $mtime = unpack ( "V"substr ( $data, 4, 4 ) );  
  •         $mtime = $mtime [1];  
  •         $xfl = substr ( $data, 8, 1 );  
  •         $os = substr ( $data,250); line-height:18px">         $headerlen = 10;  
  •         $extralen = 0;  
  •         $extra = "";  
  • if ($flags & 4) {  
  • // 2-byte length prefixed EXTRA data in header  
  • if ($len - $headerlen - 2 < 8) {  
  • return false; // Invalid format  
  •             $extralen = unpack ( "v", 2 ) );  
  •             $extralen = $extralen [1];  
  • if ($len - $headerlen - 2 - $extralen < 8) {  
  •             $extra = substr ( $data, 10, $extralen );  
  •             $headerlen += 2 + $extralen;  
  •         $filenamelen = 0;  
  •         $filename = "";  
  • if ($flags & 8) {  
  • // C-style string file NAME data in header  
  • if ($len - $headerlen - 1 < 8) {  
  •             $filenamelen = strpos ( substr ( $data, 8 + $extralen ), chr ( 0 ) );  
  • if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {  
  •             $filename = substr ( $data$headerlen$filenamelen );  
  •             $headerlen += $filenamelen + 1;  
  •         $commentlen = 0;  
  •         $comment = "";  
  • if ($flags & 16) {  
  • // C-style string COMMENT data in header  
  •             $commentlen = strpos ( substr ( $data, 8 + $extralen + $filenamelen ),85); font-weight:bold">if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {  
  • // Invalid header format  
  •             $comment = substr ( $data$commentlen );  
  •             $headerlen += $commentlen + 1;  
  •         $headercrc = "";  
  • if ($flags & 1) {  
  • // 2-bytes (lowest order) of CRC32 on header present  
  •             $calccrc = crc32 ( substr ( $data$headerlen ) ) & 0xffff;  
  •             $headercrc = unpack ( "v",250); line-height:18px">             $headercrc = $headercrc [1];  
  • if ($headercrc != $calccrc) {  
  • // Bad header CRC  
  •             $headerlen += 2;  
  • // GZIP FOOTER - These be negative due to PHP's limitations  
  •         $datacrc = unpack ( "V", - 8,250); line-height:18px">         $datacrc = $datacrc [1];  
  •         $isize = unpack ( "V", - 4 ) );  
  •         $isize = $isize [1];  
  • // Perform the decompression:  
  •         $bodylen = $len - $headerlen - 8;  
  • if ($bodylen < 1) {  
  • // This should never happen - IMPLEMENTATION BUG!  
  •         $body = substr ( $data$bodylen );  
  •         $data = "";  
  • if ($bodylen > 0) {  
  • switch ($method) {  
  • case 8 :  
  •                     // Currently the only supported compression method:  
  •                     $data = gzinflate ( $body );  
  •                     break;  
  • default :  
  • // UnkNown compression method  
  • // I'm not sure if zero-byte body content is allowed.  
  • // Allow it for Now...  Do nothing...  
  • // Verifiy decompressed size and CRC32:  
  • // NOTE: This may fail with large data sizes depending on how  
  • //       PHP's integer limitations affect strlen() since $isize  
  • //       may be negative for large sizes.  
  • if ($isize != strlen ( $data ) || crc32 ( $data ) != $datacrc) {  
  • // Bad format!  Length or CRC doesn't match!  
  • return $data;  
  • 使用起来非常简单,下面是一个调用程序: 
     * demo.PHP 
  •  * 客户端调用示例 
  •  * @filename demo.PHP 
  • include_once('../client/apiclient.PHP');  
  • $server_uri = 'http://localhost/webservice/server/server.PHP';  
  • print_r(apiclient::send($server_uri,'welcome.index'));  

  • 本文所涉及到的所有代码及主程序我都打包到下面的zip文件中,可以直接下载,有什么疑问可以直接在下面留言回复。 

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

    相关推荐