欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Servlet出现中文乱码的问题

程序员文章站 2024-03-22 19:26:04
...

中文乱码问题

​ 当页面中提交一个包含中文的请求时,在服务端有可能出现中文乱码问题。

一、乱码的产生原因

​ Http 协议中规定,数据的传输采用字节编码(unicode)方式,即无论浏览器提交的数据所包含的中文是什么字符编码格式,一旦由浏览器经过 Http 协议传输,则这些数据均将以字节的形式上传给服务器。因为 HTTP 协议的底层使用的是 TCP 传输协议。TCP(Transmission Control Protocol:传输控制协议)是一种面向连接的、可靠的、基于字节流的、端对端的通信协议。在请求中,这些字节均以 % 开头,并以十六进制形式出现。如%5A%3D等。
Servlet出现中文乱码的问题
那么,乱码是如何产生的呢?

​ 当用户通过浏览器提交一个包含 UTF-8 编码格式的两个字的中文请求时,浏览器会将这两个中文字符变为六个字节(一般一个UTF-8汉字占用三个字节),即形成六个类似%8E的字节表示形式,并将这六个字节。上传至 Tomcat 服务器。

​ Tomcat 服务器在接收到这六个字节后,并不知道它们原始采用的是什么字符编码。而 Tomcat 默认的编码格式为 IS0-8859-1。所以会将这六个字节按照【IS0-8859-1】的格式进行编码,编码后在控制台显示,所以在控制台会显示乱码。

  • 如果浏览器以【GET方式】发送请求,【请求参数】在【请求头】存放,在请求协议包到达服务端之后,【请求头】内容是由 Tomcat 负责解析,Tomcat8、9 在解析数据时,默认采用的字符集【UTF-8】,所以如果浏览器以【GET】方式发送中文参数,此时在服务端不会出现中文乱码问题
  • 如果浏览器以【POST方式】发送请求,【请求参数】在【请求体】存放,在请求协议包到达服务端之后,【请求体】内容是由对应【请求对象request】负责解码的。request 对象默认使用【IS0-8859-1】字符集。所以如果浏览器以【POST方式】方式发送中文参数,此时在服务端必会出现中文乱码问题

二、乱码的产生演示

login.jsp:

<form action="/myWeb/three.do" method="get">
    用户名:<input type="text" name="username" /><br>
    <input type="submit" value="登录">
</form>

ThreeServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String username = request.getParameter("username");
    response.getWriter.println("username = " + username);
}

提交后访问Servlet出现乱码:
Servlet出现中文乱码的问题

三、乱码的解决方案

1、解决POST提交时的中文乱码问题

setCharacterEncoding( )方法设置了请求正文中的字符编码

request.setCharacterEncoding("UTF-8");

2、解决GET提交时的中文乱码问题

注意:Tomcat 8、9版本的问题已解决,这里针对的是Tomcat7及以下版本

使用GET提交时,若请求中携带有中文,为什么会产生乱码?

​ 当用户提交了一个包含中文参数的请求时,浏览器首先会将这些中文转化为一个字节序列,发送到服务器。服务器接收到这个字节序列后,会按照其默认的字符编码【IS0-8859-1】对其进行解码,此时就产生了乱码。但紧接着,服务器会将解码过的参数存放到 parameterMap 中,那么这个Map中的参数已经是乱码了。

(1)在 Tomcat 配置文件中设置(当一个 Tomcat 中只有少数项目时可以使用,不常用
Servlet出现中文乱码的问题
加入以下一段话:URIEncoding=“UTF-8”
Servlet出现中文乱码的问题
(2)对于请求中的中文乱码的万能解决方案

//这里接收到的name,其字符编码为IS0-8859-1 
String name = request.getParameter("name"); 
//打散:将name字符串按照原编码进行打散 
byte[] bytes = name.getBytes("IS08859-1"); 
//组装:将bytes字节数组按照指定字符编码进行组装,组装为String
name = new String(bytes,"UTF-8");
//但一般情况下都组合起来写
name = new String(name.getBytes("IS08859-1"),"UTF-8");

注意:这里每次接收请求参数,都需进行一次这样的代码,重复性高。

3、解决response响应时的中文乱码问题

(1)设置响应的 MIME 类型( video/mp4,image/jpg ),其中可以指定 MIME 的字符编码,即响应体的字符编码(常用)

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

(2)setCharacterEncoding() 方法的使用前提是:之前必须要先使用 setContentType() 方法,setCharacterEncoding( )方法用于修改ContentType的MIME类型字符编码

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