文档章节

ajax中文乱码问题的总结

y
 yiranxijie
发布于 2015/06/01 11:23
字数 2744
阅读 33
收藏 0

ajax中文乱码问题的总结

ajax中文乱码问题的总结

本章解决在AJAX中常见的中文问题,分析中文乱码产生的原因,以及如何解决乱码问题

1. HTTP协议的编码规定

在HTTP协议中,浏览器不能向服务器直接传递某些特殊字符,必须是这些字符进行URL编码后再进行传送。url编码遵循的规则:

 

将空格转换为(+)

 

对0-9,a-z,A-Z之间的字符保持不变。

 

对于所有其他的字符,用这个字符的当前字符集编码在内存中的十六进制格式表示,并在每个十六进制字节前加上一个百分号%。例如,字符“+”用%2B表示,字符“=”用%3D表示,字符“&”用%26表示,字符“国”用%B9%FA表示注意,同一个中文字符在不同的字符集编码方式下,在内存中的编码值也是不同的,一个字符的URL编码是针对字符在内存中的码值而言的,采用不同编码的同一个字符的URL编码结果是不同的。

 

2. encodeURI()与encodeURIComponent()函数

javaScript中提供了两个函数来对字符进行URL编码:encodeURI()与encodeURIComponent(),两者的区别在于,encodeURI函数不会对以下的字符进行处理: “! @ # $ & * ( ) = : / ; ? + ' ”,而encodeURIComponent函数会对更多的字符进行处理比如 URI的组成部分 “/” 就会被encodeURIComponent进行处理。这两个方法对传递的值进行URL编码,过程是先找到字符所对应的UTF-8编码,比如“张三”两个字的UTF-8编码是”0xE5BCA0E4B889”(前面的是零x,表示是16进制编码).“张”是”0xE5BCA0”,”三”是”0xE4B889”,那么被转换后的结果就

是”%E5%BC%A0%E4%B8%89”,注意这个转换结果与网页的编码没有任何关系,因为这两个函数总是拿到字符所对应的UTF-8码,然后再进行URL编码的。也就是说不管网页是GBK的编码还是UTF-8的编码,转换的结果都一样。

所以如果我们发送给服务器的请求包含有中文或者其它比较特殊的字符如空格“+”等符号的时候,就就需要使用者两个函数对字符进行URL编码。

3. 封装Ajax请求代码,供后面使用。

新建一个web项目,在web项目中添加一个ajax.js文件,内容包含两个函数如下:

createXmlHttp()

function createXmlHttp() {

if (window.XMLHttpRequest) {

//alert("非IE浏览器");

return new XMLHttpRequest();

} else if (window.ActiveXObject && !window.XMLHttpRequest){

var aVersion = ["MSXML2.XMLHttp.6.0",

"MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0",

"MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp",

"Microsoft.XMLHttp"];

for (var i = 0; i < aVersion.length; i++) {

try {

var oXmlHttp = new ActiveXObject(aVersion[i]);

//alert("IE浏览器版本"+aVersion[i]);

return oXmlHttp;

}

catch (ex) {}

}

}

throw new Error("创建XMLHttpRequest对象出错!");

}

doGet(url,callBack)函数,该函数有两个参数,将来要发送AjAX GET请求可以直接调用该方法。 第一个参数表示要发送的请求的URL地址,第二个是回调函数,回调函数需要处理从服务端返回的数据。

/**

* @param url 请求的URL地址

* @param callBack 回调函数

* @return

*/

function doGet(url,callBack){

var request=createXmlHttp();

request.onreadystatechange=function(){

if(request.readyState==4 && request.status==200){

//注意我们定义回调函数的时候要多加一个参数接收返回的数据

callBack(request.responseText);

}

};

request.open("GET",url);

request.send(null);

}

4. 编写页面,该页面使用的字符集是UTF-8编码:

HTML部分:

<body>

<h3>验证用户名是否存在</h3>

输入用户名:<input type="text" id="userName" /> <span id="warning"></span><br />

<input type="button" value="验证" onclick="checkUserName('userName')" />

</body>

JavaScript部分:

首先引入ajax.js文件,然后编写当按钮点击的时候的要执行的代码:

<script type="text/javascript" src="ajax.js"></script>

<script type="text/javascript">

function checkUserName(tagID){

//获取文本框中输入的值

var userName=document.getElementById(tagID).value;

//对中文进行URL编码

①var url="ajax.do?"+encodeURI("userName="+userName);

//data是从服务端返回来的数据

doGet(url,function(data){

document.getElementById("warning").innerHTML=data;

});

}

</script>

页面效果:

 

当在文本框中输入“张三”后,点击验证后,javaScript代码执行到 ① 之后,url的值就变成了 “ajax.do?userName=%E5%BC%A0%E4%B8%89”,可以通过firefox浏览器的firebug插件进行断点调试,得到发送的url的值。

这里为什么没有使用encodeURIComponent()函数呢?这是因为encodeURIComponent函数会将”=”变成“%3D”,“?”变成” %3F”, 如果有多个参数的话会用到“&”符号,同样也会被转换,而这些字符不用转换也可以提交,所以这里使用了encodeURI,这个函数不会对”?”,”=”,”&”进行转换。后面的“%E5%BC%A0%E4%B8%89”就是“张三”两个汉字按照UTF-8字符集进行URL编码之后的结果

5. 在服务端取得发送过来的数据

编写一个Servlet,这个Servlet的映射是 /ajax.do,其中的doGet方法如下:

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//告诉客户端响应的信息的编码格式是UTF-8

response.setContentType("text/html;charset=UTF-8");

②String userName=request.getParameter("userName");

PrintWriter out=response.getWriter();

out.print("您要验证的用户名是:"+userName+",该用户名可以使用");

}

我们在②处放置一个断点,然后以断点的方式启动Tomcat,提交后程序进入断点处我们发现取得的userName的值是: “??????”,为什么会是乱码?

我们分析一下,客户端Ajax想服务器发送的请求是

”ajax.do?userName=%E5%BC%A0%E4%B8%89”,那么服务器上的

request.getParameter()方法在取参数值的时候,首先要进行URL解码(其实就是去掉字符当中的“%“),解码之后将只剩下的字节部分按照Tomcat在内部默认的ISO-8859-1字符集的方式转换成字符串,于是乱码开始在这里出现 了。因为发送过来的字节在去掉%后剩下的字节应该按照UTF-8转换字符串才对,但是却采用了ISO-8859-1,于是乱码产生了。

那么知道原因之后,解决起来就很容易了。既然是按照ISO-8859-1转换得到的字符串,那我们就得到这个字符串还原为ISO-8859-1的字节,然后再将字节按照正确的UTF-8转换为字符串,这样就得到了正确的字符了,修改Servlet中的代码如下:

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//告诉客户端响应的信息的编码格式是UTF-8

response.setContentType("text/html;charset=UTF-8");

System.out.println("进入Servlet");

String userName=request.getParameter("userName");

userName=new String(userName.getBytes("iso-8859-1"),"UTF-8");

System.out.println(userName);

PrintWriter out=response.getWriter();

out.print("您要验证的用户名是:"+userName+",该用户名可以使用");

}

客户端响应为:

6. 试一试将提交方式改成POST方式

在ajax.js文件中添加一个函数,该函数专门用于提交POST请求

/**

*

* @param url 要提交的URL

* @param submitData 要提交的数据

* @param callBack 回调函数

* @return

*/

function doPost(url,submitData,callBack){

var request=createXmlHttp();

request.onreadystatechange=function(){

if(request.readyState==4 && request.status==200){

//注意我们定义回调函数的时候要多加一个参数接收返回的数据

callBack(request.responseText);

}

};

request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

request.open("POST",url);

request.send(submitData);

}

修改页面上的javaScript代码:

<script type="text/javascript" src="ajax.js"></script>

<script type="text/javascript">

function checkUserName(tagID){

//获取文本框中输入的值

var userName=document.getElementById(tagID).value;

//data是从服务端返回来的数据

doPost("ajax.do","userName="+userName,function(data){

document.getElementById("warning").innerHTML=data;

});

}

</script>

当我们发送post请求的时候,尽管我们为请求头设置了

application/x-www-form-urlencoded,但是发送的数据并没有进行URL编码,而传统的将form表单的提交方式设置成post,在提交的时候会自动进行URL编码。

所以Ajax中的post请求时将数据原封不动的传递到了服务器上,所以只需要调用reqeust.setCharacterEncoding() 设置正确的编码集后,就可以取出数据了。

7. 最佳解决方案

前面的方式我们虽然分别解决了GET方式和POST方式的中文问题,但是需要分开进行处理,并且对于不同的服务器,默认的编码集是不同的,这样对于GET方式我们进行的手工转码就不能通用了。

那么不管是Get请求还是POST,有没有可以统一的解决方案?我们可以做如下的处理:

 

将提交的数据使用javaScript的encodeURI()进行两次URL编码

 

服务端进行一次URL 解码即可

 

这种方式的优点是与客户端网页的编码集无关,与服务器的默认编码集无关,而且能够兼容几乎所有的浏览器。

下面以GET方式为例来理解分析全过程:

修改javaScript代码为:

<script type="text/javascript" src="ajax.js"></script>

<script type="text/javascript">

function checkUserName(tagID){

//获取文本框中输入的值

var userName=document.getElementById(tagID).value;

//data是从服务端返回来的数据

var url="ajax.do? userName="+encodeURI(encodeURI(userName));

doGet(,function(data){

document.getElementById("warning").innerHTML=data;

});

}

</script>

Servlet代码修改为:

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//告诉客户端响应的信息的编码格式是UTF-8

response.setContentType("text/html;charset=UTF-8");

String userName=request.getParameter("userName");

userName=URLDecoder.decode(userName,"UTF-8");

System.out.println(userName);

PrintWriter out=response.getWriter();

out.print("您要验证的用户名是:"+userName+",该用户名可以使用");

}

运行后,在各种浏览器中都没有出现乱码问题。换成POST方式,也没有出现乱码问题。页面如果换成GBK编码,也没有出现乱码问题.

为什么这种方式没有出现问题,为什么要进行两次 encodeURI?我们只需要跟踪一下提交的数据即可:

假如我们提交的是 “张三”:

①我们第一次进行encodeURI之后的结果为:

%E6%9D%8E%E5%9B%9B

②第二次进行encodeURI之后的结果为:

%25E6%259D%258E%25E5%259B%259B

③我们对比一下两个值,发现第一次URL编码后中间有%,而第二次URL编码后将第一次编码结果中的%替换成了%25,所以最终发送的数据为:

ajax.do?userName=%25E6%259D%258E%25E5%259B%259B

④在服务端的Servlet中,我们通过调用request.getParameter(“userName”)取值的时候,getParameter方法会对%25E6%259D%258E%25E5%259B%259B进行URL解码,解码后的结果为%E6%9D%8E%E5%9B%9B,也就是将%25换成了%,那么此时Tomcat服务器按照默认的iso-8859-1转换的字符串的时候根本就没有做任何变换,还是%E6%9D%8E%E5%9B%9B

⑤当我们再次进行URL解码的时候即: URLDecoder.decode(userName,"UTF-8"),此时去掉其中的%后变成了E69D8EE59B9B,这正好是”张三”的UTF-8编码,所以使用UTF-8码转换成字符串“张三“.

从整个过程看来,这种方式的优势在于与页面的编码无关,也与服务器所使用的编码集无关。我们需要做的只需要将提交的数据(不管是POST的数据还是GET的数据),进行两次encodeURI即可。


引用地址http://www.cnblogs.com/sunxi/p/3849439.html

本文转载自:http://blog.csdn.net/u013863751/article/details/45826229

y
粉丝 0
博文 26
码字总数 0
作品 0
成都
私信 提问
JQuery中Ajax的Post提交中文乱码的解决方案(转)

引言: 在JQuery的Ajax POST请求中,进行请求,其中的中文在后台,显示为乱码,该如何解决呢? 问题的引入: var regid = $('#oregion').combobox('getValue'); //var sname = $('#sname').......

Atom_me
2015/06/02
217
2
jquery的ajax()函数传值中文乱码解决方法介绍

jquery的ajax()函数传值中文乱码解决方法介绍,需要的朋友可以参考下 代码如下: $.ajax({  dataType : ‘json',type : ‘POST',url :‘http://localhost/test/test.do',data : {id: 1, typ......

mdoo
2015/10/07
217
1
java web中中文乱码问题汇总

[关于使用java 进行的javaweb开发时候的中文乱码的解决方法][1] [1]: http://blog.sina.com.cn/s/blog_6cadcce70101ep77.html 如下是其中的内容: 1,jsp页面中文乱码解决办法:文件头部定义...

小老傅
2014/03/07
0
0
Java URL传参中文乱码问题

我们经常会遇到这样的场景:在URL中传递参数,如果该参数为中文,如果设置不当,会出现乱码问题。 URL传参所使用的编码为服务器中设置的编码,而ajax请求的编码为页面编码。 如果不设置tomca...

程序猿之小菜鸟
2015/08/28
504
0
XMLHttpRequest对象的扩展问题

解决XMLHttpRequest请求的缓存问题:增加时间戳 解决AJAX应用的中文问题: 请求数据中包含中文,服务器端程序接收错误导致乱码 1.png 响应数据中包含中文,编码设置错误导致浏览器中看到的结...

小小蒜头
2017/11/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

读书replay《maven实战》.1.20190526

前情提要 maven这个工具用了好久了,但是一直都用的迷迷糊糊的,没有对它进行过系统性的学习,只是知道一些常用的功能怎么实现,所以20190516这一天我从JD购买了徐晓斌老师所著的《maven实战...

wanxiangming
25分钟前
0
0
真实项目案例实战——【状态设计模式】使用场景

什么是状态模式 状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。 状态模式应用场景 1.一个对象的行为取决于它的状态,并且它必须在运行时刻根...

须臾之余
32分钟前
0
0
Java 实现把字符串转换成整数【底层实现】

https://blog.csdn.net/zl18310999566/article/details/80263396

qimh
35分钟前
0
0
IDEA的debugger

1、win下节省内存空间 3、条件断点

一只小青蛙
46分钟前
3
0
炸!亿级数据DB秒级平滑扩容

一步一步,娓娓道来。 一般来说,并发量大,吞吐量大的互联网分层架构是怎么样的? 数据库上层都有一个微服务,服务层记录“业务库”与“数据库实例配置”的映射关系,通过数据库连接池向数据...

编程SHA
52分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部