前言 最近開發了幾個項目,用到了web api,也通過項目加深了對web api的理解。本文試圖從內部原理講解web api的本質。透過重重迷霧,看清本質,就能更好的把握和利用好web api。
1 Web API 的本質
1.1 交互說明
Web API 是基於http傳輸協議的函數調用。http是應用最廣泛的傳輸協議,web服務端就實現了http服務器。由於web的流行,也帶動了web服務器的完善和優化。web服務器的功能也不僅限於傳輸html文本,任何數據都可以通過文本傳輸(其實,圖片,視頻也可以通過變通的方式實現傳輸)。函數的調用就是發送數據和接收數據的過程;既然http也能發送和接收數據,當然也可以通過http實現函數調用,這就是web api。
http是傳輸協議,並不解釋傳輸的內容。http協議同時也定義了一些標准的術語,方便客戶端和服務端交互。一個典型的http發送和響應數據如下:
---->request
Request URL: https://www.baidu.com/ Request Method: GET Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: keep-alive Cookie: BAIDUID=43E2CBB543131B011BC1861E7CDD83DB:FG=1 Host: www.baidu.com Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 body data
<----reponse
Status Code: 200 OK
Remote Address: 111.13.100.91:443
Referrer Policy: no-referrer-when-downgrade
Bdpagetype: 1
Bdqid: 0xecff8dba0009a0bc
Cache-Control: private
Connection: Keep-Alive
Content-Type: text/html
Cxy_all: baidu+5bd9cbe0adf9080de3f7682cf8f45af1
Date: Fri, 19 Apr 2019 13:44:36 GMT
Expires: Fri, 19 Apr 2019 13:44:05 GMT
Server: BWS/1.1
Set-Cookie: BIDUPSID=43E2CBB543131B011BC1861E7CDD83DB; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1555681476; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
body data
http分為包頭和包體,包頭包含一些關鍵字段,如Accept,Cookie,這些是http的保留字。你也可以通過包頭傳輸數據,只要不使用保留字就行。如:
myguid: 6F9619FF-8B86-D011-B42D-00C04FC964FF
通常包頭傳輸一組函數公用的數據,比如有10個函數,這些函數都用到guid,可以把guid放入包頭。
1.2 包體數據說明
http請求(request)數據:
a)對於瀏覽器的表單,包體數據格式如下:
key1=value1&key2=value2
就是key,value對,通過&號分割。key,value也可以是漢字,會做轉義處理。這些細節不需要我們處理。只需要知道key、value可以是任何字符就行。
b)json和其他數據格式
對於web api,包體數據可以是json格式。當然不限於json,可以是任意形式的數據,只要雙方對處理協議達成一致就行。
{ "sites": [ { "name":"菜鳥教程" , "url":"www.runoob.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"微博" , "url":"www.weibo.com" } ] }
傳輸復雜的數據建議使用json,json函數可以把復雜的類變量序列化;對方反序列化,就可以得到一個類變量。這樣,遠程函數調用與本地調用區別就很小;僅僅多一層json序列化。
2 asp.net 對web API的實現
常言:巧婦難為無米之炊。對於web api,http承載的數據就是米,asp.net框架就是巧婦。web api的本質就是數據的發送和接收,asp.net 能做的的就是方便你的接收和返回。asp.net這里是好心幫程序員減輕負擔,但這種好心也有副作用:很難探究web api的本質,遇到問題難以從本質上去分析解決。
2.1 數據如何變成函數參數
我們一般不處理http原始數據,這些數據一般會映射為函數參數。這種映射關系多種多樣,見下圖:
asp.net做這種映射處理就是為了減輕開發人員的負擔,但是開發人員必須了解這些映射關系。不同框架處理這種映射邏輯也是不一樣的,其實,開發人員可以定制自己的映射邏輯;但是好像沒必要這樣做,直接處理http數據,就是從asp.net request變量抽取http數據再處理,也增加不了多少工作量;這樣反而使開發人員對底層數據了解更加透徹。
2.2 asp.net 客戶端調用舉例
使用類WebClient做為示例:
//客戶端調用 void clientPost() { using (var client = new System.Net.WebClient()) { var postParam = new NameValueCollection(); //傳遞參數 postParam.Add("code", "123"); postParam.Add("name", "tom); //http body部分就變為 code=123&name=tom var responsebytes = client.UploadValues(uri, postParam); string strResult = System.Text.Encoding.UTF8.GetString(responsebytes); } } //服務端: string ServerDeal(string code, string name) { //http body數據部分映射為參數:code為123,name為tom return "ok"; }
NameValueCollection類將數據組成key、value對,並處理字符轉義。通過上面的代碼可以看出,web api調用其實很簡單,框架幫我們做了數據映射,字符轉義等常規操作,讓我從繁雜的瑣事中脫身,專注處理業務邏輯。
后記:對事物的了解要抓住本質,只要了解了本質,就一通百通。web api原理並不繁雜,但是由於上層的封裝,使我們很難了解到底層處理原理,導致很難抓住事物的本質。本文通過自身的領悟,試圖剖析其本質,希望對讀者有所裨益!