admin管理员组

文章数量:1597908

编码解码过程


上面整个过程可以概括成这样,页面编码数据传递给服务器,服务器对获得的数据进行解码操作,经过一番业务逻辑处理后将最终结果编码处理后传递给客户端,客户端解码展示给用户。

URL格式


图中参数即为常说的Query String部分

ISO-8859-1编码方式

1、ISO-8859-1是单字节编码,使用它对中文进行编码后,若仍然以ISO-8859-1格式解码,得到的中文字符肯定是 乱码 ,因为ISO-8859-1自身不能显示中文。
2、Tomcat7级以下版本默认都是用ISO-8859-1对数据进行解码,可以通过new String(request.getParameter("name").getBytes("iso-8859-1"),页面参数的编码方式) 的形式来获取正确数据。

new String(request.getParameter(“name”).getBytes(“iso-8859-1”), 页面参数的编码方式);
该语句涉及的编码转换的过程:
GBK码(“你”)->URLencode后变成->(%3F%2F)->Tomcat自动替你转一次ISO-8859-1->得到( 23 43
68 23 42 68每一个符号表示为ISO-8859-1中的一个编码)->接收页面—>再转一次为ISO-8859-1的Byte数组[23,43,68,23,42,68]—>用GBK再转为可读的文字—>(%3F%2F")---->转为(“你”)

请求参数的编码与解码

客户端浏览器的编码

1、通过输入网址的方式请求,不会设置Contente-Type,请求参数采用浏览器默认的编码格式进行编码。

2、请求参数位于URL中Query String部分时,使用的是URL编码(一种编码规范)。若是输入网址的方式请求,则URL编码由浏览器决定,不同浏览器采用URL编码不一样,例如:对于path部分Firefox、chrome、IE都是采用UTF-8,对于Query String部分Firefox、chrome采用UTF-8,IE采用GBK。若是表单get请求方式,则URL的Query String部分的编码由网页设置的编码决定,也就是由HTML源码中字符集的设定决定,即<meta http-equiv="Content-Type" content="text/html;charset=xxxx">,若不指定则使用页面默认编码格式。

3、请求参数位于请求正文Body时,可通过设置Content-typecharset来指定参数的编码格式(如:Contente-Type=“application/json;charset=utf-8”),若不指定则使用页面默认编码。当我们通过点击页面的submit按钮来提交表单时,浏览器会根据页面的charset编码格式来对POST表单的参数进行编码然后提交给服务器。

服务器端Tomcat的解码

1、无论我们是通过get方式还是post方式提交,所有的参数都是经过Tomcat解码好保存在Parameters,然后我们通过request.getParameter()获取。

2、Tomcat对于URI的解码操作是首先获取Connector的解码集,该解码集的配置在server.xml:

<Connector URIEncoding="UTF-8" />

如果没有定义,Tomcat7及以下则会默认采用ISO-8859-1来解析,Tomcat8及以上默认采用UTF-8解析。

3、不设置Content-Type属性或不设置该属性中的charset,则charset为null,req.getCharacterEncoding()为null,因此tomcat会采用默认解码格式。

4、对于Query String的解码,若要用Content-Type中的charset作为解码集,需要进行如下配置:

<Connector useBodyEncodingForURI="true"/>

5、Tomcat7及以下,对于Query String的解码,先用设置的charset,若为null,则采用默认的解码格式ISO-8859-1。

6、Tocmat8及以上,对于Query String的解码,先用设置的charset,若为null,则采用默认的解码格式UTF-8。

7、对于请求正文Body的解码,Tomcat采用ContentType中的charset。(如Contente-Type=“application/json;charset=utf-8”,采用UTF-8),若没有手动设置或请求头ContentTypecharset没有指定,则采用默认解码格式,Tomcat7及以下采用ISO-8859-1,Tomcat8及以上采用UTF-8。

8、request.setCharacterEncoding(charset) 方法用来手动设置ContentType的charset,它必须用在第一次getParameter之前。

练习题

1、直接输入网址请求 https://http://localhost:8080/poject/login?name="李明",如何获取不乱码?

2、msg="哈哈" response.sendRedirect("dirceted?msg="+msg),如何保证重定向后msg不乱码?

3、如何获取以下提交数据不会乱码?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<h2>Hello World!</h2>
<form method="Post" action="myredirect">
    账户:<input type="text" name="uesr">
    密码:<input type="text" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>

答案
1、地址直接输入,请求数据编码使用浏览器默认编码集,Tomcat解码使用默认解码集。谷歌浏览器的URL编码中Query String部分使用UTF-8,Tomcat8默认解码使用UTF-8,因此获取值不乱码的方式,直接req.getParameter(user);

2、重定向是把新的URL地址给浏览器重新请求,因此msg需要使用URL编码规范进行编码,使用的编码集可以是Tomcat默认的解码集,这样才能保证msg重定向获取不乱码。Tomcat8默认解码集UTF-8,所以msg的编码为URLEncoder.encode(msg,“utf-8”)。

3、因为设置了charset=UTF-8,且Tomcat8默认解码集UTF-8,则获取值不乱码的方式,直接req.getParameter(user);

参考
tomcat 源码研究之http报文解析
Java在web页面上的编码解码处理及中文URL乱码解决
Google Chrome浏览器对HTTP请求的编码行为
阮一峰的网络日志-关于URL编码
new String(getBytes(ISO-8859-1),GBK)解决中文乱码问题分析

本文标签: 乱码中文参数