这几天想起以前项目遇到的中文参数编码的问题,所以想再试验一下,自己就搭建了一个简单Javaweb平台,前台传到后台的中文参数,再立马传回到页面上显示。
项目平台是利用REST框架搭建,中文编码处理这块我想使用servlet的过滤器来实现,具体的页面源码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>首页</title>
<script src="js/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$("#submitBtn").click(function() {
$.ajax({
type : "post",
url : "user.json?message=中文乱码测试Test",
data : $("#form").serialize(),
dataType : "json",
cache : false,
async : false,
success : function(data) {
$("#show").html(data.msg);
},
error : function() {
}
});
$.ajax({
type : "get",
url : "user.json?message=中文乱码测试Test",
data : $("#form").serialize(),
dataType : "json",
cache : false,
async : false,
success : function(data) {
$("#show1").html(data.msg);
},
error : function() {
}
});
});
});
</script>
</head>
<body>
<div id="show"></div>
<div id="show1"></div>
<form id="form" name="form" method="post" action="">
<div>
<table>
<tr>
<td><input type="text" name="str1" id="id1" /></td>
</tr>
<tr>
<td><input type="text" name="str2" id="id2" /></td>
</tr>
</table>
</div>
<div>
<input id="submitBtn" type="button" value="提交" class="submit" />
</div>
</form>
</body>
</html>
页面中的url和data参数是专门为本次测试写的,我们先来看几组实验再来分析:
测试一:不实用任何Filter,看看是啥效果:
测试二:在web.xml里新建一个filter,如下:
<filter>
<filter-name>encodingConvertFilter</filter-name>
<filter-class>com.jobtest.filter.EncodingConvertFilter</filter-class>
<init-param>
<param-name>fromEncoding</param-name>
<param-value>ISO-8859-1</param-value>
</init-param>
<init-param>
<param-name>toEncoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingConvertFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
EncodingConvertFilter类中具体方法实现为:
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getMethod().equalsIgnoreCase("GET")) {
for (Iterator<String[]> iterator = request.getParameterMap()
.values().iterator(); iterator.hasNext();) {
String[] parames = iterator.next();
for (int i = 0; i < parames.length; i++) {
try {
parames[i] = new String(parames[i].getBytes(fromEncoding), toEncoding);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
filterChain.doFilter(request, response);
}
测试结果为:
测试三:我们把Filter实现方法稍微改一下,增加一个条件request.getMethod().equalsIgnoreCase("post"):
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getMethod().equalsIgnoreCase("GET")||request.getMethod().equalsIgnoreCase("post")) {
for (Iterator<String[]> iterator = request.getParameterMap()
.values().iterator(); iterator.hasNext();) {
String[] parames = iterator.next();
for (int i = 0; i < parames.length; i++) {
try {
parames[i] = new String(parames[i].getBytes(fromEncoding), toEncoding);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
filterChain.doFilter(request, response);
}
再测试一下:
我们来分析下测试二和测试三里的不同,在Ajax请求里,后台收到的数据,附在url里面的中文参数是"iso-8859-1" 编码,在data里提交的表单数据是“utf-8” 编码。
原因是我们在jquery-1.8.2.min.js中设置了data中数据的字符集 contentType:"application/x-www-form-urlencoded; charset=UTF-8" 为“ UTF-8 ”字符集。
在Post方式提交的数据里,Url和data里的数据被分成两部分分别编码,而Get方式就只有一种编码。因为在Tomcat5.0中,默认情况下使用ISO- 8859-1对URL提交的数据和表单中GET方式提交的数据进行重新编码(解码)。
我从网上找过很多方法,比如在过滤器里面设置request.setCharacterEncoding(“utf-8”); 但是对Get方式提交的中文参数依然无效。看servlet的官方API说明有对此方法的解释:Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using getReader().原因跟上面的原因一样。
所以我们有两种解决办法:
1、在过滤器里面对get方式单独做处理比如上面的过滤器。此外post方式最好不要在url里面带中文参数,不然也会出现中文编码问题的。页面编码也得规范好<meta http-equiv="Content-Type" content="text/html; charset=utf-8">;
2、修改Tomcat 的server.xml中的配置为
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>增加URIEncoding="编码" 这个节点,默认是默认是没有的,这样对Url和get方法也适用,此时就不需要过滤器了。