心有多大舞臺(tái)便有多大

          Embrace changes, pursue excellence, share niceness.

          [ZZ]理解form的get和post

          (轉(zhuǎn)載自http://askjava.blog.sohu.com/76540166.html)

          HTML中,form元素

          1. get和post的定義

          W3CHTML 4.01 specification說,form元素的method屬性用來指定發(fā)送form的HTTP方法。

          • 使用get時(shí),form的數(shù)據(jù)集(形如control-name=current-value的鍵值對(duì))被附加到form元素的action屬性所指定的URI后面;
          • 使用post時(shí),form的數(shù)據(jù)集(形如control-name=current-value的鍵值對(duì))被包裝在請(qǐng)求的body中并被發(fā)送。

          這可以簡單地理解為,get僅僅是拼接一個(gè)URI,然后直接向服務(wù)器請(qǐng)求數(shù)據(jù)(需要提交給服務(wù)器的數(shù)據(jù)集包含在URI中)。比如:

          <form method="get" action="FormGet.aspx">
              
          <input type="text" name="ProductID" value="1" />
              
          <input type="submit" value="Get" />
          </form>

          這個(gè)form在提交的時(shí)候,會(huì)產(chǎn)生這樣能夠一個(gè)get請(qǐng)求:FormGet.aspx?ProductID=1。

          而post會(huì)把form的數(shù)據(jù)集,即ProductID=1這個(gè)鍵值對(duì)包裝在請(qǐng)求的body中,發(fā)送給服務(wù)器,然后向服務(wù)器請(qǐng)求數(shù)據(jù)。對(duì)于:

          <form method="post" action="FormPost.aspx">
              
          <input type="text" name="ProductID" value="1" />
              
          <input type="submit" value="Get" />
          </form>

          這樣一個(gè)form在提交時(shí),我們將看到一個(gè)干凈的URI:FormPost.aspx。因?yàn)閿?shù)據(jù)不是拼接在URI中。

          2. get和post的區(qū)別

          2.1 安全性

          如果用get提交一個(gè)驗(yàn)證用戶名和密碼的form,一般認(rèn)為是不安全的。因?yàn)橛脩裘兔艽a將出現(xiàn)在URL上,進(jìn)而出現(xiàn)在瀏覽器的歷史記錄中。顯然,在對(duì)安全性有要求的情況下,應(yīng)該使用post。

          2.2 編碼

          HTML 4.01 specification指出,get只能向服務(wù)器發(fā)送ASCII字符,而post則可以發(fā)送整個(gè)ISO10646中的字符(如果同時(shí)指定

          注意get和post對(duì)應(yīng)的enctype屬性有區(qū)別。enctype有兩個(gè)值,默認(rèn)值為application/x-www-form-urlencoded,而另一個(gè)值multipart/form-data只能用于post。

          2.3 提交的數(shù)據(jù)的長度

          HTTP specification并沒有對(duì)URL長度進(jìn)行限制,但是IE將請(qǐng)求的URL長度限制為2083個(gè)字符,從而限制了get提交的數(shù)據(jù)長度。測(cè)試表明如果URL超出這個(gè)限制,提交form時(shí)IE不會(huì)有任何響應(yīng)。其它瀏覽器則沒有URL的長度限制,因此其它瀏覽器能通過get提交的數(shù)據(jù)長度僅受限于服務(wù)器的設(shè)置。

          而對(duì)于post,因?yàn)樘峤坏臄?shù)據(jù)不在url中,所以通常可以簡單地認(rèn)為數(shù)據(jù)長度限制僅受限于服務(wù)器的設(shè)置。

          2.4 緩存

          由于一個(gè)get得到的結(jié)果直接對(duì)應(yīng)到一個(gè)URI,所以get的結(jié)果頁面有可能被瀏覽器緩存。而post一般則不能,參考5。

          2.5 引用和SEO

          出于和上面相同的原因,我們可以用一個(gè)URI引用一個(gè)get的結(jié)果頁面,而post的結(jié)果則不能,所以必然不能被搜索引擎搜到。

          3. 服務(wù)端的處理

          在服務(wù)端的ASP.NET程序中,對(duì)于get,我們用Request.QueryString[control-name]來取得對(duì)應(yīng)的=current-value;對(duì)于post,我們用Request.Form[control-name]。

          我們也可以籠統(tǒng)地使用Request[control-name]。但這樣做的效率不如前者。我們可以用下面的程序比較Request.QueryString和Request的效率:

          <%@ Page Language="C#" %>

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

          <script runat="server">
              protected 
          void Page_PreInit(object sender, EventArgs e)
              {
                  
          if(Request["InputString"!= null)
                  {
                      
          int count = 1000000;
                      DateTime start;
                      DateTime end;
                      string value 
          = "";
                      start 
          = DateTime.Now;
                      
          for(int i = 0;i < count;i++)
                      {
                          value 
          = Request.QueryString["InputString"];
                      }
                      end 
          = DateTime.Now;
                      
          double requestGet = (end - start).TotalSeconds;
                      start 
          = DateTime.Now;
                      
          for(int i = 0;i < count;i++)
                      {
                          value 
          = Request["InputString"];
                      }
                      end 
          = DateTime.Now;
                      
          double request = (end - start).TotalSeconds;
                      compare.InnerHtml 
          = requestGet.ToString() + " / " + request.ToString() + " = " + (requestGet / request).ToString();
                      get.InnerHtml 
          = value;
                  }
              }
          </script>

          <html xmlns="http://www.w3.org/1999/xhtml">
              
          <head>
                  
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                  
          <title>Request.QueryString / Request</title>
              
          </head>
              
          <body>
                  
          <form method="get" action="FormGet.aspx">
                      
          <div>
                          
          <input type="text" name="InputString" /><input type="submit" value="Post" /><br />
                          Get: 
          <span runat="server" id="get"></span><br />
                          Request.QueryString / Request: 
          <span runat="server" id="compare"></span>
                      
          </div>
                  
          </form>
              
          </body>
          </html>

          同樣的辦法我們可以比較Request.Form和Request。

          最后得到的結(jié)果(Request.QueryString[control-name] / Request[control-name]和Request.Form[control-name] / Request[control-name])大多數(shù)時(shí)候是小于1的。因此,我們因該盡量用Request.QueryString或Request.Form來代替Request。

          4. 正確地使用get和post

          W3C的官方建議是:當(dāng)且僅當(dāng)form是冪等(idempotent)的時(shí)候,使用get。冪等是一個(gè)數(shù)學(xué)上的術(shù)語,其定義是:對(duì)于一個(gè)函數(shù)f : D -> D,如果D中的所有x滿足f (f x) = f x,那么這個(gè)函數(shù)是冪等的。HTTP specification(比如RFC 2616)中,將冪等解釋為:多次相同請(qǐng)求產(chǎn)生的副作用,和一次請(qǐng)求的副作用相同。

          打個(gè)比方,如果你提交一個(gè)form會(huì)從Google上查詢一個(gè)關(guān)鍵詞,那么我們可以認(rèn)為這個(gè)form是冪等的,因?yàn)?次提交和10次提交的副作用是差不多的(10次查詢可能會(huì)多消耗一些電能);如果你提交一個(gè)form是訂購一個(gè)終極大黃蜂(Utimate bumblebee),那么這就不是冪等的:要是你不小心多提交了1次form的話,你可能會(huì)被老婆亂罵,你不小心又提交了10次的話,你可能就破產(chǎn)了——一次提交和多次提交的副作用明顯不同,所以這不是冪等的。

          所以,一般來說,如果提交這個(gè)請(qǐng)求純粹只是從服務(wù)端獲取數(shù)據(jù)而不進(jìn)行其他操作,并且多次提交不會(huì)有明顯的副作用,應(yīng)該使用get。比如:

          如果提交這個(gè)請(qǐng)求會(huì)產(chǎn)生其它操作和影響,就應(yīng)該使用post。比如:

          • 修改服務(wù)器上數(shù)據(jù)庫中的數(shù)據(jù);
          • 發(fā)送一封郵件;
          • 刪除一個(gè)文件。

          另一個(gè)要考慮的因素是安全性。見2.1。

          5. 瀏覽器差異

          6. 參考

          posted on 2010-03-15 11:20 pony 閱讀(517) 評(píng)論(0)  編輯  收藏 所屬分類: 網(wǎng)站

          主站蜘蛛池模板: 黄浦区| 勃利县| 德钦县| 绍兴市| 太白县| 元阳县| 浦东新区| 奉节县| 银川市| 阿勒泰市| 新疆| 怀化市| 仙游县| 吉安市| 绥滨县| 阿合奇县| 竹溪县| 沂源县| 宣武区| 忻城县| 黑龙江省| 车致| 汤阴县| 图木舒克市| 长垣县| 马山县| 栾城县| 宝应县| 黎平县| 图木舒克市| 南雄市| 石泉县| 襄汾县| 新巴尔虎右旗| 林周县| 洪洞县| 谢通门县| 喀喇沁旗| 繁峙县| 承德县| 赫章县|