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