估計很多人在做web開發的時候,都會碰到過url傳遞中文參數,有時候會出現亂碼的問題,但有些項目或者環境,又不會有問題。當遇到亂碼的時候,上網找了很多解決方案,比如:
- 頁面設置它的編碼方式,改成utf-8 或者gb2312。
-
encodeURI(url),也有人說要2個encodeURI,如:window.location.href = encodeURI('b.html?cId='+id+"&cName="+encodeURIComponent(name));
然后后台String str = java.net.URLDecoder.decode(str, "UTF-8");這樣進行轉碼等。
解決方法就不一一列舉了,大家可自行百度搜索,我也搞不清楚究竟怎么能保證百分百解決問題。
項目中碰到的情況是,開發環境經過上述的2種方法,折騰過,確實能定位某個編碼轉換是正常的。
但部署到測試環境調試輸出后發現,無論是gbk,utf8,iso等等編碼測試,都無法正常還原中文字符串。
於是想到了另外一種方法,就是把中文轉換為數字或者是英文字母以及標點符號等組成的字符串傳遞到后台,
因此有想法是把字符串加密為base64的方式傳過去后,再后台再進行解密。上網找了下,沒找到現成的有效方法,於是放棄了。
再后來,想着不需要加密了,直接把字符串轉換成16進制傳遞到后台,再把它轉回來吧,於是,這個終極的解決方案就出來了。
首先是jsp頁面中增加腳本,把字符串轉換成16進制字符串,字符之間用,號隔開,不隔開,無法區分出哪個是半角哪個是全角(如果不用,號隔開的,麻煩請提供個好的解決方法,謝謝)
function stringToHex(str){
var val="";
for(var i = 0; i < str.length; i++){
if(val == "")
val = str.charCodeAt(i).toString(16);
else
val += "," + str.charCodeAt(i).toString(16);
}
return val;
}
頁面上把字符串經過該函數轉換后,傳遞到后台,如:
var code_value=stringToHex(PrjName);
var url= "/assets/fmProjectInfo.do?method=synCheckProjectName&prjName="+code_value+"&typeId=<bean:write name="fmProjectInfoForm" property="bo.ftId"/>"
后台的轉換代碼為:
public static String decode(String unicodeStr) {
if (unicodeStr == null) {
return null;
}
StringBuffer retBuf = new StringBuffer();
int maxLoop = unicodeStr.length();
for (int i = 0; i < maxLoop; i++) {
if (unicodeStr.charAt(i) == '\\') {
if ((i < maxLoop - 5)
&& ((unicodeStr.charAt(i + 1) == 'u') || (unicodeStr
.charAt(i + 1) == 'U')))
try {
retBuf.append((char) Integer.parseInt(
unicodeStr.substring(i + 2, i + 6), 16));
i += 5;
} catch (NumberFormatException localNumberFormatException) {
retBuf.append(unicodeStr.charAt(i));
}
else
retBuf.append(unicodeStr.charAt(i));
} else {
retBuf.append(unicodeStr.charAt(i));
}
}
return retBuf.toString();
}
//把jsp頁面傳遞進來的,用,號隔開的16進制字符串轉換成 類似:select \u7528\u6237\u540d from \u7528\u6237 的字符串,在調用decode方法把中文轉換出來。
public static String jspStrInit(String sourceStr)
{
String[] sourceStrArray = sourceStr.split(",");
StringBuffer sb=new StringBuffer();
for (int i = 0; i < sourceStrArray.length; i++) {
if (sourceStrArray[i].length()<=2)
sb.append(hexStr2Str(sourceStrArray[i].toUpperCase()));
else
sb.append("\\u"+sourceStrArray[i]);
}
return sb.toString();
}
public static String jspDecode(String unicodeStr) {
String mStr=jspStrInit(unicodeStr);
return decode(mStr);
}
/**
* 十六進制轉換字符串
* @param String str Byte字符串(Byte之間無分隔符 如:[616C6B])
* @return String 對應的字符串
*/
public static String hexStr2Str(String hexStr)
{
String str = "0123456789ABCDEF";
char[] hexs = hexStr.toCharArray();
byte[] bytes = new byte[hexStr.length() / 2];
int n;
for (int i = 0; i < bytes.length; i++)
{
n = str.indexOf(hexs[2 * i]) * 16;
n += str.indexOf(hexs[2 * i + 1]);
bytes[i] = (byte) (n & 0xff);
}
return new String(bytes);
}
public static void main(String[] args) throws Exception
{
String bb="5e02,91cd,70b9,5de5,4f5c,6d4b,8bd5";
String cc=jspDecode(bb);
System.out.println(cc);
}
jspDecode這個方法就是把jsp頁面傳遞過來的字符串進行還原的。該終極解決方法就此結束。
最后,在另外一個項目中有客戶的研發保障,說修改意見那里有時候保存不成功,有時候又沒問題,經過分析,修改意見那里是使用ajax封裝了json的數據傳遞到后台進行更新的。
由於意見里面包含了回車,標點符號等特殊符號,違反了json的原則導致的,我給他提供的解決方案,也是采用了該方案,讓他把該意見轉換為16進制字符串之后,傳遞到后台再轉換回來去解決。
目前還沒得到問題的解決答復,但按理,應該也可以用在該場景里面。
原創作品出自努力偷懶,轉載請說明文章出處:http://blog.csdn.net/kfarvid或 http://www.cnblogs.com/kfarvid/
