有運營同學反映,後台編輯的一個中文顯示名稱,前台亂碼了,於是乎~~
先看代碼是否get請求沒轉碼:
$.ajax({type: 'POST',url: '/admin/updatedisplayname}',data: {displayName:displayName},success: function(res){alert(1);},error: function() {alert(2);},dataType: 'json'})
這段代碼不管怎麼看,也沒有問題,post請求過去的,應該不會存在亂碼問題,自己測了下,修改回去了,沒亂碼(Firefox)
奇怪~
問了下,對方用的是Google,檢查他的瀏覽器編碼有沒特殊設定過,沒有,一切正常。
納悶,回來在Google測試下,暈死,果然重現,亂碼了,哈哈,那就好辦,查~
看看要求標頭資訊啥的,發現使用$.ajax請求的時候有一個值有問題
chrome:contentType: 'application/x-www-form-urlencoded'
ff:contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
難道是這個在作祟,如果乎~
$.ajax({type: 'POST',url: '/admin/updatedisplayname}',data: {displayName:displayName},contentType: 'application/x-www-form-urlencoded; charset=UTF-8',success: function(res){alert(1);},error: function() {alert(2);},dataType: 'json'})
加上參數測試,果然在Google下不亂碼了,問題解決。
莫不是有啥玄機,查看jquery手冊
contentTypeString
(預設: "application/x-www-form-urlencoded") 發送資訊至伺服器時內容編碼類別型。預設值適合大多數情況。如果你明確地傳遞了一個content-type給 $.ajax() 那麼他必定會發送給伺服器(即使沒有資料要發送)
為毛我在不傳入這個值的時候,Firefox會加上 charset=UTF-8呢?
看看jquery源碼:
ajaxSettings: {url: location.href,global: true,type: "GET",contentType: "application/x-www-form-urlencoded",processData: true,async: true,/*timeout: 0,data: null,username: null,password: null,traditional: false,*/// Create the request object; Microsoft failed to properly// implement the XMLHttpRequest in IE7 (can't request local files),// so we use the ActiveXObject when it is available// This function can be overriden by calling jQuery.ajaxSetupxhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?function() {return new window.XMLHttpRequest();} :function() {try {return new window.ActiveXObject("Microsoft.XMLHTTP");} catch(e) {}},accepts: {xml: "application/xml, text/xml",html: "text/html",script: "text/javascript, application/javascript",json: "application/json, text/javascript",text: "text/plain",_default: "*/*"}},
貌似問題已經找到,通知團隊成員,仔細檢查所有項目的$.ajax方法的使用,是否有傳遞中文參數,如果有就加上:
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
果然發現了幾個隱藏的bug,不過像這樣的直接使用$.ajax一般只有後台系統才用用到,而我們的後台系統是可以不相容google的,所以當時測試的時候可能沒測到。
不過,又有問題,有同學沒有加,但是測試是ok的,Google不亂碼,各種不淡定啊。。。。
再查~
首先想到檢查jquery版本,果然,這哥們是用jquery1.7.2,而我用的是1.4.2,查看1.7.2的源碼:
ajaxSettings: {url: ajaxLocation,isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),global: true,type: "GET",contentType: "application/x-www-form-urlencoded; charset=UTF-8",processData: true,async: true,/*timeout: 0,data: null,dataType: null,username: null,password: null,cache: null,traditional: false,headers: {},*/accepts: {xml: "application/xml, text/xml",html: "text/html",text: "text/plain",json: "application/json, text/javascript","*": allTypes},contents: {xml: /xml/,html: /html/,json: /json/},responseFields: {xml: "responseXML",text: "responseText"},// List of data converters// 1) key format is "source_type destination_type" (a single space in-between)// 2) the catchall symbol "*" can be used for source_typeconverters: {// Convert anything to text"* text": window.String,// Text to html (true = no transformation)"text html": true,// Evaluate text as a json expression"text json": jQuery.parseJSON,// Parse text as xml"text xml": jQuery.parseXML},// For options that shouldn't be deep extended:// you can add your own custom options here if// and when you create one that shouldn't be// deep extended (see ajaxExtend)flatOptions: {context: true,url: true}},
暈死,在1.7.2中居然加上了charset=UTF-8,
各種~~~~,再探~1.7源碼裡面也是沒有的
好吧,1.7.2裡面沒有這個問題。
結論:
1、使用1.7.2之前的版本,在使用$.ajax的時候需要自行設定contentType否則,Google會亂碼。
2、跟瀏覽器也有關係,Firefox就可以自動加上utf-8而Google則不會,也行jquery團隊發現這個問題,所以就在最新版更正了這個問題。
測試及產生環境:
1、java環境,打包gbk,頁面編碼gbk,tomcat中URIEncoding配置utf-8等,也許應該跟這些伺服器配置也是有關係的,就不深究下去了。
猜測:一般post表單請求的請求資料編碼是按照頁面裡面的meta指定的編碼格式編碼的,我們頁面是gbk的,所以在Google瀏覽器在未指定ajax的contentType參數的時候採用預設頁面編碼方式gbk編碼然後發送到伺服器端,而我們tomcat裡面的URIEncoding是utf-8的,所以就兩邊編碼不一樣,就亂碼了,顯式的指定一下就ok。不過貌似ajax統一都是utf-8的來編碼的,就算不指定也不會有問題,莫不是Google。。。。