Ajax中浏览器缓存导致的问题
问题描述:
当XMLHttpRequest对象利用open方法向服务器发送请求的时候,当一次请求成功以后,页面会把请求到的值存放在页面缓存中,当你第二次发送同样的请求的时候。浏览器不会再去服务器重新取值,而是自动去页面缓存中查找。这样导致浏览器获得的永远是哪个第一次请求时获得的值而无法从浏览器中获得新的值.
例如
cachexmlhttp.open("GET","cache",true);但浏览器第二次请求cache的时候,由于这次请求和上次请求的对象是一样的,而且浏览器缓存中已经保存了上次请求的值,所以就不再去请求cache,而是直接从缓存中获取上次保存的值
解决方法
在每次向服务器发送请求的时候,在url里面拼上一个当前时间的时间戳,这样浏览器就会认为每次请求都不一样,就会去向服务器发送请求了
var url="cache";
//为url添加上时间戳
if(url.indexof("?")>=0){
//如果请求的url原来就有参数
url=url+"&t="+(new Date()).valueOf();
} else{
//如果请求的url原来没有参数
url=url+"?t="+(new Date()).valueOf();
}
cachexmlhttp.open("GET",url,true);
关于中文乱码问题
Ajax中文乱码问题分为两种,一种是服务器端返回数据是中文,一种是页面发送到服务器的数据是中文。
先讨论服务器端返回数据是中文的情况。
对于IE6以上的浏览器,这个问题的解决办法就是XMLHttpRequest对象在页面端定义的Charset和服务器端的http响应头的Content-Type中定义的Charset保持一致就不会有问题。
但是对于IE6,所有的事情就变态起来了。即使按照上面的原则同样解决不了问题。这个时候有两个解决问题的办法
方法1
这个方法很诡异,因为它和前面论述的东西是向矛盾的,在IE6中定义的XMLHttpRequest对象在页面端定义的Charset和服务器端的http响应头的Content-Type中定义的Charset都是GB2312的时候,同样会出现乱码。这个时候,把服务器端的http响应头的Content-Type中定义的Charset设置成utf-8就可以解决问题。
方法2
这个是推荐的方法,在IE6中定义XMLHttpRequest对象的时候,只使用MSXML2.XMLHTTP和Miscrosoft.XMLHTTP两个版本的Activex控件来创建就
可以解决这个问题,下面是代码
这是微软推荐的做法。所以通常就这么用了
var activexName = ["MSXML2.XMLHTTP","Miscrosoft.XMLHTTP"];
for (var i = 0; i <activexName.length; i++) {
try{
xmlhttp = new ActiveXObject(activexName[i]);
break;
} catch(e) {
}
}
对于页面端发送到服务器中文导致的乱码问题
当页面段和服务器端使用的编码方式都是GB2312的时候
解决办法是在页面端获取需要发送的字符串,进行两次编码再传送到服务器,代码如下
var userName = document.getElementById("UserName").value;
//但页面请求参数出现中文,在页面端取得参数后进行两次编码。
//然后在服务器端对编码后的内容进行一次解码,就可以解决这个问题。
userName = encodeURI(encodeURI(userName));
在服务器端,对接收到的数据进行一次解码操作就可以解决问题具体操作如下
String old = request.getParameter("name");
//对经过页面端两次编码的参数进行一次解码。避免了中文乱码问题.
String name = URLDecoder.decode(old,"utf-8");
这样问题就得以解决
其中具体的原理分析如下,假设页面端输入的中文是一个“中”,按照下面步骤进行解码
1.第一次encodeURI,按照utf-8方式获取字节数组变成[-28,-72-83],对字节码数组进行遍历,把每个字节转化成对应的16进制数,这样就变成了[E4,B8,AD],最后变成[%E4,%B8,%AD]
2.第二次encodeURI,把数组最后变成[%25E4,%25B8,%25AD]然后就把处理后的数据[%25E4,%25B8,%25AD]发往服务器端当应用服务器调用getParameter方法,getParameter方法会去向应用服务器请求参数
应用服务器最初获得的就是发送来的[%25E4,%25B8,%25AD],应用服务器会对这个数据进行URLdecode操作,URldecode操作和encodeURL操作是相反的操作,处理结果就是[%E4,%B8,%AD],并把这个值返回给getParameter方法
然后再在servlet中调用URLDecoder.decode(old,"utf-8")就可以把数据还原成最初页面发送过来的中文“中”了。
这么在页面两次编码encodeURI(encodeURI(userName));再到服务器用utf8方式解码一次URLDecoder.decode(old,"utf-8");这么麻烦的原因是
,应用服务器自身总会进行一次URLdecode操作,而不同版本的应用服务器解码所用的编码版本又都不一样,如果把数据直接发送到应用服务器
,结果不同版本的应用服务器解码得到的结果是不可预料的,必然得到的是乱码。而这样在页面段两次编码后产生的[%25E4,%25B8,%25AD]无论
结果什么版本的应用服务器解码,产生的结果都是[%E4,%B8,%AD]。这样在servlet那里进行一次URLDecoder.decode(old,"utf-8");就可以得到
正确的结果。