一文让你今后告别HTTP乱码(二)Response篇

概述

  开发Web项目的过程当中,常常遇到浏览器中显示的内容乱码,或者服务器获取浏览器请求参数时乱码的问题,不少同窗基本都是在遇到乱码的时候去网上一顿搜索,而后看哪篇文章比较靠谱就照着上面的内容去配后乱码成功消失了,而后就没而后了...html

最后基本只是停留在知道怎么样设置能避免常见的乱码问题,而不知道具体的原理,一旦遇到了网上查不到的乱码场景就不知道如何解决了~web

  本文会深刻的让你了解针对于HTTP请求时,这一去一回(Request,Response)之间,到底作了怎样的事情,让你完全告别Web项目中的乱码烦恼。本文的内容是基于Tomcat 8.0.23版本的,其余容器也能够参考本文的内容,毕竟理论都是通的~数组

Response乱码

  当你在浏览器中看到响应的内容是乱码的时候,第一反应就是,是否是我程序的问题,是否是我程序吐出的内容就是个乱码,因此才致使了浏览器里面看到了乱码。那么接下来我将带你过一遍Response的过程,以及对刚才的猜想进行验证~浏览器

  首先,我建了一个很是简单的Web项目,里面只有一个Servlet,做用是直接返回我要响应的内容~服务器

项目结构以下:工具

 

Servlet内容以下:编码

web.xml内容以下:spa

接下来咱们在浏览器中访问:http://localhost:8080命令行

 首先在Firefox中访问,结果以下:xml

接下来再在QQ Browser中访问,结果以下:

此时咱们看见2个浏览器中展现的内容不管是浏览器正文仍是下面的Response标签中显示的字符都是乱码,而且是相同的乱码内容~

那么这个乱码是怎么产生的呢?回头再去看咱们servlet中的代码:

代码中能够看见咱们没有指定任何的编码相关内容,那么Tomcat在将result字符串转换成字节数组时会使用HTTP规范的默认编码ISO-8859-1,因而输出的内容就是将result进行ISO-8859-1编码后的字节数组,

由于ISO-8859-1能表示的字符数量有限,它没法表示中文,因此在此时Response的内容与就已是乱码了。

而后Response到达浏览器,浏览器会获取Response中的内容,由于Response中的响应头中没有指定信息的编码类型,因此浏览器会尝试根据编码规则进行推测,并根据推测进行解码,因为我使用的是中文系统,Firefox

的正文部分采用的是GBK编码,而Response中的内容则使用了UTF-8编码。QQ Browser正文部分使用的也是GBK编码,而Resopnse中的内容则使用了ISO-8859-1编码(不一样浏览器,或者同一个浏览器的不一样版本解码使用的编码均可能会不同),

解码以后就是我所看见的 ???~????! 乱码了。

下面这段程序就能够验证上面的内容:

  上面的验证本质上是由于在Servlet中处理Response的时候没有指定编码,从而致使了使用了默认的ISO-8859-1对Response的内容(楚楚街~卖得漂亮!)进行了编码,可是由于ISO-8859-1没法表示中文,结果在Servlet编码

时就已经产生了乱码,以后不管你怎么解码它都是个乱码。

  接下来咱们改进下Servlet,使其在Response的时候使用UTF-8(由于UTF-8能够表示中文)进行编码,代码以下:

而后咱们再次请求http://localhost:8080

Firefox结果以下:

QQ Browser结果以下:

从结果咱们能够看出,Firefox中正文依然乱码,而Response的内容正确解析了,而QQ Browser中正文和Response中的内容都是乱码。

根据以前的分析,咱们已经知道Firefox的正文是GBK编码,Response内容是UTF-8编码,而QQ Browser中的正文也是GBK编码,Response的内容是ISO-8859-1编码。

下面代码对上面的内容进行了验证:

咱们在对Servlet返回给2个浏览器的Response进行一下抓包,看下Response的内容究竟是啥~

对Firefox的抓包:

对QQ Browser的抓包:

从结果咱们能够看到2个浏览器收到的Response的结果都是相同的,其中Data部分都是e6a59ae6a59ae8a1977ee4b9b0e79a84e6bc82e4baae21,这串值就是

对 楚楚街~买的漂亮! 进行UTF-8编码后的值。

到此为止,作一个小总结:

  1.Response在返回前会对要返回的内容作编码,在不指定(setCharacterEncoding("UTF-8"))的状况下会使用默认的ISO-8859-1编码。

  2.不一样的浏览器在收到返回的Response时,获取到的内容是一致的,以后浏览器会根据自身的策略对内容进行解析。

  继续上面的乱码问题,为何此次使用UTF-8对中文进行了编码后,浏览器里面依然是乱码呢?缘由就是在Response中没有对响应的内容使用的是哪一种编码作说明,致使了

浏览器不知道使用哪一种编码作解码,而后就使用了浏览器默认的解码行为进行解码,从而致使了乱码。

  接下来咱们为Response加上响应头Content-Type:text/plain; charset=utf-8来告诉浏览器,Response内容应该用什么编码来解码,代码以下:

上面的代码中,咱们指定了2次编码而且2次的编码不一致,那么到底会使用哪一个编码呢?还会出现乱码么?看实际结果说话~

 Firefox结果:

QQ Browser结果:

咱们能够看到,2个浏览器不管是正文部分仍是Response的内容中都正确的解码了~

总结:

  1.Response须要告知浏览器使用哪种编码来解码其内容。

  2.Response所使用的编码为最后一次设置的编码,也就是说后面的编码设置信息会覆盖掉前面的编码设置信息。

接下来咱们再来使用命令行来请求下试试,以下图:

发现结果竟然是乱码,难道以前的结论是错误的?什么鬼...

  其实以前的结论并没错,而是以前的结论须要加个限定条件(只适用于浏览器),咱们把HTTP请求的Response能够划分为2个步骤,第一步是获取到这个Response,第二步就是对

这个Response进行解析,上面的问题就出如今了第二步(解析)。由于浏览器是遵循HTTP规范的,HTTP规范中说明了响应头中的Content-Type属性中的charset指定的编码就是Response

中内容的实际编码,因此浏览器会使用这个charset中指定的编码对Response中的内容进行解码,那么天然没问题了,而命令行则不须要遵循HTTP中的规范,因此命令行并无关心charset指定

的内容,而是使用命令行默认的编码进行解码的,因此致使了乱码,知道了问题的根本缘由,那么是否是咱们改变了命令行的编码就能够正确显示了呢?看下面结果:

首先咱们修改了命令行的编码为UTF-8(chcp 65001),而后从新请求后,发现显示正常了~

到此为止~Response时的乱码问题成功解决啦~

Response乱码总结:

  1.Response在返回前会对要返回的内容作编码,在不指定编码的状况下会使用默认的ISO-8859-1编码。

  2.不一样的浏览器在收到返回的Response时,获取到的内容是一致的,以后浏览器会根据自身的策略对内容进行解析。

  3.Response须要告知浏览器使用哪种编码来解码其内容。

  4.Response所使用的编码为最后一次设置的编码,也就是说后面的编码设置信息会覆盖掉前面的编码设置信息。

  5.浏览器会遵循HTTP规范,使用Content-Type属性中的charset指定的编码去解码,而命令行工具则不会关注charset的内容,而是根据命令行自身的编码方案进行解码。

 

至此,一文让你今后告别HTTP乱码系列文章所有结束了~但愿对遇到乱码的同窗有所帮助,哪怕只有一点点~

附上上一篇文章的链接:一文让你今后告别HTTP乱码(一)Request篇

相关文章
相关标签/搜索