概念:
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。
<?phpswitch($_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\"?>\r\n" ."<data>\r\n" .$string ."</data>"; header("Content-type:application/xml"); print($string); }function add($id,$username,$sex,$age){ $users=getCsvFile("example.csv"); $string="$id,$username,$sex,$age"; WriteLinetxt($string,"example.csv"); $string="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" ."<return>\r\n" ." <status>0</status>\r\n" ."</return>\r\n"; 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."\r\n",FILE_APPEND);}?>
代碼說明:
上述代碼,根據請求的方式是POST還是GET來區分,如果是GET的話,則需帶上查詢的ID。服務會返回一個Content-type為application/xml的一份xm文檔。如果是POST的話,則會把相應的POST進來的值寫入到資料庫。
本例中,資料庫只是簡單的採用CSV檔案,即用逗號分割資料的文字檔。資料檔案如下:
650) this.width=650;" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px" title="CBD247FF7AF9473193DC06EB24DBCCC8" border="0" alt="CBD247FF7AF9473193DC06EB24DBCCC8" src="http://www.bkjia.com/uploads/allimg/131228/1124314622-0.jpg" height="169" />
由於REST風格的web服務可以通過瀏覽器驗證,因此可以輸入url地址測試。本例中沒有採用url重寫,如果使用url重寫的話,服務地址會更友好。
650) this.width=650;" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px" title="D87BE31CF24D416BA901BA11EF15A2A6" border="0" alt="D87BE31CF24D416BA901BA11EF15A2A6" src="http://www.bkjia.com/uploads/allimg/131228/1124312N4-1.jpg" height="431" />
服務部署好之後,就可以調用了。在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);?>
650) this.width=650;" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px" title="74A2BDE9531F4A879C284A805D575126" border="0" alt="74A2BDE9531F4A879C284A805D575126" src="http://www.bkjia.com/uploads/allimg/131228/1124313A5-2.jpg" height="536" />
通過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對象。而且資料庫中資料也已經寫入。
650) this.width=650;" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px" title="5ABB6024DDF8491FAE0A051F8E524C15" border="0" alt="5ABB6024DDF8491FAE0A051F8E524C15" src="http://www.bkjia.com/uploads/allimg/131228/1124315293-3.jpg" height="127" />
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[] paramName, 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, 0, 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; } }
650) this.width=650;" style="border-bottom:0px;border-left:0px;border-top:0px;border-right:0px" title="F8FED7F3BB7C4808801FE1FA3AC1C220" border="0" alt="F8FED7F3BB7C4808801FE1FA3AC1C220" src="http://www.bkjia.com/uploads/allimg/131228/1124314302-4.jpg" height="335" />
參考文檔:
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