常見中文亂碼問題

2021-07-24 17:34:36 字數 3908 閱讀 9978

一、常見亂碼問題

1.1 ajax請求中文引數亂碼

傳送ajax請求時,如果引數中有中文,服務端獲取到引數後,有可能亂碼。

1.2 外聯js**中文字元亂碼

外聯方式引入js檔案,如果js的**中有中文,有可能亂碼。

下面就來依次分析這兩個場景。

二、ajax請求中文引數亂碼

ajax請求分為get和post兩種方式,對於這2種方式,webx框架的處理不盡相同。此外,在客戶端瀏覽器的處理上,也有可能出現一些中文編碼字符集的不確定性。

2.1 知識點

首先介紹下encodeuricomponent('***'),這個js原生函式採用utf-8編碼,js**中對中文字元進行顯式編碼時,基本上用的都是該函式。

接下來介紹下編碼的基本知識,在此copy一下webx文件的一段話,如下。

2.1.1 get請求

對於get方式的ajax請求,如果未顯式執行

encodeuricomponent對中文引數進行編碼,那麼瀏覽器會根據「輸出字符集」對中文字元進行編碼,webx預設配置的是gbk輸出字符集,也就是說瀏覽器極有可能採用gbk字符集進行中文字元編碼。當前,也不排除個別瀏覽器在實現上不是這個套路。如果使用了某些js庫的ajax元件,js庫也有可能額外搞一些動作。而對於英文作業系統,由於我沒有測試過,也不確定是否會影響到瀏覽器的編碼字符集。因此存在著一定的編碼字符集不確定性。

在服務端對get請求的處理過程中,webx框架沒有採用servlet引擎的解碼方式,而是另起爐灶,特殊進行了引數解析和字元解碼。需要特別說明的是,webx在此之前,統一設定了characterencoding,

webx預設配置的是gbk輸入字符集

。get請求引數解析和字元解碼的關鍵**如下圖所示。

詳細**可參見webx3的com.alibaba.citrus.service.requestcontext.parser.impl.parameterparserimpl類,以建構函式為入口進行閱讀。

2.1.2 post請求

對於post方式的ajax請求,字元編碼一律採用utf-8,這應該是ajax的乙個規範。在kissy的**和webx的文件中都有闡述,ajax規範還有待進一步研究確認。​

對於非ajax的正常表單提交,字元編碼會採用web頁面的字符集,對於**的頁面來講,通常就是gbk。

在服務端對post請求的處理過程中,webx框架採用了servlet引擎提供的解碼方式。仍然需要特別說明的是,webx在servlet引擎解碼之前,也統一設定了httpservletrequest的characterencoding,即「輸入字符集」,webx預設配置的是gbk,與get請求設定characterencoding是在同乙個地方。如下所示。

// 試圖從querystring中取得inputcharset

string querystring = getrequest().getquerystring();

string inputcharset = locale.getcharset().name();

if (querystring != null)

}}getrequest().setcharacterencoding(inputcharset);

詳細**可參見webx3的com.alibaba.citrus.service.requestcontext.locale.impl.setlocalerequestcontextimpl類,以prepare方法為入口進行閱讀。

2.2 亂碼原因

由以上知識點可知,我們通常遇到的亂碼一般是由於客戶端對中文採用了utf-8編碼,而服務端採用gbk解碼導致。

2.3 解決方法

2.3.1 對於get請求產生的亂碼,通常需要做兩件事情。第一,使用encodeuricomponent對中文字元進行編碼,消除編碼字符集的不確定性。第二,需要在url中額外增加 

_input_charset 引數,值為utf-8,這個引數是webx預留的引數,可以優先設定本次請求的解碼字符集,核心**同2.1.2的**貼圖,這裡補充一下webx.xml的配置和匹配_input_charset 引數的正則pattern,如下所示。

string input_charset_param_default = "_input_charset";

inputcharsetparam = defaultifnull(inputcharsetparam, input_charset_param_default);

inputcharsetpattern = pattern.compile(inputcharsetparam + "=([w-]+)");

這裡還有另外一種處理方式,即尋找第三方js庫,提供gbk編碼的encodeuri函式,可以免去url中的_input_charset 引數。

2.3.2 對於post請求產生的亂碼,通常只需要

在url(請注意是url,不是表單引數)中額外增加 

_input_charset 引數,值為utf-8即可。

如果這樣處理仍然有問題,並且使用的是kissy庫的ajax元件,那麼可以先使用encodeuricomponent對中文字元進行編碼,然後再傳送ajax請求,這時候url中是否有_input_charset 引數已經無關緊要。之後,服務端業務**要顯式執行urldecoder.decode("***","utf-8"),即可獲取到正確的中文字元。這裡面發生了一些有趣的事情,簡單yy下。在顯式執行encodeuricomponent之後,傳送ajax請求之前,kissy的ajax元件又額外進行了一次

encodeuricomponent。以「測試」舉例,經過一次

encodeuricomponent處理後的值是「

測試」,再經過一次encodeuricomponent,值變成了「

%25e6%25b5%258b%25e8%25af%2595

」,這樣無論webx框架採用何種輸入字符集,servlet引擎解碼後,值都會恢復成「測試」,之後業務**再顯式執行urldecoder # decode,就拿到中文字元了。

kissy額外的一次

encodeuricomponent,發生在對傳入的表單陣列進行s.param的時候,可以參看原始碼。

三、外聯js**中文字元亂碼

3.1 知識點

web頁面引用外聯js,若未加特殊處理,一般會按照web頁面的字符集對外聯js進行解碼。

瀏覽器解碼的字符集,一般按照以下優先順序判斷。httpheader(」content-type:text/html; charset=***」)優先順序最高,如http-header未指定則依據html,如果http-header和html-meta都沒有指定,那麼一般就是依據檔案的bom編碼格式。

3.2 亂碼原因

我遇到的亂碼都是發生在daily環境。

**的web頁面基本都是gbk字符集。

**外聯的js,daily環境放在assets測試伺服器上,線上環境放在tbcdn上,編碼字符集由js檔案的bom決定。

前端同學編寫js**,在儲存時一般都採用utf-8編碼。

因此,用gbk解析utf-8編碼的中文字元,就出現亂碼了。

3.3 解決方法

3.3.1 對script單獨設定解碼字符集,,這樣處理後,該script的解碼就按照指定的charset進行。

3.3.2 前端採用gbk字符集儲存**並提交。這個應該不太可行,前端採用utf-8編碼應該有一些原因,至於是對壓縮有影響,還是其它的原因,有待深入**。

3.3.3 採用ucool等工具作**,並將**檔案以gbk字符集儲存。

中文亂碼問題

母頁 tran cel.jsp?p user id p user id p paraxml mytran cel paraxml ie8對window.open二進位製流會遮蔽,用二次請求解決該問題 modify by 20120731。mytran cel paraxml encodeuri my...

中文亂碼問題

url位址中傳遞中文,接收亂碼。修改tomcat的server.xml.在埠號那一項中增加 uriencoding utf 8 connectiontimeout 20000 redirectport 8443 uriencoding utf 8 在form表單中中文亂碼 1.保證你的專案的屬性是u...

中文亂碼問題

中文亂碼問題 1.什麼時候會出現亂碼?編碼和解碼的方式不一致。2.請求時亂碼 a.get a.修改tomcat的配置檔案,即修改 tomcat conf server.xml中的70行,增加uriencoding utf 8 b.不修改解碼方式,讓servlet直接接收亂碼,然後採用iso8859 ...