Get编码和Post编码的中文乱码问题

 

1.post乱码

原因:

(1)容器使用的编码处理方式和客户端发送非ASCII字符的请求参数的编码方式不一样,比如网页编码是UTF-8,使用窗体post发送某个中文字符,浏览器会把这个中文方式变为在"UTF-8"编码下的三个字节的对应十六进制数值表示.

(2)在Servlet中取得请求参数时,容器若默认使用ISO-8859-1来处理编码. web容器就会把这个中文字符UTF-8编码的十六进制数值表示按照ISO-8859-1编码方式处理,最终得到的就是乱码了.

(Tomcat 8以后URIEncoding的默认值为UTF-8,8以前为ISO-8859-1)

解决:

如果浏览器以UTF-8来发送请求,则接收时web容器也要使用UTF-8编码字符串,则可以在取得任何请求值之"前",执行以下语句: request.setCharacterEncoding("UTF-8"); 这样post乱码就解决了.

2.Get乱码

原因:

request.setCharacterEncoding("UTF-8");这个方法对于请求Body中的字符编码才有作用,也就是基本只对POST产生作用.

       在tomcat8后,如果网页的编码方式是UTF-8,使用GET方法提交请求是不用处理乱码问题的,因为tomcat8后默认编码处理方式是UTF-8,编码形式不冲突,就不会有乱码问题.

例如:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="request.jsp" method="get" >
		姓名: <input type="text" name="name"> <br> 
		密码: <input type="password" name="pass"> 
		      <input type="submit" value="提交">
	</form>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
	    
		String name = request.getParameter("name");
		String pass = request.getParameter("pass");
	%>
	姓名:<%=name%>
	密码:<%=pass%>
</body>
</html>

网页的默认编码是utf-8. tomcat容易的默认编码是utf-8. 那么这样get参数就不会出现乱码.

另一种情况:

把tomcat connector属性更改一下:

<Connector executor="tomcatThreadPool"
    port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443"
    URIEncoding="ISO-8859-1"/>

再测试, 就看到乱码了.所以通过这个tomcat的配置文件来与浏览器匹配编码, 是一个能避免get乱码的方式.

还有一种方法, 就是自己手动转码了

<%
  //web容器处理时把网页的UTF-8编码方式的十六进制表示直接按照容器默认的ISO-8859-1处理,得到的是中文乱码
		String nameN = request.getParameter("name");//nameN是一个中文乱码
 //在这一步,还原上一步用ISO-8859-1转换的形式,便得到utf-8形式的十六进制表示,然后以UTF-8编码方式再进行一次转换,便得到正确中文字符
		String name = new String(nameN.getBytes("ISO-8859-1"), "UTF-8");
		String pass = request.getParameter("pass");
%>

3.另外说一下

(1) HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的request body的编码而不是设置get方法提交的queryString的编码。该方法告诉应用服务器应该采用什么编码解析post传过来的内容。
(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。
(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。
(4) POST提交的数据是作为request body的一部分。

(5) 网页的Http头中ContentType("text/html; charset=GBK")的作用:

(a) 告诉浏览器网页中数据是什么编码;

(b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。

这里需要注意的是:这里所说的ContentType是指http头的ContentType,而不是在网页中meta中的ContentType。

http://hi.baidu.com/爱宝的妍 属于PathInfo,所以根据IE以及Firefox默认设置,ie用utf8 encode了该url,而firefox用gbk encode的,随之服务器端得到了url2和url3不同的url。

  • url1. http://hi.baidu.com/爱宝的妍
  • url2. http://hi.baidu.com/%E7%88%B1%E5%AE%9D%E7%9A%84%E5%A6%8D (UTF-8 编码)
  • url3. http://hi.baidu.com/%B0%AE%B1%A6%B5%C4%E5%FB (GBK 编码)

4. response和request的setCharacterEncoding区别

(1)1.request.setCharacterEncoding():是设置从request中取得的值或从数据库中取出的值的编码方式。 
指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码。在执行setCharacterEncoding()之前,不能执行任何getParameter()。而且,该指定只对POST方法有效,对GET方法无效。 
get需在Tomcat的server.xml中的: )加入URIEncoding解决get请求乱码问题

客户端编码后,用该方法告知服务端,解码时使用相同的编码格式,否则会出现乱码。客户端一般编码()设置<meta http-equiv="Content-Type" content="text/html; charset=gbk">    (post提交的form表单参数采用meta编码方式)

(2)response.setContentType("text/html;charset=gb2312")是设置页面中为中文编码。(get中的QueryString参数用response中的contentType编码,如果没有采用meta编码)

该方法是指定服务端编码格式,并告知客户端解码时的编码码格式,这样两者保持一致,才不会出现乱码。

阅读更多

没有更多推荐了,返回首页