Servlet 中文乱码

1. 乱码原因

简单地讲,编码(encode)和解码(decode)使用的字符集不一致,就会导致乱码

  • 服务器接收请求参数乱码原因:服务器接收数据解码时使用的字符集,与客户端发送数据编码时使用的字符集不一致
  • 客户端接收响应数据乱码原因:客户端接收数据解码时使用的字符集,与服务器发送数据编码时使用的字符集不一致

2. 服务器获取GET请求queryString乱码解决方案

从Tomcat8开始,GET乱码问题已经由Tomcat自己解决了

如果是Tomcat7及之前,可以编辑conf/server.xml

1
2
3
4
5
<!-- 找到设置port="8080"的那个标签,添加URIEncoding="UTF-8"即可 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />

如果使用的是Maven Tomcat插件,在<configuration>标签中设置<uriEncoding>属性即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<!-- 设置uriEncoding -->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>

3. 服务器获取POST请求体乱码解决方案

1
2
3
// 在获取请求参数之前,先通过setCharacterEncoding设置编码
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");

4. 客户端接收响应体乱码解决方案

在响应头不指定ContentType时,浏览器器默认使用的字符集与系统环境有关,例如Windows中文环境下,默认字符集是GBK(GB2312)

resp.getWriter() 获取输出流对象。Response是Tomcat实现的,编写Tomcat的不是中国人,他们指定了输出流的的默认字符集是IOS-8859-1。所以你用PrintWriter输出中文,使用IOS-8859-1,但是浏览器用GBK解码,肯定会乱码

解决方案如下:

1
2
3
4
resp.setCharacterEncoding("UTF-8");   // 在获取输入流之前,设置响应体的编码
resp.setContentType("text/html;charset=utf-8"); // 设置响应头ContentType,告诉浏览器使用指定字符集进行解码
PrintWriter out = resp.getWriter();
out.print("<h1>你好</h1>");

事实上,setCharacterEncoding()可以进一步省略,因为Tomcat在实现setContentType()时,不仅仅设置响应头了的ContentType,还同时设置了响应体的编码

1
2
3
resp.setContentType("text/html;charset=utf-8");  // 只要这一句就够了
PrintWriter out = resp.getWriter();
out.print("<h1>你好</h1>");

panchaoxin wechat
关注我的公众号
支持一下