今天在测试spring mvc是想知道原生的servlet的request和response的字符编码,于是写了两行代码测试一下。
System.out.println(request.getCharacterEncoding());//输出null
System.out.println(response.getCharacterEncoding());//输出ISO-8859-1
这让我大惑不解,为什么request会输出null呢?
查资料后懂了。
先说乱码,发送方要发送一串字符,首先必须用字符集给它编码(encode)变成2进制传输,接收方需要用同一个字符集进行解码(decode)方才能知道发送方发送的内容。如果双方所用的字符集不一致就会产生乱码。
web交互中的request中的发送方是客户端,接收方是服务端。发送方默认使用ISO-8859-1来编码发送的内容。所以这里我们就明白了,发送内容的字符编码服务端是不知道的,因为这是客户端指定的。
所以我们在服务端就只能获取null。
但是,服务端可以request.setCharacterEncoding("UTF-8");
来告诉服务器发送端用的是什么编码,以便于服务端用相同的字符集来解码。没有设置会默认使用ISO-8859-1来解码。
在jsp页面中可以用contentType中的charset来指定服务器返回页面用何种字符集来编码。如下就是指定用utf-8编码,如果没有设置则默认为ISO-8859-1,这是一个单字节字符集,处理不了中文。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
如果不指定则默认为ISO-8859-1.
三种乱码
1. 页面中文乱码:这种乱码是服务端返回的页面的编码不支持中文导致的
所以这种无论客户端用何种编码解析都是乱码。
下面是一个jsp
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
<%--<form action="login" method="post">--%>
<%--用户名:<input type="text" name="username"><br>--%>
<%--密 码:<input type="text" name="password"><br>--%>
<%--<input type="submit">--%>
<%--</form>--%>
<a href="param">测试转换器</a><br>
<a href="testServlet?user=熊大">测试获取原生api</a><br>
<a href="anno/testRequestParam?username=哈哈哈">测试requestParams</a><br>
</body>
</html>
输出:
在第一行指定支持中文的utf-8字符集后,乱码问题解决
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
<%--<form action="login" method="post">--%>
<%--用户名:<input type="text" name="username"><br>--%>
<%--密 码:<input type="text" name="password"><br>--%>
<%--<input type="submit">--%>
<%--</form>--%>
<a href="param">测试转换器</a><br>
<a href="testServlet?user=熊大">测试获取原生api</a><br>
<a href="anno/testRequestParam?username=哈哈哈">测试requestParams</a><br>
</body>
</html>
输出:
2.post内容中文乱码:这种乱码是由于客户端的编码和服务端的解码所用的字符集不一致导致的。
客户端的编码是服务器返回页面时候指定的,如果是jsp则是在contentType中指定的,客户端仍然会用相同的编码给服务器post数据。
最常见的就是用utf-8编码post数据,然后用默认,即iso-8859-1解码。就会出现乱码,这时候设置请求的编码集就能解决问题。request.setCharacterEncoding("utf-8")
。
举个例子:
我用客户端post一个表单,然后控制台输出
输出代码:
@RequestMapping("/param/saveUser")
public String saveUser(User user){
System.out.println(user);
return "success";//这是一个跳转页面,不用管
}
控制台输出乱码了:
User{uname='????¤§', age=12, date=Thu Nov 11 00:00:00 CST 1999}
由于我用的是spring mvc这时候我们需要用一个过滤器Filter来设置编码。核心代码就一行request.setCharacterEncoding("UTF-8");
然后在xml中配置过滤的url映射,在交给控制器处理之前先设置一下编码。
public class FilterTest implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
filterChain.doFilter(request, response); // 执行目标资源,放行
}
public void init(FilterConfig arg0) {
}
}
配置了过滤器之后,输出:
User{uname='熊大', age=23, date=Thu Nov 11 00:00:00 CST 1999}
3. get内容中文乱码:这个是uri路径编码导致的。
表现为get传输的内容在url中默认也是使用contentType中指定的编码,如果contenType中的内容改过,对应的tomcat中的配置关系解码uri方式也要改不然就是默认编码。
更改tomcat安装目录下面的conf中的server.xml,找到Connector,添加URIEncoding=“UTF-8”
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
参考:
https://stackoverflow.com/questions/12358101/request-getcharacterencoding-returns-null-why
https://baike.baidu.com/item/ISO-8859-1/7878872