你的位置:首页 > 软件开发 > Java > 一文让你从此告别HTTP乱码(一)Request篇

一文让你从此告别HTTP乱码(一)Request篇

发布时间:2017-03-24 00:01:09
概述  开发Web项目的过程中,经常遇到浏览器中显示的内容乱码,或者服务器获取浏览器请求参数时乱码的问题,很多同学基本都是在遇到乱码的时候去网上一顿搜索,然后看哪篇文章比较靠谱就照着上面的内容去配后乱码成功消失了,然后就没然后了...最后基本只是停留在知道怎么样设置能避免常见的乱 ...

概述

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

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

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

Request乱码

   在Request过程中我们需要注意2个步骤,第一个是请求发送时所使用的编码,第二个是应用收到请求后解码时所用的编码,只有保证这两步中使用相同的编码即可有效防止乱码的发生。那么请求时使用的是什么编码呢?这个主要取决于请求时的客户端。

下面我们做个测试,客户端分别使用浏览器和curl来请求,服务端使用Tomcat 8.0.23来处理。

  请求地址:http://localhost:8080/ccj/楚楚街?query=买的漂亮  

  我们先来分析下上面的地址:

  url:http://localhost:8080/楚楚街

  uri:/ccj/楚楚街

  queryString:query=买的漂亮

Tomcat使用默认配置,使用下面代码来接收请求:

一文让你从此告别HTTP乱码(一)Request篇

Firefox中请求 http://localhost:8080/ccj/楚楚街?query=买的漂亮 结果如下:

一文让你从此告别HTTP乱码(一)Request篇

上面信息可以看出,在发送请求之前Firefox先对请求地址中的中文使用UTF-8编码进行了百分号编码,关于百分号编码的内容可以自行Google查阅相关内容,这里不在赘述。

这里我们发现获取的内容居然没有乱码,这是因为我是用的是Tomcat8的缘故,看下官方说明:

一文让你从此告别HTTP乱码(一)Request篇

在不指定URIEncoding的情况下,并且也没指定系统属性org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true时,默认使用UTF-8进行解码。这个变化是从Tomcat8开始的,Tomcat8之前的的处理方式是,如果没指定

URIEncoding的情况下,那么会直接使用ISO-8859-1作为默认编码的。

下面我们加上系统属性org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true来模拟Tomcat8之前的情况,发起同样的请求 http://localhost:8080/ccj/楚楚街?query=买的漂亮 结果如下:

一文让你从此告别HTTP乱码(一)Request篇

看结果发现,果然出现了乱码问题,那么我们已经知道了Firefox发送过来的请求是经过了UTF-8编码的百分号编码,那么我们可以对query进行ISO-8859-1编码的百分号解码来重现下乱码,看结果:

一文让你从此告别HTTP乱码(一)Request篇

  我靠~什么鬼为什么乱码跟我们预想的结果不一样,这个乱码跟之前访问Sevlet中出现的乱码不一样???难道之前的结论都是错的么???其实并不是~这里出现2次乱码显示的不一致的情况是控制台编码不一致导致的,

我是用的IDEA,IDEA的控制台编码是受到-Dfile.encoding这个虚拟机启动参数影响的,这里送上之前写的一篇文章供参考(Java虚拟机(JVM)默认字符集详解)。

 

================================================华丽的分割线之IDEA乱码问题开始================================================

 

  既然遇到了控制台编码乱码问题,接下来我就顺便讲一下IDEA控制台乱码的解决方法吧~首先我们看上面2附图,先看第一个图请求Servlet时控制台打印的是 file.encoding=GBK,而第二个图中使用main方法运行后

控制台打印的是 file.encoding=UTF-8。2次运行使用的都是同一个IDEA实例,为什么编码会不一样呢?我们先关掉IDEA,然后杀死所有当前java进程,然后重新启动IDEA,看一下进程启动参数,因为是windows系统,所以cmd中使用命令:

wmic  process where caption="java.exe" get caption,commandline /value

Linux下使用命令:ps -aux | grep java

结果如下图:

一文让你从此告别HTTP乱码(一)Request篇

看见了吧,-Dfile.encoding=GBK这个是当前IDEA实例启动时候的JVM虚拟参数,所以当前IDEA的控制台编码是GBK,但为什么我们跑main方法时打印的信息是-Dfile.encoding=UTF-8呢,这是因为我修改了Settings

中的File Encodings导致的,直接看图:

一文让你从此告别HTTP乱码(一)Request篇

这个地方的配置会影响运行main方法时的控制台编码,那么既然知道了原因,我们就开始解决问题吧~首先我们需要更改IDEA启动时的参数-Dfile.encoding=UTF-8,修改的方式为:

windows x64环境修改 C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2017.1\bin\idea64.exe.vmoptions

windows x86环境修改 C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2017.1\bin\idea.exe.vmoptions

分不清楚的可以将上面2个文件全部修改~修改内容为在文件末尾加上红框中的内容:

一文让你从此告别HTTP乱码(一)Request篇

MacOS系统修改文件 /Applications/IntelliJ IDEA 2017.app/Contents/Info.plist,修改完之后重启IDEA才能生效~

重启后我们再次访问 http://localhost:8080/ccj/楚楚街?query=买的漂亮 结果如下:

一文让你从此告别HTTP乱码(一)Request篇

结果发现依然是乱码,并且乱码跟最开始访问的时候不一样了...这是什么鬼...我们继续来分析,因为是运行在Tomcat中,所以我们在打印的时候会根据启动Tomcat的那个JVM的file.encoding进行编码,

通过查看线程启动参数发现Tomcat启动时的file.encoding=GBK,那么问题就迎刃而解了,原理简述如下:

原标题:一文让你从此告别HTTP乱码(一)Request篇

关键词:http

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。