java web 乱码解决心得

 

关于jsp,ajax乱码问题网上可以搜集到一堆资料,可是大部分都是在讲如何应用。我这里主要说下我个人理解的浏览器端与服务器端乱码问题的根源与原理。

 

   首先,要说明的是服务端(如:tomcat)与浏览器端(如:ie)底层实现都是基于socket通信的(不了解的朋友可以自己去学习下socket  )。那么好的,如果各位自己实现socket通信的话肯定会也会处理这个编码问题。例如,我自己写个socket实现,我规定socket两端都采用"UTF-8"编码,那么两端的消息接收肯定不会出现乱码问题了。好的进一步扩展,如果我socket两端都不限定编码,并且socket客户端访问服务端接收到消息后便暂时关闭。那么各位该如何制定消息接收完毕,消息发出,编码等一系列规则呢(恐怕大家到这里就想到了这不就是http协议吗 )。哦继续,那么现在我们就可以吧浏览器端(如ie)看成一个socket的客户端,服务器端(如tomcat)就是一个socket服务端(大家记好这里 socket客户端就是指 浏览器,socket服务端就是指的  服务器,以后我可要用了啊)。

 

   进入正题,首先说页面显示,浏览器socket客户端接收到服务端的数据内容,那么客户端如何知晓服务端发送的内容需要用什么编码格式展示呢。http协议规定,根据接收到的<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">中的编码格式来显示页面的。,哈哈大家知道了吧,如果你自己写一个http socket客户端那么我们也是一定也是这样那么如果你的页面后台编码不是charset这里规定的格式,那么能不能正常显示到浏览器页面那么只能够听天由命了。注意,这里要说明的是:

 

response.setContentType("text/html;charset=gb2312")是设置页面中为gb2312编码,设置页面静态文字  
response.setContentType指定 HTTP 响应的编码,同时指定了浏览器显示的编码.  
response.setCharacterEncoding设置HTTP 响应的编码,如果之前使用  
response.setContentType设置了编码格式,则使用  
response.setCharacterEncoding指定的编码格式覆盖之前的设置.  
与response.setContentType相同的是,调用此方法,必须在getWriter执行之前或  
者response被提交之前.  
  
另外需要说明的是  
response.setContentType("text/html; charset=UTF-8");与页面中  
<meta http-equiv="Content-Type" content="text/html; charset=GBK">  
作用相同。  
但如果response.setContentType("text/html; charset=UTF-8");与页面中  
<meta http-equiv="Content-Type" content="text/html; charset=GBK">  
中都存在,则以response.setContentType("text/html; charset=UTF-8");为  
主.  
 

 

 

        然后说大家遇到比较多的问题,request.getParameter("")获得的结果为乱码这个问题。服务端根据http协议是通过“URL编码”来获得客户端socket提交的信息的。如果不懂“URL编码”,大家这里http://baike.baidu.com/view/204662.htm ,我这里给大家解释下,

看一个简单页面:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title>Insert title here</title>
</head>
<body>
<form action="TestPostContent.jsp" method="post">
  <label for="username">username</label><input type="text" name="username" /><br/>
  <label for="password">password</label><input type="text" name="password" /><br/>
  <button type="submit">submit</button>
</form>
</body>
</html> 

 

 那么这个post 方式的 form表单里面的两个值是如何发送到后台的呢,

  需要先将这两个input的值转化为GBK编码(转化为GBK编码的原因过会再说),然后在将结果在进行“URL编码”,

例如我们发送的两个值分别是 username=你好  ,password=你好 .那么最后提交的数据内容就会是

username=%C4%E3%BA%C3&password=%C4%E3%BA%C3。至于具体过程还要大家多多理解下“URL编码”.

 

这里是个重点大家要记清楚:http post提交的表单内容信息通过“URL编码”发送给服务端。

 

    这里说说为什么要用GBK对上面那个表单编码,这里恐怕大家同样也猜到了<meta http-equiv="Content-Type" content="text/html; charset=GBK">,对就是这里,

http协议的规定post提交的内容根据Content-Type的字符编码类型进行编码。

稍微做个总结:post提交的数据编码格式根据Content-Type,编码后在进行“URL编码”,然后发送给服务端.

 

    那么到了这里该说说get方式的提交了,或者说 url地址栏的内容信息提交(不懂这里说的get方式,只能自己补下了)

好的,这里大家可以这么考虑(实际上也是这样),url地址栏的内容是可以手动输入的,那么这里url的编码便于操作系统环境有关系了,例如:中国的xp用户 编码格式为GBK,中国台湾的xp用户 编码格式为BIG5。而浏览器中socket便直接将url地址栏里面的内容提交上去了,什么操作转码啊都没有进行。哦,说到这里,大家恐怕也理解了为什么不同浏览器get提交的编码格式不同(环境不同,默认编码不同)。

 

  OK说说服务端接收信息的方式,即:request.getParameter("").  服务端socket根据http协议(我自己的理解),接收到信息之后,首先进行一次url解码(url编码的反过程)。这个在tomcat解码默认为iso-8859-1.  这里还要说明一点,comcat中 如果设置了request.setCharacterEncoding("utf-8"),那么post提交的数据解码过程便是根据utf-8,但是这个request.setCharacterEncoding("utf-8")并不对get提交的数据内容起作用(为什么,默认如此,我也不知道)。 

 

 

  好的综上所述,做个总结:

     1.客户端浏览器显示页面的编码根据<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">,否则如果没有设置这个地方的编码,便与浏览器有关。

     2.客户端浏览器get提交的数据url中是什么样子,那么后台获得的便是什么样子。例如:浏览器默认环境对url是GBK编码,那么服务器端获得的内容便是GBK编码。

    3.post提交的数据编码格式根据Content-Type,编码后在进行“URL编码”,然后发送给服务端.。同上,如果没有设置这个地方的编码格式,编码格式便与浏览器有关。

 

 

     4.服务端request.getParameter("")接收数据,首先进行一次解码(不管是什么数据类型,都要解码   既:               URLDecoder.decode(url,charset))

     其中如果是get方式提交的数据,这里的charset便是与服务器默认有关了例如:tomcat解码默认为iso-8859-1.

     如果是post方式提交的数据,这里charset的值获得方式为如下两步:

               (1)request.getCharacterEncoding("utf-8"),如果获得的编码格式不为空,好的,解码用这种格式(不走第二步了)如果获得的编码格式为空,好的只能进行第二步了

               (2)   与服务器默认post解码格式    例如:tomcat解码默认为iso-8859-1.

 

 

    5.服务端与客户端分开看,它们各自拥有着自己的编码格式。至于怎么编码,就是我上面做的总结了。

 

     大家在遇到乱码问题是,多多考虑以上几条。

 

 

      另外着重说明:ajax post提交的数据么有进行“URL编码”.(为什么这么实现,我也不清楚 ,我在想如果浏览器进行了url编码,我们做ajax实现不就省事了吗)。这也就是为什么ajax post提交数据时候为什么encodeURI(encodeURI('中文')) 进行两次的原因了(大家自己具体思考下哈。我给大家提个醒,url原始数据old编码一次后,得到的数据假设为 a ,那么 a 全是ascii可以接受的值,在编一次之后得到b,数据b提交到了客户端。那么服务端第一次解析数据b的时候,不管是采用那种URLDecoder.decode(url,charset)编码格式解析,得到的肯定是还是a,因为a是纯ascii编码。好的这时候我们在对a 进行一次解码后那么我们就得到了url原始数据old).

 

 

 

 

 

 

你可能感兴趣的:(java,应用服务器,Web,socket,浏览器)