最近一個項目,客戶端使用用jQuery編寫ajax請求,服務端采用struts2框架。js發送請求和action處理請求過程中,遇到一個問題。剛開始覺得問題很詭異,仔細定位很久之后才發現問題,雖然問題解決了, 但更深層次的原因還不清楚,歡迎大牛們指導。
1.問題現象
- 客戶端問題
通過IE9下的開發人員工具F12發現,瀏覽器的確是發送了post請求,但是該請求“結果”欄顯示的是“已終止”,“發起程序”值 是“已掛起”。請求頭、請求體、響應頭、響應體都是空的。也就說瀏覽器發送了1個異常的請求。
- 服務端問題
Struts2的action能夠接受到post的請求,但是獲取不到請求參數的值。
2.相關JS代碼
- function sendMessage()
- {
- $.post("indvAction!sendShortMsg.action", {
- "configType" : "1"
- });
- }
- //彈出確認對話框
- Nf.promptConfirm({
- message :”operation success”,
- width : 300,
- height : 150,
- handler : function(btn)
- {
- if (btn == "ok")
- {
- //向服務器發送ajax請求
- sendMessage()
- //關閉當前頁面
- NfLayout.closeTab();
- }
- }
- });
function sendMessage() { $.post("indvAction!sendShortMsg.action", { "configType" : "1" }); } //彈出確認對話框 Nf.promptConfirm({ message :”operation success”, width : 300, height : 150, handler : function(btn) { if (btn == "ok") { //向服務器發送ajax請求 sendMessage() //關閉當前頁面 NfLayout.closeTab(); } } });
3.定位過程
剛開始使用F12沒有得到與定位問題有關的信息。后面使用httpWatch或burp suite進行http抓包,查看原始的http請求和響應報文。結果發現了問題。
1、瀏覽器發出的請求報文中,的確沒有傳遞configType字段的值。請求報文如下:
- POST /mobile/jsp/indvconfig/indvAction!sendShortMsg.action HTTP/1.1
- x-requested-with: XMLHttpRequest
- Accept-Language: zh-CN,en;q=0.5
- Referer: https://*.*.*.*:17243/mobile/jsp/indvconfig/indv_config.jsp
- Accept: */*
- Content-Type: application/x-www-form-urlencoded
- Accept-Encoding: gzip, deflate
- User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
- Host: 11.12.213.87:17243
- Content-Length: 0
- Connection: Keep-Alive
- Cache-Control: no-cache
- Cookie: JSESSIONID=62C9FF9CBC97731B120ABAC297C4E4C5
POST /mobile/jsp/indvconfig/indvAction!sendShortMsg.action HTTP/1.1 x-requested-with: XMLHttpRequest Accept-Language: zh-CN,en;q=0.5 Referer: https://*.*.*.*:17243/mobile/jsp/indvconfig/indv_config.jsp Accept: */* Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) Host: 11.12.213.87:17243 Content-Length: 0 Connection: Keep-Alive Cache-Control: no-cache Cookie: JSESSIONID=62C9FF9CBC97731B120ABAC297C4E4C5
2、瀏覽器的確收到了服務器的響應報文。
- HTTP/1.1 200 OK
- Server: Apache-Coyote/1.1
- Content-Type: text/plain;charset=UTF-8
- Vary: Accept-Encoding
- Date: Fri, 22 Nov 2013 01:34:31 GMT
- Content-Length: 6
- this is my response!
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/plain;charset=UTF-8 Vary: Accept-Encoding Date: Fri, 22 Nov 2013 01:34:31 GMT Content-Length: 6 this is my response!其實一切都很正常了,瀏覽器確實發送了HTTP請求,只不過是沒有攜帶請求參數值,只不過是被IE9的展示方式欺騙了,所以剛開始定位很久都沒有頭緒。現在產生了如下問題:為什么瀏覽器發送了ajax請求,但是沒有攜帶請求參數?為什么IE9顯示請求是“已掛起”、“已終止”?
4.問題解決
去掉NfLayout.closeTab();這行代碼就可以解決問題了。這是因為jquery的POST請求是異步的,當post請求還沒有准備好數據的時候,這個時候執行了NfLayout.closeTab();當前頁面關閉,導致了瀏覽器終止了http請求。這樣的話就,相當於是請求被異常終止,於是IE9顯示請求“已掛起”、“已終止”。具體深層次的原因不清楚,下面是個人一些猜想和解釋:
1、 JS代碼只有加載才會被執行,而觸發js加載的正是html/jsp頁面的顯示。所以,我覺得Html/jsp就是js的執行環境。如果js還沒有執行完,頁面關閉的話,后續js代不會再執行。測試代碼如下:
- <head>
- <script type='text/javascript'>
- function test()
- {
- alert(1111);
- window.opener = "";
- window.open("","_self");
- window.close();
- alert("我不會在執行了,因為頁面已經關閉。");
- //setTimeout('callBack( )', 3000)
- }
- </script>
- </head>
- <body>
- <input id="button_-12你" type="button" value="testRight" onclick="test();">
- </body>
<head> <script type='text/javascript'> function test() { alert(1111); window.opener = ""; window.open("","_self"); window.close(); alert("我不會在執行了,因為頁面已經關閉。"); //setTimeout('callBack( )', 3000) } </script> </head> <body> <input id="button_-12你" type="button" value="testRight" onclick="test();"> </body>個人感覺,可能是jquery拼post的請求體,會相對比較耗時,還沒有執行完畢。此時頁面關閉,JS終止了執行,瀏覽器發送了1個不完全的HTTP請求(沒有附上請求體)。 這是個人的猜測,大家有自己見解的,歡迎指教。基於這個結論,我們將POST請求,改成Get請求,雖然IE9顯示的還是請求終止,但是服務端能夠收到請求的參數值了。