对于做后端的朋友来说,httpPost请求用的非常多,在参数传递过程中,中文参数乱码情况经常出现,有时很让我们头疼。最近解决了一些实际工作中的参数乱码问题后,我也做了些总结,现分享给大家。
以HttpClient为例,常见的传参方式有:
1、UrlEncodedFormEntity,如下面代码片段:
nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("name", "张三"));
nvps.add(new BasicNameValuePair("id", "12312312311"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
UrlEncodedFormEntity以字符串键值对形式传给后台,即:{"a":"value1", "b":"value2"},传给java方法,接收到的参数是:a=value1&b=value2,它不支持json参数传递。
2、StringEntity,如下面代码片段:
httpPost.setEntity(new StringEntity(JSON.toJSONString(paramMap), Consts.UTF_8));
StringEntity传参,后台接收到的依然是 {"a":"value1", "b":"value2"},即StringEntity能传递json,当然,如果你传递的就是一个普通的字符串,StringEntity也是支持的。
对于第一种方式(UrlEncodedFormEntity),服务接收端一般采用request.getParameter()方式接参,这种情况下只要服务请求端设置参数时指定了UTF-8或者GBK编码就不会出现中文乱码问题,此处不再多说。下面,主要说一下第二种方式(StringEntity)传参时出现中文乱码的情况及解决方案。
情况一:服务请求端设置参数时没有指定编码方式,此时会默认ISO-8859-1方式编码,服务接收端中文乱码,无法解决,所以服务请求端设置参数时必须指定编码方式(UTF-8或GBK)。
情况二:服务请求端设置参数时指定了编码方式,但是服务接收端有时会乱码,有时不会,服务接收端接参方式如下:
@RequestMapping(value = "/testB")
@ResponseBody
public void testB(HttpServletRequest request) throws Exception {
String body = "";
try {
ServletInputStream inputStream = request.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while(true){
String info = br.readLine();
if(info == null){
break;
}
if(body == null || "".equals(body)){
body = info;
}else{
body += info;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("入参:" + body);
}
后来发现,出现这种现象的原因是服务接收端用流的方式读取参数时没有指定解码方式,这样会默认采用服务器环境的编码方式,所以在不同的服务器环境下有时会出现乱码,有时不会。找到原因后,接参的时候指定解码方式不就得了?结果问题又来了,我咋知道客户端设置参数时指定的是哪种编码方式啊?后来复习了http协议后明白了,从请求报文中就能拿到编码格式额,好吧,于是代码优化为:
经过测试,问题得以解决。其实,还有更简单的接参方式:
@RequestMapping(value = "/testA")
@ResponseBody
public void testA(@RequestBody String para) throws Exception {
System.out.println("入参:" + para);
}
通过@RequestBody注解,直接拿到参数,并且不存在乱码问题。这样既简单又好用,但是我在想为啥它就不存在乱码问题了呢,我猜测中间有个环节必定也通过获取请求端编码方式并以此为依据解析参数的。于是查了下相关的源码,印证了我的猜测,其中有一段代码如下:
至于如何一步步调到这个方法的,中间过程很复杂,感兴趣的可以参考下面大佬的文章链接,并自己走一遍看看:
Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
以上几种情况基本涵盖了httpPost请求中文参数乱码的常见问题及解决,希望能帮到遇到类似问题的朋友,不足之处敬请斧正。