一、为什么会产生乱码
1.1、理解编码和解码
编码:将我们看的懂得语言转换成计算机看的懂得语言,如计算机只认识英文,则可以利用码表将我们的中文编码为英文
解码:将计算机看得懂的语言转换为我们看得懂的语言
码表:一种规则,将我们看得懂的语言转换为计算机可识别语言的一种规则,常见的码表如ISO-8859-1,GBK,UTF-8等一系列码表,GBK、UTF-8、UTF-16是支持中文的一种码表,ISO-8859-1是标识英文的码表。
1.2、servlet接受/响应数据传输原理
请求乱码问题解决的核心思路:就是把得到的乱码按原来乱码的步骤进行逆序操作
请求乱码问题;以“中”字为例:
(1)乱码过程:游览器将“中”用UTF-8编码为“%E2%E9%1E”后发送给服务器Tomcat,Tomcat再将“%E2%E9%1E”以ISO-8859-1解码为“????”,java服务端得到的就是一个乱码的结果。
(2)服务端解决请求乱码:逆序过程;将“????”以ISO-8859-1码表格式编码为“%E2%E9%1E”,再以UTF-8码表的格式将“%E2%E9%1E”解码为“中”,乱码问题成功解决。
响应乱码问题;以“中”字为例:
(1)乱码流程:java服务端将“中”字传输给Tomcat服务器,Tomcat服务器将“中”以ISO-8859-1码表解码为“????”乱码,游览器以UTF-8码表格式编码为“¥#……%”,游览器无法识别乱码。
(2)响应乱码解决:响应乱码与请求乱码的解决方式不同,请求是要将已经乱码的请求数据被迫的转换为我们可识别的语言(中文),所以需要上述的逆序操作;而响应乱码的问题面向的对象是已知的中文数据,以一种预防的思路即可解决乱码问题,在java服务端将Tomcat和游览器的码表都更换为UTF-8格式。
PS:Tomcat只能以ISO-8859-1码表解码,Tomcat是前后台数据传递的中介,主要支持Http协议,而http协议的底层是tcp协议,以二进制字节流的方式传输数据。
二、servlet乱码问题解决
2.1、Get和Post请求的区别
区别:官方申明,Get方式请求是明文传输,请求参数是存放于请求头之中,不安全;Post方式请求参数是放在请求正文中,安全指数很高,强烈推荐。
2.2、请求乱码解决
(1)get请求:
方式一:流程是先编码后解码,缺点是每一个请求参数均要进行乱码解决操作,可以通过过滤器filter来进行设置
name = new Strign(name.getBytes("ISO-8859-1"),"utf-8");
方式二:利用URLEncoder和URLDecoder进行乱码的逆序操作
// 先对用户名进行解码得到%E7%8E%8B%E6%8C%AF%E5%9B%BD 这样的形式
username = URLEncoder.encode(username, "ISO-8859-1");
// 再进行utf-8编码 一次得到页面上输入的文本内容
username = URLDecoder.decode(username, "UTF-8");
方式三:在tamcat配置文件中修改相应的配置,不推荐
(2)post请求:
//设置请求正文的码表为UTF-8格式
req.setCharacterEncoding("utf-8");
PS:Tomcat9.0以及Tomcat9.0以上版本已经解决了get请求的中文乱码问题,post和get请求处理乱码问题不同的主要原因是他们的传递参数的方式不同,因为get请求的参数主要通过请求头传输,所以setCharacterEncoding对get请求无用,get请求只能先用以ISO-8859-1码表格式编码,再以UTF-8码表的格式将参数解码。
2.3、响应乱码的解决:get和post响应的解决方式相同,设置Tomcat和游览器的码表均为UTF-8
(1)方式一:
//设置响应正文为UTF-8
response.setCharacterEncoding("UTF-8");
response.setHeader("text/html");
(2)方式二:与方式一等价
response.setContentType("text/html;charset=utf-8");