ajax问题总结

在看文章前,先指定一个变量xhr,xhr代表ajax对象。

测试浏览器:ie为ie6,firefox为2,其他的未测试。统称ie6为ie,firefox2为ff。

基本的============================================

1,最经典的就是ie下的缓存问题了。
如果使用的是get,那么在ie下出现缓存问题。导致代码只执行一次。解决办法就是加时间戳或者随机数,使url变为唯一,这样就不会出现ie

下的缓存问题了,或者改为post提交。
xhr.open("get","xxxx.aspx?_dc="+new Date().getTime(),true);


2,ajax对象属性的大小写问题
在w3c浏览器,如ff中,对大小写是敏感。如
if(xhr.readystate==4)这种写法,在ie下是成立的,但是在ff下就行不通了,因为ie不区分大小写,ff是区分大小的。
标准写法为if(xhr.readyState==4),同理还有属性 responseText,responseXML,status。
还有状态转换函数xhr.onreadystatechange,要注意全部为小写


3,ajax状态0问题
有些时候在测试ajax代码的时候,加了 xhr.status==200的判断后,一直不执行xhr.status==200的代码,这个就需要注意了。

xhr.status==200是要通过服务器来浏览,并且服务器页面没有发生错误或者转向时才返回200状态的,此状态和你通过浏览器访问页面时服务器定义的状态一致。

直接拖进浏览器浏览结果或者双击运行html页面的,未发生错误时,此时的xhr.status是0,不是200。

所以可以多加一个xhr.status==0的判断。如下

+展开 -JavaScript
if(xhr.status==200||xhr.status==0){
  alert('ok');
}


直接拖进浏览器浏览结果或者双击运行html页面时,又出现一个问题,如果请求的是xml文件,那想当然的是使用responseXML属性返回xmlDom了,但是在ie返回不了xmlDom属性,解决办法如何呢,看下面的responseXML问题。

4,responseXML问题。
要使用responseXML属性,请求的是xml文件或者设置了响应头为"text/xml"的动态页面了。要注意如果请求的是动态页面,一定不要忘记设置contenttype为"text/xml"!!!!!!!!切记~~~~~~

asp为 response.contenttype="text/html"
asp.net为 Response.ContentType="text/html";
php为 header("content-type:text/xml;");

在ie下有个问题,直接拖进浏览器浏览或者双击运行html预览效果时,请求的即使是xml文件,使用responseXML返回不了xmldom。

大家测试下就知道了,如下
showbo.xml

+展开 -XML
<?xml version="1.0" encoding="utf-8"?>
<showbo>
 <item>1</item>
 <item>2</item>
 <item>3</item>
 <item>4</item>
</showbo>

test.html

+展开 -JavaScript
function getajax(){
  if(window.XMLHttpRequest)return new XMLHttpRequest();
  else if(window.ActiveXObject)return new ActiveXObject("microsoft.xmlhttp");
}
var xhr=getajax();
xhr.onreadystatechange=function(){
  if(xhr.readyState==4){
    if(xhr.status==200||xhr.status==0){
      var doc=xhr.responseXML,item=doc.getElementsByTagName("item");
      alert(item.length);//在ie输出为0,在ff下为4。似乎在ie下未生成xml的树结构,具体原因要问ms了。。
    }
    else alert('发生错误\n\n'+xhr.status);
  }
}
xhr.open("get","showbo.xml?_dc="+new Date().getTime(),true);
xhr.send(null);


解决办法就是使用microsoft.xmldom对象重新建立xml的树结构,如下


+展开 -JavaScript
xhr.onreadystatechange=function(){
  if(xhr.readyState==4){
    if(xhr.status==200||xhr.status==0){
      var doc=xhr.responseXML;
      if(document.all&&xhr.status==0){//为ie并且直接托进浏览器的时重构xml的树结构
        doc=new ActiveXObject("microsoft.xmldom");
        doc.loadXML(xhr.responseText);
        doc=doc.documentElement;
      }
      var item=doc.getElementsByTagName("item");
      alert(item.length);
    }
    else alert('发生错误\n\n'+xhr.status);
  }
}


5,为post提交时需要注意的。

1)如果为post提交时,注意要设置content-type为"application/x-www-form-urlencoded",这样在动态页才可以使用request/request.form/request.querystring对象通过键获取值,否则得使用2进制数据,然后自己分析2进制数据生成字符串对象,使用正则什么的获取对应的值。

2)需要在open以后才能使用xhr.setRequestHeader方法,否则出错。
xhr.open("post","xxxx.aspx",true);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");//这里。。。。

 

6.还有一个问题忘记总结了,跨域的问题
如果请求的页面不是当前站点的,那就跨域了,最好的解决方案就是服务器端的xhr请求

可以参考下面的的解决方案
AJAX跨域问题解决办法

不久前放出的一个
使用alexa,google的api获取alexa排名和google  pr,分别使用了客户端和服务器端的xhr请求
中就是使用了服务器端的xhr请求,应为请求的是Google和alexa的页面,所以跨域了,需要使用服务器端的xhr请求。


乱码问题============================================

对于ajax应用来说,乱码也是一个经常出现的问题。
1)meta声明的charset要和请求的页面返回的charset一致。最好在请求的页面中再设置下输出编码。
asp: response.charset="gb2312或者utf-8"
asp.net: response.charset="gb2312或者utf-8"
php: header("charset=gb2312或者utf-8")

2)文件物理存储编码要和meta声明的编码要一致。如meta指定为gb2312,则物理存储编码为ansi。如果为utf-8,则要存储为utf-8编码。

对于asp,如果指定编码为utf-8,记得还要设置

'防止asp使用utf-8编码时中文出现乱码

+展开 -VBScript
Session.CodePage=65001
Response.CharSet="utf-8"

因为asp在国内服务器默认处理编码为gb2312


对于asp.net的话,meta设置为gb2312时,最好设置web.config文件中的

+展开 -XML
<globalization requestEncoding="gb2312" responseEncoding="gb2312"/>

,并且在输出中文前设置Response.CharSet="gb2312";

因为asp.net默认的编码为utf-8

3)发送中文到动态页面时使用escape/encodeURI/encodeURIComponent编码一下。建议使用encodeURIComponent。

更多的js编码信息查看这篇文章

JS URL编码函数

对于php来说,还有个问题,需要在服务器点解码下。可以看这篇文章里面的讨论。

写了一个php查询,但是就是传不出中文。


4)如果1-2都对上了但是在接受服务器端发送的信息时还是出现乱码,试试用XML作为信息载体,然后使用responseXML分析下回传的xml文件。因为ajax原本就是用xml作为信息载体的。。。。。。ajax英文名原本就是“异步javascript和xml”【asynchronous javascript and xml】


如果不会解析xml文件,可以参考这篇文章

JavaScript解析XML的方法总结


下面是一些csdn上出现乱码的文章和解决办法,还未解决的看看,是否和你的如出一辙。

在FireFox浏览器中asp.net+AJAX传输的中文字符串到服务器端后乱码的问题!!!!
请教ajax返回乱码

就列上面两个了,要查找更多的,查看这个查询连接,都是ajax出现乱码的问题。
http://so.csdn.net/bbsSearchResult.aspx?q=ajax+%e4%b9%b1%e7%a0%81&p=0

 


同步问题============================================问题描述如下,问题来自http://topic.csdn.net/u/20090630/16/d4d07596-65da-430c-8e89-cae60e25e03c.html,精简了下创建ajax的代码


+展开 -JavaScript
function callServerByPost(url,data,fun) {
        var http_request=null;    
        if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); 
        }else if (window.XMLHttpRequest)  http_request = new XMLHttpRequest();
        if (!http_request) {
            alert('Giving up :Cannot create an XMLHTTP instance');
            return false;
        } 
        http_request.onreadystatechange = fun; 
        http_request.open("POST", url, true);
        http_request.setrequestheader("Content-length",data.length);
        http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
 
    http_request.send(data);//传送资料
}

function ajax_post(url,data) {
    url=url+"?t="+new Date();
    callServerByPost(url,data,function fns(){        
        if(http_request.readyState == 4) {     
            if (http_request.status == 200) {
                return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到
              } else {
              alert("你请求数据有错");
              }
        }
});   
}

function getData(){
   var url="ajax_server.aspx";
   var data="name=ljp&pwd=ljp";
   var t=ajax_post(url,data);
   alert(t);//在这里弹出undefined =============================
}


为什么会出现这个问题呢??因为在执行getData中的代码var t=ajax_post(url,data);时,由于指定了异步,所以callServerByPost中的http_request.send(data);//传送资料 这句话并不会中断其他js代码的执行,所以会继续执行getData中的下一句代码,就是alert(t),所以会出现undefined。

其实呢并不仅是ajax异步导致出现undefined的问题。认真看下代码var t=ajax_post(url,data);,t变量是接受的是ajax_post的返回值,但是ajax_post函数中并未使用return 返回任何值,所以默认是返回undefined。

你会说我这里不是使用了return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到返回了吗??????????

大家看清楚了,那个是状态转换函数,你返回任何值是没有意义的,他只是处理ajax的状态,你返回值给谁用的呢?????是不是。

如何解决这个问题呢?

一种是改为同步发送
一种就是为异步时使用全局变量来接受ajax的返回值,在状态转换函数中给全局变量赋值。


使用异步+全局变量时要注意的是在ajax未返回前千万不用使用全局变量,要不还是undefined。

下面给出同步的解决办法。异步+全局变量的解决方法看这篇文章

为什么数组作为参数传递进去取不了值出来?


+展开 -JavaScript
function callServerByPost(url,data,fun) {
        var http_request=null;    
        if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); 
        }else if (window.XMLHttpRequest)  http_request = new XMLHttpRequest();
        if (!http_request) {
            alert('Giving up :Cannot create an XMLHTTP instance');
            return false;
        } 
       // http_request.onreadystatechange = fun;  //为同步时不再需要处理函数了。。。。。。。
        http_request.open("POST", url, false);//改为同步
        http_request.setrequestheader("Content-length",data.length);
        http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
 
    http_request.send(data);//传送资料
return http_request.responseText;//同步时可以直接返回,因为会阻止其他的代码执行
}

function ajax_post(url,data) {
    url=url+"?t="+new Date();
    return callServerByPost(url,data,null);//不需要传递回调,并且直接返回callServerByPost的返回值
  
}

function getData(){ 
   var url="ajax_server.aspx";
   var data="name=ljp&pwd=ljp";
   var t=ajax_post(url,data);
   alert(t);//这里就不会输出undefined了。。。。。。。。。。。。,不过如果网路慢的话,浏览器就假死了。。
}


下面这篇是介绍ff和ie状态转换的异同的,有兴趣的参考下

Firefox下的AJAX onreadystatechange问题

 

最后放一个自己写的ajax类库~~~~~O(∩_∩)O哈哈~~~~~完毕


+展开 -JavaScript
String.prototype.trim=function(){return this.replace(/$\s*|\s*$/g,'');}
var Showbo={author:'showbo'};
//获取json对象
Showbo.getJson=function(v){if(typeof(v)=='string')return eval('('+v+')');else return v;}
//根据id获取对象
Showbo.$=function(Id){if('object'==typeof(Id))return Id;else if('string'==typeof(Id))return document.getElementById(Id);else return null;}
Showbo.IsIE=!!document.all;
//扩展IE下的XMLHttpRequest
if(Showbo.IsIE&&!window.XMLHttpRequest)window.XMLHttpRequest=function(){
  var acX=['msxml2.xmlhttp.5.0','msxml2.xmlhttp.4.0','msxml2.xmlhttp.3.0','msxml2.xmlhttp','microsoft.xmlhttp'],Xhr;
  for(var i=0;itry{Xhr=new ActiveXObject(acX[i]);return Xhr;}catch(e){}
  return false;
}
//ajax应用池
Showbo.Ajax={
  pools:[]//存储ajax对象的数组
  ,getObject:function(){//从数组中获取ajax对象,如果未返回则新建一个ajax对象
    for(var i=0;i<this.pools.length;i++)
      if(this.pools[i].readyState==0||this.pools[i].readyState==4)return this.pools[i];
      this.pools[this.pools.length]=new XMLHttpRequest();
      return this.pools[this.pools.length-1];
  }
  ,send:function(cfg){/*cfg示例 
    {
    
url:'请求的页面'
    ,params:'键值对,注意不是json对象'
    ,method:'post/get,如果为指定则默认为get'
    ,success:成功时的回调函数
    ,failure:失败时的回调函数
    ,otherParams:提供给回调函数的其他参数,可以为json对象
    }
   
    成功或者失败的回调函数参数为  (当前的xhr对象,配置文件的中的otherParams)
    */
    if(!cfg||!cfg.url)throw("未设置配置文件!");
    var method=cfg.method,asy="boolean"==typeof(cfg.asy)?cfg.asy:true;
    if(!method||method!="post")method="get";
    if(method.toLocaleLowerCase()=='get'){
      var _dc=new Date().getTime();//加时间戳防止ie浏览器下的缓存
      cfg.params=cfg.params?cfg.params+'&_dc='+_dc:'_dc='+_dc;
      if(cfg.url.indexOf("?")!=-1)cfg.url+="&"+cfg.params;
      else cfg.url+="?"+cfg.params;cfg.params=null;
    }
    else if(!cfg.params)cfg.params='';
    var o=this.getObject();
    if(!o)throw("未能创建ajax对象!");
    o.open(method,cfg.url,asy);
    if(method.toLocaleLowerCase()=='post')o.setRequestHeader("content-type","application/x-www-form-urlencoded");
    o.send(cfg.params);
    o.onreadystatechange=function(){
      if(o.readyState==4){
        if(o.status==200||o.status==0){
          if("function"==typeof(cfg.success))cfg.success(o,cfg.otherParams);
        }
        else if("function"==typeof(cfg.failure))cfg.failure(o,cfg.otherParams);
      }
    }
  }
}

 

 

在responseXML问题。这块中您谈到在“ie输出为0,在ff下为4。似乎在ie下未生成xml的树结构,具体原因要问ms了” 但是我的项目中的结果却是反的,在ie下正常输出为2,ff下始终为0。我仔细检查了大小写都没有问题。ajax的代码为
var xmlHttpRequest;
function createXmlHttpRequest(){
if(window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}
}
function haoLeJiaoWo(){
if(xmlHttpRequest.readyState == 4){
if(xmlHttpRequest.status == 200){
var str = xmlHttpRequest.responseXML;
//解析XML
var inStr="<option>请选择手机型号</option>";
var ele=str.getElementsByTagName("ret");
alert("Array length is"+ele.length);
for(var i=0;i<ele.length;i++)
{
var opt=ele[i].text;
inStr+="<option value="+opt+">"+opt+"</option>";
}
alert(inStr);
document.getElementById("my").innerHTML="<select id=myModel>"+inStr+"</select>";
}
}
}
function show(){
var brand = document.getElementById("myBrand").value;
var url = "/dft/phoneModel.do?operate=getModelByBrand&myBrand=" + brand;
xmlHttpRequest = createXmlHttpRequest();
xmlHttpRequest.onreadystatechange = haoLeJiaoWo;
xmlHttpRequest.open("POST",url,true);
xmlHttpRequest.send(null);
}
但是在ff中输出的结果始终为0 var inStr="<option>请选择手机型号</option>";
var ele=str.getElementsByTagName("ret");
alert("Array length is"+ele.length);

望您给个解答...


管理员回复(2009-7-8 21:56:01)
你生产的xml是什么格式的了?方便的话贴出来看看。
你请求的是动态页,是否设置了相应头为“text/xml”?

并且你可以输出responseText看看是否返回了正确xml格式的字符串


+展开-JavaScript
if(xmlHttpRequest.status == 200){
var str = xmlHttpRequest.responseXML;
alert(xmlHttpRequest.responseText)//=========<br/><br/><br/>

标签: 页面, XML, AJAX, utf, status

AJAX乱码解决大全【精】


1、编码
      
编码比较常用的有:UTF-8GBKGB2312ISO-8859-1,除了iso-8859-1之外的其它三个编码都能很好的支持中文,但它们都兼容ISO-8859-1的编码(就是说无论编码怎么改变,只要是ISO-8859-1中的字符,永远不会出现乱码)。
     
这四种编码中,GB2312是中国规定的汉字编码,也可以说是简体中文的字符集编码;GBKGB2312的扩展,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名;UTF-8虽然也支持中文,但却GB码不兼容(编码值不同)UTF-8使用的是可变长的UNICODE编码,编码可能是116进制(即ISO-8859-1中的字符,其编码也是相同的)也有可能是2位或3位的16进制。UTF-8的优点是:1CPU字节顺序无关,可以在不同平台之间交流。2、容错能力高,任何一个字节损坏后,最多只会导致一个编码码位损失,不会链锁错误(GB码错一个字节就会整行乱码),所以在国际化处理中基本都是建议使用UTF-8作为编码。

2、文件的编码
     
文件编码最常使用的有两种:ANSIUTF-8,光看名字估计你都可以猜到了,ANSI就是我们保存文件时使用的默认编码,而UTF-8则需自己设置。对于编码的改变,我使用的工具是NOTEPADECLIPSENOTEPAD使用最简单,只要打开文件后在另存为中选择相应的编码就行了,而且它对编码的支持非常好;而在ECLIPSE中,只要稍微设置一下就行了,打开首选项,然后选择:常规->内容类型(ContentType),在右边选中你想改变保存编码的文件类型,然后在下方的缺省编码中改变其值,最后点击更新(UPDATE)按钮即可。


而在其它的编辑器中,默认保存的内容都是GB2312或者GBK(NOTEPAD中对应ANSI).而根据前面所说的UTF-8和GBK,GB2312等 的编码值是不同的这一点,可以知道,如果文件使用了UTF-8,那么字符编码就必须使用UTF-8,否则编码值的不同就可能造成乱码。而这也就是为什么那 么多的人使用了UTF-8编码后还会产生乱码的根本原因。(JS和JSP都是这个道理)
3、JSP,STRUTS等的中文乱码解决方案
     其实解决的方法只有一个:

request.setCharacterEncoding(encoding);

    方法只有一种,但处理方式就多种多样了,初学者会在JSP页面上直接使用,而有经验的程序员会使用过滤器。而现在所要说的方法也是过滤器。这里以统一使用 UTF-8作为编码作为例子说明。具体过程就不多说了,网上有很多教程。偷懒一点的,到TOMCAT中复制就行了。在TOMCAT的目录下 的"webapps"jsp-examples"WEB-INF"classes"filters"找到 SetCharacterEncodingFilter.java 这个类,放到你的程序中并配置好映射路径。配置好后基本上你的乱码问题就解决了。但要映射路径中需要注意的就是不能使用 '*'

  <filter-mapping>
    
<filter-name>Set Character Encoding</filter-name>
    
<servlet-name>*</servlet-name>
  
</filter-mapping>

像上面这样配置的话(可能也是网上大多教程的做法,想当年也是害苦了我),可能你只有JSP的乱码解决了,要解决STRUTS的乱码需要映射 *.do 或者 servletActionName。然后在初始化参数中设置encoding的值就行了。

<init-param>
      
<param-name>encoding</param-name>
      
<param-value>UTF-8</param-value>
</init-param>

当然,最重要的是要记得根据前面所说的方法,改变你所使用的编辑器保存文件的编码要与使用的字符编码一致。
而在JSP内容中,还是使用如网上教程所说的那种技俩,在所有页面的页首加入:

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding
="UTF-8"%>

至此,相信JSP,ACTION都不太可能出现乱码了。
4、资源文件的乱码解决方案
      资源文件谁都知道是国际化支持不可或缺的一部分,如果资源文件都出现乱码了那还了得?其实资源文件的乱码是很好解决的,其原因也是因为使用了UTF-8做 为JSP编码后,没有相应地改变资源文件的文件编码造成的,所以只要对资源文件保存的编码进行更正后,乱码问题也就解决了。当然,你的中文要使用 native2ascii 命令进行正确的转换。
5、调用JS时,JS内容乱码的解决方案。
     其实JS的乱码还是跟文件的编码有关系的,如果JS中有中文的话,那JS文件保存的编码就必须跟调用此JS的页面编码相同,否则,你的所有中文都要从JSP页面传给JS才会显示正常。可以看出对于调用JS出现的乱码是最容易解决的.

6、AJAX提交数据乱码,返回数据乱码的解决方案

     万变不离其宗,AJAX的乱码问题自然跟编码有关了,其实很多人跟我一样想到了对文件编码进行设置,并且在接数据时设置了requet的编码,在返回的数 据时设置了response的编码一切都以为会很顺利,可是这一切都是徒劳无功的,讨厌的乱码再一次出现在你眼前。在你试了N多种方法,包括JS自身的 escape,unescape方法后,你发现乱码仍然猖狂地出现在屏幕上。
    其实在试过这N多方法后,很多人都没发现,解决的方法其实很简单,而且其答案就在我们之前处理的JSP乱码之中。让我们先看一下AJAX的经典请求代码

xmlhttp.open( "post", url, async );
xmlhttp.setRequestHeader( "Content-Type", "text/html" );
xmlhttp.send( params );

通过前面的说明,不知道你现在看出端倪了没有。不知道是受了网上教程的影响还是其它方面影响,setRequestHeader并是万年不变的,也没人想过去改它,而问题就正好出在这个地方。回想一个JSP页面内容的编码设置,其中有这么一节:

contentType="text/html; charset=UTF-8"

现在知道问题了吧,所以我们要把第二句代码改为:

xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=UTF-8" );

如果提交的是form,那么设置为"application/x-www-form-urlencoded; charset=UTF-8"

最后别忘了在返回数据时也设置上:

response.setContentType( "text/xml" );
response.setCharacterEncoding( "UTF-8" );

如果要问为什么的话,其实我们可以把xmlhttp看成是一个临时页面,它由浏览 器动态生成,主要作用是在后台获得请求的数据(可以看成是一个高级的iframe)。所以对于普通页面设置的编码,对它也要同样设置。而在servlet 中返回数据为什么要设置contentType和encoding其道理也是一样的。众所周知,jsp的最后形态就是servlet,而jsp页首设置的 那个内容其实也就是让生成的servlet中生成这么两句话:

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

而pageEncoding则是跟jvm说明了这个页面的内容要使用什么编码保存(这跟之后生成的CLASS有关系)。所以在servlet设置response的编码也是理所当然的了。

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

response.setHeader("Pragma",   "no-cache");   //HTTP   1.0  

response.setDateHeader("Expires",   0);   //prevents   caching   at   the   proxy   server  

PrintWriter out = response.getWriter();

out.write(outXML);

out.flush();

out.close();

OK!这样向客户端写的数据中的中文也是UTF-8编码了,客户端js脚本获取到request.responseXML也好,responseText也好,里面的数据都不会有乱码了


标签: 乱码, 编码, utf, jsp

ajax中文乱码完美解决(兼容ie ff)

AJAX的中文乱码可以大概分为两中,第一种是向服务器端发送中文参数时 (xmlhttp.open(“get|post”,url,true)),服务器端接收到的为乱码,这个也是我今天遇到的问题,没做处理之前,在IE里 是正常的,但是在Firefox里面就出现了乱码,我先把接收到参数输出到一个文本里,没有发现什么问题,郁闷了,然后我就把查询语句在输出来观察(我这 里是要从数据库里查出与参数相关的东西),终于发现问题,IE和Firefox输出的参数不一样,虽然汉字上都一样,但是和前后连接上有细小的区别,于是 认定了是编码问题,在网上查找了相关资料,都没能解决问题,但是得到一些启示,因为AJAX发送数据都是采用UTF-8编码的方式发送的,所以要在服务器 端进行编码转换(我这里页面是采用GB2312编码的,如果是采用UTF-8的话应该不会有这步的问题),所以我在服务器端进行了UTF-8转 GB2312,

 

$str=iconv("UTF-8","GB2312",$str);

 

然后测试,在Firefox上顺利解决了问题,以为大公告成了,可是再到IE下测试,发现IE又出现了问题,服务器端接收到的参数没值,这下就郁闷 了,突然看到发送头设置了setRequestHeader("Content-Type","application/x-www-form- urlencoded");,就找到问题所在了,然后就在发送那里进行了参数编码:

 

geturl=encodeURI(geturl);

       geturl=encodeURI(geturl); //两次也可以写成geturl=encodeURI(encodeURI(geturl));

xmlhttp.open("GET",geturl,true);

 

然后再到服务器端进行URL解码:

 

   $str=urldecode($str); //解码

$ str =iconv("UTF-8","GB2312",$ str); //编码转换

 

   注意:解码必须在编码转换前面,不然得不到正确值

 

保存测试,IE和Firefox都能正常了。

 

第二种就是服务器端向客户端输出中文时出现乱码,这类问题网上的答案就比较多了,也都能解决,为了避免各位再去查找,我在这里就COPY下J

 

原因:AJAX在接收responseText或responseXML的值的时候是按照UTF-8的格式来解码的,如果服务器段发送的数据不是UTF-8的格式,那么接收responseText或responseXML的值有可能为乱码。


    解决办法:

 

    在服务器指定发送数据的格式:
    在jsp文件中:
    response.setContentType("text/text;charset=UTF-8");//返回的是txt文本文件
    或是
    response.setContentType("text/xml;charset=UTF-8");//返回的xml文件

     PHP:header('Content-Type:text/html;charset=GB2312');
     ASP:Response.Charset("GB2312")
     JSP:response.setHeader("Charset","GB2312");

Struts+Hibernate+MyEclipse+Tomcat+MySQL的乱码之解决篇

在系统中出现乱码一般是编码设定和编码转换问题,那么我们来看看当中有多少编码设定和编码转换的呢?



显示界面,JSP 2.0      

JAVA容器:Tomcat 5.X

MVC构架:Struts 1.2

ORM工具:Hibernate 3

数据库:MySQL   5.0

编译IDE:MyEclipse 5.0



知道了有六个地方要设定编码,那么哪种编码最好呢?使用中文可以GBK,但我认为UTF-8会是更好的选择,如果想知道了解编码的更多细节,请访问:

计算机编码大全-A

计算机编码大全-B



好现在选定UTF-8,在上面的这六个地方一一设定吧:



显示界面,JSP

       在页面的开头加入或修改成:<%@ page language="java" pageEncoding="utf-8"%> 红色部分为要设定部分。



JAVA容器:Tomcat

       本人参照某兄台的之作:Tomcat中文编码问题解决方案(简) 有兴趣可以进去看看。

       下面开始设定,在Tomcat安装目录下的conf文件打开Server.xml文件,找到相应段落并更改成以下字样:

       <Connector port="8080" maxThreads="150" minSpareThreads="25"

maxSpareThreads="75" enableLookups="false" redirectPort="8443"

acceptCount="100" debug="0" connectionTimeout="20000"

        disableUploadTimeout="true"  URIEncoding="utf-8"/>

       红色部分为要设定部分。



MVC构架:Struts

       在这里添加一个字符集的Fliter,代码如下:

package com.ruder.filters;

//上面的包名表示你把这个Fliter文件放在哪个包中,在下面的Web.xml也要相应改动。
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}

下面是对Web.xml的配置:

<filter>

                   <filter-name>Set Character Encoding</filter-name>

                           <filter-class>com.ruder.filters.SetCharacterEncodingFilter</filter-class>

                   <init-param>

                           <param-name>encoding</param-name>

                          <param-value>UTF-8</param-value>

                </init-param>

      </filter>

       <filter-mapping>

                           <filter-name>Set Character Encoding</filter-name>

                   <url-pattern>
21    public void init(FilterConfig arg0) throws ServletException {
22        // TODO Auto-generated method stub
23        this.filterConfig = arg0;
24        this.defaultEncoding = filterConfig.getInitParameter("defaultencoding");
25    }
26
27   
30    public void doFilter(
31        ServletRequest request,
32        ServletResponse response,
33        FilterChain chain)
34        throws IOException, ServletException {
35        // TODO Auto-generated method stub
36        request.setCharacterEncoding(selectEncoding(request));
37        chain.doFilter(request, response);
38    }
39
40
41    public void destroy() {
42        
43        this.defaultEncoding = null;
44        this.filterConfig = null;
45    }
46
47
48    protected String selectEncoding(ServletRequest request) {
49
50        return this.defaultEncoding;
51    }
52
53}


4.提交表单的jsp页面设置
<%@ page language="java"  contentType="text/html; charset=UTF-8"%>




至此问题已经解决,但是还有一些我们应该了解的,下面我简述一下:

为 每个jsp页面设置了其编码格式(utf-8),但传递数据到另一页面时依然显示为乱码?  首先要需要了解的是web容器默认编码是iso- 8859-1,一个汉字占用两个字节,而在utf-8中一个汉字占用三个字节。所以在数据传递过程中,必须手动设定容器编码格式,否则会出现字符位丢失的 情况。即3个字节变为两个字节,自然会变成乱码。为什么保存到数据库中的数据都变成了乱码?  原理同上,首先要搞清楚使用的数据库默认的编码格式,比如 mysql默认的字符编码是ISO-8859-1。所以必须手动修改其默认编码格式。  清楚了以上问题后,再来看如何解决utf-8的乱码问题。

1. 设置web容器的编码格式。为你的servlet的doGet或doPost方法开始处加入如下代 码:request.setCharacterEncoding("utf-8");   response.setCharacterEncoding ("utf-8");

2.为每个jsp页面指定其编码格式。<%@ page pageEncoding="utf-8"%>

3.在连接数据库用的URL后加入:useUnicode=true; characterEncoding=utf-8 如: url="jdbc:mysql:///db1?useUnicode=true; characterEncoding=utf-8"

4.为指定数据库默认编码格式。在C:\WINDOWS目录下找到my.ini文件,并在 [mysqld]中加入default-character-set=gbk,重新启动mysql服务。 

至此,乱码问题全部解决。

起初总搞上去不清,为什么要将mysql的默认编码格式设置为gbk,后来由相关的资料得知utf-8默认输入编码方式为gbk,默认输出编码方式为utf-16be。  

个 人认为,将数据进行utf-8进行编码的目的(即将中文编码为%的形式),主要是为了在多层服务间进行数据传输时,防止发生字符丢失(如msn)。普通的 web程序显然没有必要这样做,只要使用以上方法进行处理,就可以有效的解决乱码问题,从而结省存储空间。如果都像公司的SC系统那样,将一个汉字编码为 18个字符后,再存储到数据库中,抛开效率不说,就存储空间的浪费就够人受的,要知道,那是需要银子地!

完美解决PHP中文乱码问题

  一.首先是PHP网页的编码

  1.php文件本身的编码与网页的编码应匹配

  a.如果欲使用gb2312编码,那么php要输出头:header(“Content-Type: text/html; charset=gb2312"),静态页面添加,所有文件的编码格式为ANSI,可用记事本打开,另存为选择编码为ANSI,覆盖源文件。

  b.如果欲使用utf-8编码,那么php要输出头:header(“Content-Type: text/html; charset=utf-8"),静态页面添加,所有文件的编码格式为utf-8。保存为utf-8可能会有点麻烦,一般utf-8文件开头会有BOM, 如果使用 session就会出问题,可用editplus来保存,在editplus中,工具->参数选择->文件->UTF-8签名,选择总 是删除,再保存就可以去掉BOM信息了。

  2.php本身不是Unicode的,所有substr之类的函数得改成mb_substr(需要装mbstring扩展);或者用iconv转码。

  二.PHP与Mysql的数据交互

  PHP与数据库的编码应一致

  1.修改mysql配置文件my.ini或my.cnf,mysql最好用utf8编码

  [mysql]

  default-character-set=utf8

  [mysqld]

  default-character-set=utf8

  default-storage-engine=MyISAM

  在[mysqld]下加入:

  default-collation=utf8_bin

  init_connect='SET NAMES utf8'

  2.在需要做数据库操作的php程序前加mysql_query("set names '编码'");,编码和php编码一致,如果php编码是gb2312那mysql编码就是gb2312,如果是utf-8那mysql编码就是 utf8,这样插入或检索数据时就不会出现乱码了

  三.PHP与操作系统相关

  Windows和Linux的编码是不一样的,在Windows环境下,调用PHP的函数时参数如果是utf-8编码会出现错误,比如 move_uploaded_file()、filesize()、readfile()等,这些函数在处理上传、下载时经常会用到,调用时可能会出现下 面的错误:

  Warning: move_uploaded_file()[function.move-uploaded-file]:failed to open stream: Invalid argument in ...

  Warning: move_uploaded_file()[function.move-uploaded-file]:Unable to move '' to '' in ...

  Warning: filesize() [function.filesize]: stat failed for ... in ...

  Warning: readfile() [function.readfile]: failed to open stream: Invalid argument in ..

  在Linux环境下用gb2312编码虽然不会出现这些错误,但保存后的文件名出现乱码导致无法读取文件,这时可先将参数转换成操作系统识别的 编码,编码转换可用mb_convert_encoding(字符串,新编码,原编码)或iconv(原编码,新编码,字符串),这样处理后保存的文件名 就不会出现乱码,也可以正常读取文件,实现中文名称文件的上传、下载。

  其实还有更好的解决方法,彻底与系统脱离,也就不用考虑系统是何编码。可以生成一个只有字母和数字的序列作为文件名,而将原来带有中文的名字保 存在数据库中,这样调用move_uploaded_file()就不会出现问题,下载的时候只需将文件名改为原来带有中文的名字。实现下载的代码如下

  header("Pragma: public");

  header("Expires: 0");

  header("Cache-Component: must-revalidate, post-check=0, pre-check=0");

  header("Content-type: $file_type");

  header("Content-Length: $file_size");

  header("Content-Disposition: attachment; filename=\"$file_name\"");

  header("Content-Transfer-Encoding: binary");

  readfile($file_path);

  $file_type是文件的类型,$file_name是原来的名字,$file_path是保存在服务上文件的地址。