工作兩年多了,我會經常嘗試給公司小伙伴兒們解決一些問題,幾個月下來我發現初入公司的小朋友最愛問的問題就三個
1. 我想前台調用后台的XXX方法怎么弄啊?
2. 我想后台調用前台的XXX JavaScript方法怎么弄啊?
3. 怎么用JavaScript找到/創建/修改XXX這個服務器端控件啊?
每次我會跟小朋友分析一下為什么會有如此荒誕不經的想法,然后說原來你做XXX啊,那你應該這樣,可發現這種模式太失敗了,因為隔幾天我又會聽到小朋友還是有類似的疑惑。
我決定以后再有誰問這個問題,我就讓誰給我講講HTTP協議,幾次過后效果非凡啊,看看這兩個問題和HTTP協議有什么關系吧
HTTP協議
HTTP協議即超文本傳輸協議 (HTTP-Hypertext transfer protocol) 是分布式,協作式,超媒體系統應用之間的通信協議。是萬維網(world wide web)交換信息的基礎。是一種詳細規定了瀏覽器和萬維網服務器之間互相通信的規則,通過因特網傳送萬維網文檔的數據傳送協議。
這是從百度上抄來的定義,感覺味同嚼蠟,反正我要是問人什么是HTTP,要是這么回答我,我肯定得急,所以還有
HTTP協議允許將超文本標記語言 (HTML) 文檔從 Web 服務器傳送到 Web 瀏覽器。HTML 是一種用於創建文檔的標記語言,這些文檔包含到相關信息的鏈接。您可以單擊一個鏈接來訪問其它文檔、圖像或多媒體對象,並獲得關於鏈接項的附加信息。
還是不明白,看看HTTP的請求-響應模型就清楚了
HTTP協議規定的交互很簡單,客戶端向服務器發送包含着信息的請求(絕逼不是整個HTML頁面),服務器接到請求后,根據請求信息生成響應(什么響應都可能,多數是HTML頁面文本),然后把響應發給瀏覽器(如果響應是HTML頁面的話,瀏覽器就加載這個新頁面了)
HTTP的請求-響應模型非常簡單,可是初入門的時候我們會誤會它很深
瀏覽器到底向服務器請求什么了
請求不是整個HTML頁面,小朋友們在ASP.NET的codeBehind中經常試圖去Request對象中找頁面的某個DIV,認為請求就是整個HTML頁面,理由也很充分,我能夠找到服務器端控件,怎么就找不到HTML控件呢。訪問百度首頁一下看看瀏覽器究竟請求了什么
當我們在瀏覽器地址欄輸入uri回車或者頁面form提交,瀏覽器會把請求打成包,HTTP請求包(GET/POST等請求方法)由三個部分構成,
<request-line>
<headers>
<blank line>
[<request-body>]
request-line:俗稱請求行,類似於這樣 Get / HTTP /1.0,用來說明請求類型、要訪問的資源路徑(/ 表示跟路徑)以及使用的HTTP版本。
headers: 也就是我們常說的HTTP Headers,訪問百度首頁的時候是一個這樣的東東
需要注意的是heasers中包括了該域下的cookie
blank line:這就是一個空行,還是必須的
request-body:這個在post請求時有用,是頁面表單元素的name和value,也就是在Resquest.Forms中能取到的內容,在百度上搜索得到,request body是這樣的
是的,HTTP 請求包中就這些內容,沒有什么div啊,什么服務器端控件啊什么的了
為什么能在codeBehind中操作服務器端控件,頁面上卻不能用JavaScript來做
簡單的說服務器端控件是服務器的,服務器並沒有把這個給客戶端,給客戶端的只是服務器端控件render的html文本,所以服務器端找到服務器端控件(你看人家都叫服務器端控件了),客戶端找不到。看起來很高端深奧,實際很簡單,看看服務器交給瀏覽器的是什么,和Request格式類似,Response格式如下
<status-line>
<headers>
<blank line>
[<response-body>]
status-line:表示請求的狀態碼,也就是我們常見的200、301、404、500神馬的
headers:一些響應的數據,還是上面例子,在百度上搜索得到,response headers是這樣的
content-type是不是很熟悉?值得注意的是response headers中同樣包含cookie
blank-line:仍舊是不可或缺的空白行
response-body:響應內容,訪問百度首頁response body 大概這樣,其實也就是百度首頁的HTML代碼
也就是說,也就是說response body在一般情況下就是得到的就請求頁面的HTML,瀏覽器接收到response后會按照response body重新加載渲染頁面內容。寫過Web Control的同學肯定知道,服務器端控件render成什么了
看一個最簡單的頁面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FrontBehind.Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button ID="btnServer" runat="server" Text="Server" OnClick="btnServer_Click" /> </div> </form> </body> </html>
頁面上只有一個服務器端的控件(不要太計較),看看生成的頁面內容
服務器端的控件Button經過處理后交給客戶端時已經變成了一個 submit類型的input,頁面上通過JavaScript當然找不到這個服務器端控件了,有興趣同學可以看看Web Control的render control方法,所有的Web Control在Page render的時候都會調用此方法,將服務器端控件按照自己規則render成瀏覽器認識的HTML,然后放到Resoponse中。
瀏覽器從噢乖服務器得到的是全新的HTML文本(不考慮Ajax),沒有其它服務器控件神馬的。
在編碼的時候的頁面和瀏覽器拿到的頁面有什么關系
可能偶同學會對上面的理論有疑問,我們在編程的時候寫的頁面,上面有很多服務器端控件,和最終瀏覽器展示的頁面有什么關系?!這就需要我們講講動態網頁的前世今生。
最開始的時候頁面全都是靜態的HTML文本,瀏覽器做的事情就是告訴服務器我要哪個頁面,服務器傳給你這個頁面,就像張三家開了個磚窯,你需要了就會吼一嗓子,張三,給我塊磚!然后張三扔給你。
但是這樣好單調,有時候頁面內容相當有規律,但是頁面是靜態的就得准被很多頁面,也沒法做到和用戶交互,於是產生了ASP等服務器腳本語言,可以根據用戶參數或者預設條件來修改頁面部分內容,不再簡單返回瀏覽器靜態頁面文件內容,而是根據規則生成HTML文本,然后返回給瀏覽器。
后來面向對象的普及及模塊兒化編程等等思想的影響,有一些常用的規則,比如畫出個日歷啊我們可以寫成一個單獨的模塊兒,然后通過指令使其嵌在頁面內,用的時候寫一條指令就可以了,這就是ASP.NET 中例如Button等的Web Control,也就是服務器端控件。
如果服務器判斷出瀏覽器請求的是帶有服務器腳本的頁面的時候(一般根據拓展名或者Map關系判斷),就會交給固定類型腳本的“解釋器”去處理這些腳本,轉換成HTML語句,然后返回給客戶端。
所以瀏覽器呈現的頁面是我們根據開發時候定義的規則,動態生成的HTML文本加載渲染的結果
HTTP工作流程
- 一次HTTP操作稱為一個事務,其工作過程可分為四步:
首先客戶機與服務器需要建立連接。只要單擊某個超級鏈接,HTTP的工作開始。
建立連接后,客戶機發送一個請求給服務器,請求方式的格式為:統一資源標識符(URL)、協議版本號,后邊是MIME信息包括請求修飾符、客戶機信息和可能的內容。
服務器接到請求后,給予相應的響應信息,其格式為一個狀態行,包括信息的協議版本號、一個成功或錯誤的代碼,后邊是MIME信息包括服務器信息、實體信息和可能的內容。
客戶端接收服務器所返回的信息通過瀏覽器顯示在用戶的顯示屏上,然后客戶機與服務器斷開連接。
HTTP特點
通過上面的說明可以看出HTTP協議有幾個特征
1.HTTP協議永遠都是客戶端發起請求,服務器回送響應。這樣就限制了使用HTTP協議,無法實現在客戶端沒有發起請求的時候,服務器將消息推送給客戶端。必須是客戶端給服務器要,而不能服務器主動給客戶端。
2.HTTP協議是一個無狀態的協議,同一個客戶端的這次請求和上次請求是沒有對應關系。也就是說你連續兩次訪問百度,這兩次之間沒有什么關系(不考慮緩存),不會像你去親戚家串門,上次去了,這次就認識你了。要想讓它們有關系我們注意到request header和resonse header都有cookie,Session等客戶端狀態維護就是基於此實現的。
3.在請求時並不是頁面所有內容都被發往服務器
4.在客戶端就已經沒有什么服務器端控件、方法、屬性了,只有HTML文本
幾個問題
總而言之有一句需要注意:HTTP協議並不是瀏覽器把整個頁面發給服務器,然后讓服務器做少許改動傳回給瀏覽器,而是瀏覽器發送少量數據參數傳給服務器,服務器根據特定頁面規則和瀏覽器參數生成全新頁面傳回給瀏覽器,瀏覽器更新加載這個全新頁面(不考慮Ajax)。瀏覽器呈現的頁面和服務器之間並不能通過所謂調用來交互。
理論知識就這么多,下一篇中就要即使一下開頭提的三個問題了,修改羅列一下
1.服務器端如何影響客戶端元素與行為
2.客戶端如何”調用“服務器端方法
3.JavaScript如何操作服務器控件render的HTML,以實現交互
PS:如果還有同學對HTTP協議有疑惑,可以看看之前為了跟小伙兒伴們將HTTP而寫的一個課件