实践基于REST风格的Webservice(PHP,C#)
概念: WEB服务的风格,从维基百科上查了一下,有不下十几种,但是比较常用的就是REST和RPC。其中,基于SOAP协议的Webservice就是RPC风格的。 REST全称Representational State Transfer。它是基于无状态的,cs结构的,可以缓存的通信协议。事实上,它是使用 HTTP协议的。某些观点来看,互联网本身就是基于HTTP的,因此也可以认为是一种基于REST风格的Webservice。REST风格的Webservice对于SOAP,CORBA(一种和SOAP互相竞争的协议)来说,属于轻量级。请求较之于也比较简单。比如,用SOAP的Webservice的请求可能是如下这样的一个XML,有用的信息都被包括在冗余的信息中: <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:body pb="http://www.acme.com/phonebook"> ?<pb:GetUserDetails> ? <pb:UserID>12345</pb:UserID> ?</pb:GetUserDetails> </soap:Body> </soap:Envelope> 而使用REST的请求就很简单,只是一个URL地址:http://www.acme.com/phonebook/UserDetails/12345,只需要使用浏览器就能验证这个REST的Webservice是否正常。HTTP的请求方式有多种,GET,POST,PUT,PATCH,DELETE。REST同样可以利用这些请求方式。REST的Webservice的响应通常是一个XML文件,但是和SOAP不同的是,REST并不一定需要响应返回XML文件,它也可以是CSV格式或者Json格式。 很多公司都采用REST风格的Webservice,比如 Google Glass API,Twitter,Yahoo,Flickr,Amazon等。比如Google有一个Webservice,Google Maps API,它提供2种输出格式,JSON和XML。地址分别是http://maps.googleapis.com/maps/api/geocode/json?parameters和http://maps.googleapis.com/maps/api/geocode/xml?parameters 该服务的具体使用方法和参数满可以查阅https://developers.google.com/maps/documentation/geocoding/?hl=zh-CN&csw=1#XML 演示: 下面演示一个基于PHP语言开发的REST风格的webservice。 <?php switch($_SERVER['REQUEST_METHOD']) { case 'GET': $id=$_GET["id"]; $arrayid = explode(",",$id); search($arrayid); break; case 'POST': $id=$_POST["id"]; $username=$_POST["username"]; $sex=$_POST["sex"]; $age=$_POST["age"]; add($id,$username,$sex,$age); break; default: exit(); } function search($arrayid) { $users=getCsvFile("example.csv"); $string=""; foreach($users as $a) { $id=$a[0]; if(in_array($id,$arrayid)) { $string.= <<<EOF <user id="$a[0]"> <name>$a[1]</name> <sex>$a[2]</sex> <age>$a[3]</age> </user> EOF; } } $string="<?xml version="1.0" encoding="UTF-8"?>rn" ."<data>rn" .$string ."</data>"; header("Content-type:application/xml"); print($string); } function add($id,$age) { $users=getCsvFile("example.csv"); $string="$id,$age"; WriteLinetxt($string,"example.csv"); $string="<?xml version="1.0" encoding="UTF-8"?>rn" ."<return>rn" ." <status>0</status>rn" ."</return>rn"; header("Content-type:application/xml"); print($string); } function getCsvFile($filepath) { $handle=null; $returnvalue=array(); try { $handle = fopen($filepath,"r"); while ($data = fgetcsv($handle,1000,")) { array_push($returnvalue,$data); } fclose($handle); } catch(Exception $e) { fclose($handle); $handle=null; die("Error!: ".$e->getMessage()."<br/>"); } return $returnvalue; } function WriteLinetxt($content,$filename) { file_put_contents($filename,$content."rn",FILE_APPEND); } ?> 代码说明: 上述代码,根据请求的方式是POST还是GET来区分,如果是GET的话,则需带上查询的ID。服务会返回一个Content-type为application/xml的一份xm文档。如果是POST的话,则会把相应的POST进来的值写入到数据库。 本例中,数据库只是简单的采用CSV文件,即用逗号分割数据的文本文件。数据文件如下: 由于REST风格的web服务可以通过浏览器验证,因此可以输入url地址测试。本例中没有采用url重写,如果使用url重写的话,服务地址会更友好。 服务部署好之后,就可以调用了。在PHP中,可以通过simplexml_load_file方法,get到这个xml文件。 <?php $url="http://localhost:8080/b.php?id=1001,1003,1004"; $response=simplexml_load_file($url); var_dump($response); ?> 通过var_dump,可以看到获得的直接是一个SimpleXMLElement对象,当然你也可以把它转换成string对象。 下面用php代码实现模拟POST数据。PHP常用的模拟POST动作的方法有3种,分别为Curl、socket、file_get_contents,这里还是采用file_get_contents方法。代码如下: <?php $url="http://localhost:8080/b.php"; $data = array ( 'id' => '1990','username' => '小张','sex' => '男','age'=>'20' ); $post_string=http_build_query($data); $context = array( 'http' => array( 'method' => 'POST','header'=>'content-type: application/x-www-form-urlencoded','content' => $post_string) ); $stream_context = stream_context_create($context); $response = file_get_contents($url,false,$stream_context); $xml=simplexml_load_string($response); var_dump($xml); ?> 代码中,模拟了POST提交,并且获得了返回的string,再把string转成了SimpleXMLElement对象。而且数据库中数据也已经写入。 C#版本访问: C#也可以通过代码调用PHP写的REST风格的Webservice。代码如下: class Program { static void Main(string[] args) { string[] paramName = { "id" }; string[] paramVal = { "1001,1004" }; var p = HttpGet("http://localhost:8080/b.php",paramName,paramVal); Console.WriteLine(p); Console.WriteLine("-------------------------------"); string[] paramName1 = { "id","username","sex","age" }; string[] paramVal1 = { "1030","tom","男","23" }; var p1 = HttpPost("http://localhost:8080/b.php",paramName1,paramVal1); Console.WriteLine(p1); } static string HttpGet(string url,string[] paramName,string[] paramVal) { StringBuilder paramz = new StringBuilder(); for (int i = 0; i < paramName.Length; i++) { paramz.Append(paramName[i]); paramz.Append("="); paramz.Append(HttpUtility.UrlEncode(paramVal[i])); paramz.Append("&"); } url += "?" + paramz.ToString(); HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; string result = null; using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse) { StreamReader reader = new StreamReader(resp.GetResponseStream()); result = reader.ReadToEnd(); } return result; } static string HttpPost(string url,string[] paramVal) { HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest; req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; // Build a string with all the params,properly encoded. // We assume that the arrays paramName and paramVal are // of equal length: StringBuilder paramz = new StringBuilder(); for (int i = 0; i < paramName.Length; i++) { paramz.Append(paramName[i]); paramz.Append("="); paramz.Append(HttpUtility.UrlEncode(paramVal[i])); paramz.Append("&"); } // Encode the parameters as form data: byte[] formData = UTF8Encoding.UTF8.GetBytes(paramz.ToString()); req.ContentLength = formData.Length; // Send the request: using (Stream post = req.GetRequestStream()) { post.Write(formData,formData.Length); } // Pick up the response: string result = null; using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse) { StreamReader reader = new StreamReader(resp.GetResponseStream()); result = reader.ReadToEnd(); } return result; } } 参考文档: http://geeknizer.com/rest-vs-soap-using-http-choosing-the-right-webservice-protocol/ http://msdn.microsoft.com/zh-cn/magazine/dd942839.aspx http://www.gen-x-design.com/archives/create-a-rest-api-with-php/ http://rest.elkstein.org/2008/02/what-is-rest.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |