客户端是UTF-8编码,这也是现在大家公认的标准编码
在这种情况下,实用AJAX异步获取GB2312编码的服务器端信息时,不可避免的要遇到汉字乱码问题
因为目标数据是GB2312,但XMLHttpRequest默认是用UTF-8来进行数据封装的,因此会产生乱码
相信很多人都在用轻量级的JS工具集-prototype.js,它的AJAX功能同样很出色
我也一直在用它,因此对于这个问题也一直是基于 prototype.js来考虑的
但经过多次试验,还是没能把它返回的 responseText 转成正确的编码格式
后来了解到,在XMLHttpRequest对象的 responseBody
属性中,保存了原始的数据信息
但prototype.js的AJAX功能返回的 responseBody 属性是
undefined,看来还是要自己动手了
经过近一个小时的敲打,一个短小精悍的AJAX框架腾空出世了,哈哈,不过功能还是很全的
里面某些写法借鉴了另一个轻量级的AJAX框架-bingo.js的实现方式
调用方式及注释:

大多数的客户端都采用UTF-8编码,这也是现在实现国际化最常用的编码格式

前后台都是UTF-8编码,在用AJAX的GET方式传递数据时,发生乱码!

参考资料:

复制代码 代码如下:

在这种情况下,实用AJAX异步获取GB2312编码的服务器端信息时,不可避免的要遇到汉字乱码问题

将解决方式记载一下,以待追溯:

乱码的本质是涉及到编解码的几个过程所用的编码方式不一样。

myAjaxCall({
url : ‘xxxxx.jsp’ //目标页面地址
,params : URLEncoding(‘prm1=参数1&prm2=参数2’) //参数串信息
,method : ‘POST’ //发送方式POST or GET
,callBack : retValue //回调函数名称
,isBody : true //是否返回 responseBody ,默认返回 responseText
//,isXml : false //是否以XML格式返回数据
//,errorReport : false //发送错误时,是否弹出提示
//,attachs : {} //附加的其他参数,可传递给回调函数
});
function retValue(res,att){
var strRet = bytes2BSTR(res);
alert(strRet);
}

因为目标数据是GB2312,但XMLHttpRequest默认是用UTF-8来进行数据封装的,因此会产生乱码

前台:

一、从服务端到客户端

注意看其中的两个函数:

相信很多人都在用轻量级的JS工具集-prototype.js,它的AJAX功能同样很出色

 

在整个服务器端数据返回到浏览器的过程中,涉及到三次编码:

、URLEncoding :对参数进行编码
、bytes2BSTR :对返回的数据进行解码

我也一直在用它,因此对于这个问题也一直是基于 prototype.js来考虑的

1 var strUrl = “../getInfo?paramName=中文参数值”;   
2 strUrl = encodeURI(encodeURI(strUrl)); //两次URL转码   
3  Ext.Ajax.request({   
4     url : strUrl,   
5     method : ‘GET’   
6 });  

第一次:java文件以什么编码存放在硬盘中

这两个函数直接借鉴了网络上很流行的两个编码函数,不过都是用vbs写的
需要把这两个函数也附加到上面的页面里:

但经过多次试验,还是没能把它返回的 responseText 转成正确的编码格式

 

第二次:字符串是以什么编码方式转换成字节数组的,若未指定@RequestMapping的produces属性,同时也未给StringHttpMessageConverter指定编码方式,则字符串默认是以ISO-8859-1形式转换成字节数组的。

复制代码 代码如下:

后来了解到,在XMLHttpRequest对象的 responseBody
属性中,保存了原始的数据信息

 

    可以通过produces =
“text/html;charset=UTF-8″来指定编码:@RequestMapping(value =
“/register”, method = RequestMethod.POST, produces =
“text/html;charset=UTF-8”)

Function URLEncoding(vstrIn)
strReturn = “”
For i = 1 To Len(vstrIn)
ThisChr = Mid(vStrIn,i,1)
If Abs(Asc(ThisChr)) < &HFF Then
strReturn = strReturn & ThisChr
Else
innerCode = Asc(ThisChr)
If innerCode < 0 Then
innerCode = innerCode + &H10000
End If
Hight8 = (innerCode And &HFF00) \ &HFF
Low8 = innerCode And &HFF
strReturn = strReturn & “%” & Hex(Hight8) & “%” & Hex(Low8)
End If
Next
URLEncoding = strReturn
End Function
Function bytes2BSTR(vIn)
strReturn = “”
For i = 1 To LenB(vIn)
ThisCharCode = AscB(MidB(vIn,i,1))
If ThisCharCode < &H80 Then
strReturn = strReturn & Chr(ThisCharCode)
Else
NextCharCode = AscB(MidB(vIn,i+1,1))
strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 +
CInt(NextCharCode))
i = i + 1
End If
Next
bytes2BSTR = strReturn
End Function

但prototype.js的AJAX功能返回的 responseBody 属性是
undefined,看来还是要自己动手了

后台:

第三次:数据发送给浏览器后,浏览器接收到一堆字节数组,浏览器又是以什么编码方式来解码的。 

下面附上我写的轻量级Ajax框架 – myAjax.js 源码:

经过近一个小时的敲打,一个短小精悍的AJAX框架腾空出世了,哈哈,不过功能还是很全的

 

只有三者统一才不会出现乱码。具体见上述参考文章。

复制代码 代码如下:

调用方式及注释:

1 String paramValue = request.getParameter(“paramName”);   
2 paramValue = java.net.URLDecoder.decode(paramValue,”UTF-8″);

 

/**
2 * myAjax
3 * by netwild
4 *
[email protected]
5 */
6 var myAjaxConfig = {
7 “url”:””
8 ,”params”:””
9 ,”method”:”GET”
,”callBack”:function(){}
,”isXml”:false
,”isBody”:false
,”isCache”:false
,”errorReport”:true
,”statePoll”:null
,”postData”:null
,”attachs”:{}
};
function myAjaxCall(requestJson){
var attach;
if(requestJson && typeof requestJson == “object”){
if(requestJson.url){myAjaxConfig.url = requestJson.url;}
if(requestJson.params){myAjaxConfig.params = requestJson.params;}
if(requestJson.method){myAjaxConfig.method = requestJson.method;}
if(requestJson.callBack){myAjaxConfig.callBack =
requestJson.callBack;}
if(requestJson.isXml){myAjaxConfig.isXml = requestJson.isXml;}
if(requestJson.isBody){myAjaxConfig.isBody = requestJson.isBody;}
if(requestJson.isCache){myAjaxConfig.isCache = requestJson.isCache;}
if(requestJson.statePoll){myAjaxConfig.statePoll =
requestJson.statePoll;}
if(requestJson.attachs){myAjaxConfig.attachs = requestJson.attachs;}
}
if(!myAjaxConfig.isCache){
var nocache = new Date().getTime();
if(myAjaxConfig.url.indexOf(“?”)>0){myAjaxConfig.url += “&nocache=” +
nocache;}
else{myAjaxConfig.url += “?nocache=” + nocache;}
}
var newCall = new myAjaxCore();
newCall.init();
}
function myAjaxCore(){
var _self = this;
var _state,_status;
var _httpRequest,_attach;
////////////////////////////////////////////////////
this.init = function(){
if (window.XMLHttpRequest){
_httpRequest = new XMLHttpRequest();
if (_httpRequest.overrideMimeType) {
_httpRequest.overrideMimeType(‘text/xml’);
}
}else if (window.ActiveXObject) {
var MSXML =
[‘MSXML2.XMLHTTP.6.0′,’MSXML2.XMLHTTP.3.0′,’MSXML2.XMLHTTP.5.0′,’MSXML2.XMLHTTP.4.0′,’MSXML2.XMLHTTP’,
‘Microsoft.XMLHTTP’];
for(var n=0;n<MSXML.length;n++){
try {
_httpRequest = new ActiveXObject(MSXML[n]);
break;
}catch(e){}
}
}
with(_httpRequest) {
onreadystatechange = _self.getResponse;
open(myAjaxConfig.method,myAjaxConfig.url,true);
if(myAjaxConfig.method == “POST” && (myAjaxConfig.params != “”)){
setRequestHeader(“Content-Length”,myAjaxConfig.params.length);
setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
send(myAjaxConfig.params);
}else{
var textType = myAjaxConfig.isXml?”text/xml”:”text/plain”;
_httpRequest.setRequestHeader(‘Content-Type’,textType);
if(browser.IE){
setRequestHeader(“Accept-Encoding”, “gzip, deflate”);
}else if(browser.FF){
setRequestHeader(“Connection”,”close”);
}
send(null);
}
}
};
////////////////////////////////////////////////////
this.getResponse = function(){
_state = _httpRequest.readyState;
if(_httpRequest.readyState == 4 && _httpRequest.status){_status =
_httpRequest.status;}
if(myAjaxConfig.statePoll){myAjaxConfig.statePoll(_httpRequest.readyState);}
if(_httpRequest.readyState==4 && _httpRequest.status>=400){
_self.abort();
_self.alertf(“ERROR:HTTP response code “+_httpRequest.status);
}
if(_httpRequest.readyState==4 && _httpRequest.status==200){
var response_content;
if(myAjaxConfig.isXML){
response_content = _httpRequest.responseXML;
}else if(myAjaxConfig.isBody){
response_content = _httpRequest.responseBody;
}else{
response_content = _httpRequest.responseText;
}
if(typeof myAjaxConfig.callBack == “function”){
myAjaxConfig.callBack(response_content,myAjaxConfig.attachs);
}else{
eval(myAjaxConfig.callBack+”(response_content,myAjaxConfig.attachs)”);
}
}
};
////////////////////////////////////////////////////
this.abort=function(){_httpRequest.abort();};
this.state=function(){return _state;};
this.status=function(){return _status;};
this.destory=function(){_self.abort();delete(_httpRequest);};
this.alertf=function(error){if(myAjaxConfig.errorReport){alert(error);}};
}
if(!browser){
var browser={};
browser.IE = browser.ie =
window.navigator.userAgent.indexOf(“MSIE”)>0;
browser.Firefox = browser.firefox = browser.FF = browser.MF =
navigator.userAgent.indexOf(“Firefox”)>0;
browser.Gecko = browser.gecko =
navigator.userAgent.indexOf(“Gecko”)>0;
browser.Safari =
browser.safari=navigator.userAgent.indexOf(“Safari”)>0;
browser.Camino =
browser.camino=navigator.userAgent.indexOf(“Camino”)>0;
browser.Opera =
browser.opera=navigator.userAgent.indexOf(“Opera”)>0;
browser.other = browser.OT=!(browser.IE || browser.FF || browser.Safari
|| browser.Camino || browser.Opera);
}

myAjaxCall({      
    url : 'xxxxx.jsp' //目标页面地址      
    ,params : URLEncoding('prm1=参数1&prm2=参数2') //参数串信息      
    ,method : 'POST' //发送方式POST or GET      
    ,callBack : retValue //回调函数名称      
    ,isBody : true //是否返回 responseBody ,默认返回 responseText      
    //,isXml : false //是否以XML格式返回数据      
    //,errorReport : false //发送错误时,是否弹出提示      
    //,attachs : {} //附加的其他参数,可传递给回调函数      
});      
function retValue(res,att){      
    var strRet = bytes2BSTR(res);      
    alert(strRet);      
}

 

二、客户端到服务端

在这种情况下,实用AJAX异步获取GB2312编码的服务器端信息时,不可避免的要遇到汉字乱…

 

 

此过程涉及到两次编码:

注意看其中的两个函数:

第一次:当你输入  
的时候,浏览器将以什么样的编码方式将中国转化成字节数组,这称为URL编码
。不同的浏览器会采用不同编码方式来将 中国
转换成字节数组,一般为UTF-8;而程序中按默认编码对中文进行url
encode,中文环境一般为GBK,这点应注意。

1、URLEncoding :对参数进行编码
2、bytes2BSTR
:对返回的数据进行解码

第二次:当浏览器发送请求时,服务器是以请求的content-type来解析请求数据的,当浏览器请求没有指定content-type时,不同的服务器应该有不同的策略,并且可以进行设置。

这两个函数直接借鉴了网络上很流行的两个编码函数,不过都是用vbs写的
需要把这两个函数也附加到上面的页面里:

如Tomcat服务器,默认采用的是ISO-8859-1(不支持中文),可以通过修改Tomcat的conf/server.xml文件,在Connector标签中增加 URIEncoding=’UTF-8′ 来修改Tomcat的默认编码解析方式(在Tomcat
8中默认已为UTF-8,这个应特别注意,否则经下面所说的代码方法处理后的代码放在Tomcat8反而会乱码,笔者就因为这个原因导致本机能正确跑的代码放在生产环境中后跑的结果不正确,浪费了好多时间);

 

对于默认采用的是ISO-8859-1的服务器,此也可以通过在代码中解码再编码数据来解决乱码:

Function URLEncoding(vstrIn)   
    strReturn = ""   
    For i = 1 To Len(vstrIn)   
        ThisChr = Mid(vStrIn,i,1)   
        If Abs(Asc(ThisChr)) < &HFF Then   
            strReturn = strReturn & ThisChr   
        Else   
            innerCode = Asc(ThisChr)   
            If innerCode < 0 Then   
                innerCode = innerCode + &H10000   
            End If   
            Hight8 = (innerCode  And &HFF00) \ &HFF   
            Low8 = innerCode And &HFF   
            strReturn = strReturn & "%" & Hex(Hight8) &  "%" & Hex(Low8)   
     End If   
    Next   
    URLEncoding = strReturn   
End Function   
Function bytes2BSTR(vIn)   
    strReturn = ""   
    For i = 1 To LenB(vIn)   
        ThisCharCode = AscB(MidB(vIn,i,1))   
        If ThisCharCode < &H80 Then   
            strReturn = strReturn & Chr(ThisCharCode)   
        Else   
            NextCharCode = AscB(MidB(vIn,i+1,1))   
            strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))   
            i = i + 1   
        End If   
    Next   
    bytes2BSTR = strReturn   
End Function
// GET方式:http的url传过来的数据Tomcat默认是用iso-8859-1(不支持中文)解码的,故数据先用iso-8859-1编码得到原文后再用与url相同的编码方法解码
userName = new String(userName.getBytes("iso8859-1"), "utf-8");

 

 

下面附上我写的轻量级Ajax框架 – myAjax.js 源码:

三、java Servlet中中文乱码

 

1、post

/**
 * Ajax工具类: myAjax
 * @author     网无忌(netwild)
 * @email      inetwild@gmail.com
 * @qq         52100641
 * @version    1.0
 */
var myAjaxConfig = {   
    "url":""   
    ,"params":""   
    ,"method":"GET"   
    ,"callBack":function(){}   
    ,"isXml":false   
    ,"isBody":false   
    ,"isCache":false   
    ,"errorReport":true   
    ,"statePoll":null   
    ,"postData":null   
    ,"attachs":{}   
};   
function myAjaxCall(requestJson){   
    var attach;   
    if(requestJson && typeof requestJson == "object"){   
        if(requestJson.url){myAjaxConfig.url = requestJson.url;}   
        if(requestJson.params){myAjaxConfig.params = requestJson.params;}   
        if(requestJson.method){myAjaxConfig.method = requestJson.method;}   
        if(requestJson.callBack){myAjaxConfig.callBack = requestJson.callBack;}   
        if(requestJson.isXml){myAjaxConfig.isXml = requestJson.isXml;}   
        if(requestJson.isBody){myAjaxConfig.isBody = requestJson.isBody;}   
        if(requestJson.isCache){myAjaxConfig.isCache = requestJson.isCache;}   
        if(requestJson.statePoll){myAjaxConfig.statePoll = requestJson.statePoll;}   
        if(requestJson.attachs){myAjaxConfig.attachs = requestJson.attachs;}   
    }   
    if(!myAjaxConfig.isCache){   
        var nocache = new Date().getTime();   
        if(myAjaxConfig.url.indexOf("?")>0){myAjaxConfig.url += "&nocache=" + nocache;}   
        else{myAjaxConfig.url += "?nocache=" + nocache;}   
    }   
    var newCall = new myAjaxCore();   
    newCall.init();   
}   
function myAjaxCore(){   
    var _self = this;   
    var _state,_status;   
    var _httpRequest,_attach;   
    ////////////////////////////////////////////////////   
    this.init = function(){   
        if (window.XMLHttpRequest){   
            _httpRequest = new XMLHttpRequest();   
            if (_httpRequest.overrideMimeType) _httpRequest.overrideMimeType('text/xml'); 
        }else if (window.ActiveXObject) {   
            var MSXML = ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];   
            for(var n=0;n<MSXML.length;n++){    
                try {    
                    _httpRequest = new ActiveXObject(MSXML[n]);    
                    break;    
                }catch(e){}   
            }    
        }   
        with(_httpRequest) {   
            onreadystatechange = _self.getResponse;   
            open(myAjaxConfig.method,myAjaxConfig.url,true);   
            if(myAjaxConfig.method == "POST" && (myAjaxConfig.params != "")){   
                setRequestHeader("Content-Length",myAjaxConfig.params.length);      
                setRequestHeader("Content-Type","application/x-www-form-urlencoded");   
                send(myAjaxConfig.params);   
            }else{   
                var textType = myAjaxConfig.isXml?"text/xml":"text/plain";   
                _httpRequest.setRequestHeader('Content-Type',textType);   
                if(browser.IE) setRequestHeader("Accept-Encoding", "gzip, deflate");   
                else if(browser.FF) setRequestHeader("Connection","close");   
                send(null);   
            }   
        }   
    };   
    ////////////////////////////////////////////////////   
    this.getResponse = function(){   
        _state = _httpRequest.readyState;   
        if(_httpRequest.readyState == 4 && _httpRequest.status){_status = _httpRequest.status;}   
        if(myAjaxConfig.statePoll){myAjaxConfig.statePoll(_httpRequest.readyState);}   
        if(_httpRequest.readyState==4 && _httpRequest.status>=400){   
            _self.abort();   
            _self.alertf("ERROR:HTTP response code "+_httpRequest.status);   
        }   
        if(_httpRequest.readyState==4 && _httpRequest.status==200){   
            var response_content;   
            if(myAjaxConfig.isXML){   
                response_content = _httpRequest.responseXML;   
            }else if(myAjaxConfig.isBody){   
                response_content = _httpRequest.responseBody;      
            }else{   
                response_content = _httpRequest.responseText;   
            }          
            if(typeof myAjaxConfig.callBack == "function"){   
                myAjaxConfig.callBack(response_content,myAjaxConfig.attachs);   
            }else{   
                eval(myAjaxConfig.callBack+"(response_content,myAjaxConfig.attachs)");   
            }   
        }   
    };   
    ////////////////////////////////////////////////////   
    this.abort=function(){_httpRequest.abort();};   
    this.state=function(){return _state;};   
    this.status=function(){return _status;};   
    this.destory=function(){_self.abort();delete(_httpRequest);};   
    this.alertf=function(error){if(myAjaxConfig.errorReport){alert(error);}};   
}   
if(!browser){   
    var browser={};   
    browser.IE = browser.ie = window.navigator.userAgent.indexOf("MSIE")>0;   
    browser.Firefox = browser.firefox = browser.FF = browser.MF = navigator.userAgent.indexOf("Firefox")>0;   
    browser.Gecko = browser.gecko = navigator.userAgent.indexOf("Gecko")>0;   
    browser.Safari = browser.safari=navigator.userAgent.indexOf("Safari")>0;   
    browser.Camino = browser.camino=navigator.userAgent.indexOf("Camino")>0;   
    browser.Opera = browser.opera=navigator.userAgent.indexOf("Opera")>0;   
    browser.other = browser.OT=!(browser.IE || browser.FF || browser.Safari || browser.Camino || browser.Opera);   
}

对于post方法中的乱码,浏览器通常是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收。

 

可以通过request.setCharacterEncoding(“utf-8”);解决;或在代码中解码再编码数据来解决乱码

 

2、get

在代码中解码再编码数据来解决乱码

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图