官术网_书友最值得收藏!

2.3 服務器請求

Ajax與傳統Web應用的第一個區別在于發送請求的方式不同:傳統Web應用采用表單或請求某個資源的方式發送請求;而Ajax則采用異步方式在后臺發送請求。下面詳細介紹Ajax發送請求的各種細節。

2.3.1 發送GET請求

通常情況下,GET請求用于從服務器上獲取數據,POST請求用于向服務器發送數據。GET請求將所有請求參數轉換成一個查詢字符串,并將該字符串添加到請求的URL之后,因而可在請求的URL后看到請求參數名和請求參數值。如果將某個表單的action屬性設置為GET,則請求會將表單中各字段的名和值轉換成字符串,并附加到URL之后。

GET請求傳送的數據量較小,一般不能大于2KB。POST傳送的數據量較大,通常認為POST請求參數的大小不受限制,但往往取決于服務器的限制。通常來說,POST請求的數據量總比GET請求的數據量大。

POST請求則通過HTTP POST機制,將請求的參數以及對應的值放在HTML Header中傳輸,用戶看不到明碼的請求參數值。

當使用Ajax發送異步請求時,建議使用POST請求,而不是GET請求。發送GET方式的請求應注意如下兩點。

(1)通過open()方法打開與服務器的連接時,設置使用GET方式。

(2)如果需要發送請求參數,應將請求參數轉成查詢字符串,并追加到請求URL之后。

下面的示例應用是個級聯菜單的示范,但這個級聯菜單與傳統級聯菜單是有所區別的,區別在于:Ajax的級聯菜單無須一次將所有的菜單信息加載到頁面中,而是每次改變父菜單時頁面會異步地向服務器發送請求,然后再根據服務器響應來動態加載子菜單。

采用GET請求將父菜單的ID作為參數發送,下面是服務器的響應頁面,此處并未讓服務器響應頁面從數據庫讀取——后臺數據庫訪問可仿照傳統Java EE架構。服務器響應頁面的代碼如下:

上面的代碼作為服務器響應非常簡單:先讀取請求參數,當請求id為1時,返回三個中國城市;當請求id為2時,返回三個美國城市;當請求id為3時,返回三個日本城市。客戶端的HTML頁面則通過XMLHttpRequest向服務器發送請求,并將請求動態顯示在HTML文檔中。下面是對應的HTML頁面的代碼。

通過上面的代碼,發送GET方式的Ajax請求,并動態加載服務器響應。

運行效果演示

在瀏覽器中瀏覽該頁面,并改變第一個下拉列表框的選中項,將可以看到如圖2-7所示的效果。

圖2-7 發送GET異步請求

2.3.2 發送POST請求

如上所述,POST請求的適應性更廣,可使用更大的請求參數,而且POST請求的請求參數通常不能直接看到,因此,在使用Ajax發送請求時,盡量采用POST方式而不是GET方式發送請求。發送POST請求通常需要如下三個步驟:

(1)使用open()方法打開連接時,指定使用POST方式發送請求。

(2)設置正確的請求頭,POST請求通常應設置Content-Type請求頭。

(3)發送請求,把請求參數轉為查詢字符串,將該字符串作為send()方法的參數。

對于上面的應用,同樣可以采用POST方式來發送請求,只需更改一個請求的發送方法,如下所示。

其余的部分則無須改變,應用的執行效果與采用GET方式發送請求的效果完全一樣。事實上,即使采用POST方式發送請求,一樣可以將請求參數附加在請求的URL之后。代碼如下:

2.3.3 發送請求時的編碼問題

在開發過程中,不可避免地需要發送包含非西歐字符的請求參數,而這些請求參數在傳輸過程中的編碼將直接影響服務器的處理。如果發送的請求里不包含非西歐字符,將不會有任何問題;但一旦包含了非西歐字符的請求參數,則可能出現異常。

下面的簡單應用通過文本輸入框獲取用戶輸入,然后分別使用兩種方式發送請求,服務器負責獲取用戶請求,并將請求參數在控制臺中輸出。首先看服務器程序。

上面的服務器響應頁面沒有生成任何響應,而只是打印了value請求參數的值。本應用專門用于分析客戶端請求參數??蛻舳隧撁嫣峁┝藘煞N方法來發送請求,分別通過GET方式和POST方式發送請求。下面是客戶端的頁面代碼。

上面的頁面提供了兩個按鈕,這兩個按鈕分別用于發送GET請求和POST請求,單擊兩個按鈕時分別觸發postSend()方法和getSend()方法,兩個請求都將使用文本頁面中的文本框的值作為請求參數。圖2-8是發送請求的頁面。

在圖2-8所示頁面中輸入“Ajax程序設計”字符串,分別采用GET方法和POST方法發送請求,在Tomcat的控制臺中可看到如圖2-9所示的頁面。

圖2-8 發送請求的頁面

圖2-9 中文請求參數

從圖2-9中可以看出,當使用GET方式發送請求時,請求參數變成了亂碼。編碼問題也是Ajax應用必須處理的問題,對于POST請求很好處理,異步POST請求默認采用UTF-8字符集來編碼請求參數,因此只需要調用HttpServletRequest的setCharacterEncoding("UTF-8")即可解決亂碼問題。服務器采用如下代碼即可獲得正確的POST請求參數。

再次在如圖2-8所示的文本框中輸入中文字符,使用POST方法發送請求,可以看到Tomcat控制臺中獲得了正確的參數值;如果使用GET方法發送請求,請求參數值依然是亂碼。

前面已經介紹過,GET請求將請求參數和對應的值附加在請求的URL之后。對于中文的請求參數值,將不再以中文的方式傳遞,而是轉碼成URL的格式。因此,可將服務器頁面修改成如下形式,對GET請求和POST請求分開處理。

上面的代碼先獲取value請求參數,再將該參數按ISO-8859-1字符集編碼成字節數組,然后按UTF-8字符集將該字節數組解碼成字符串。再次在圖2-8所示的頁面中的文本框中輸入“Ajax程序設計”,單擊“GET發送”按鈕,可看到控制臺中出現如圖2-10所示的輸出。

圖2-10 編碼分析的Tomcat控制臺

問題是不是得到了解決呢?如果我們將瀏覽器更換成Internet Explorer,在文本框中輸入“Ajax程序設計”,然后單擊“GET發送”按鈕,將看到Tomcat控制臺中再次出現亂碼。

相同的代碼,使用不同的瀏覽器將產生不同的結果。由此可見,使用GET方式發送請求參數所用的字符集和客戶端瀏覽器有關,不同瀏覽器在發送GET請求參數時使用了不同的字符集,而服務器頁面進行編碼時始終采用new String(tmp.getBytes("ISO-8859-1"),"UTF-8");進行解碼,顯然這個UTF-8字符集需要根據客戶端瀏覽器進行改變。

假如將解碼請求參數的代碼改為new String(tmp.getBytes("ISO-8859-1"),"GBK");,則在使用Internet Explorer發送非西歐字符請求參數時,可以在Tomcat控制臺中看到正常字符;但使用Firefox發送非西歐字符請求參數時將看到亂碼。

解決這個問題的唯一做法是在發送請求的HMTL頁面中采用固定的URL Encode,手動編碼包含非西歐字符的請求參數,這樣就可以控制請求,即在客戶端的HTML頁面采用如下Java代碼。

然后,再在服務器端采用如下代碼。

這個過程相當煩瑣,而且需要在HTML頁面中使用Java API,相當不合時宜。因此通常建議發送POST請求,盡量少使用GET請求,理由如下:

(1)處理GET請求的請求參數比較繁瑣。

(2)當請求參數包含的數據太多時,GET請求可能丟失請求參數。

(3)當兩次GET請求的請求參數相同時,Internet Explorer將直接使用服務器上次的緩存,根本不會重新發送請求,這對于自動刷新頁面相當不利。

主站蜘蛛池模板: 集贤县| 永康市| 诸城市| 仙桃市| 于都县| 乐东| 荆门市| 永昌县| 安徽省| 夏河县| 五常市| 大埔县| 紫阳县| 新建县| 浠水县| 仁寿县| 黔西| 海淀区| 南安市| 昌都县| 贺兰县| 武城县| 德阳市| 韶山市| 洪江市| 赫章县| 轮台县| 辉南县| 高阳县| 新晃| 康马县| 长乐市| 门源| 临洮县| 夹江县| 清新县| 永年县| 盐池县| 铅山县| 隆化县| 青川县|