1、实际项目遇到的问题
客户端发送POST请求访问接口, 请求参数放在Body当中。每个参数utf-8编码,从获取出来的中文参数时乱码 请求截图:
服务器端获取company参数:request.getParameter("company") 为 ”æå»é¥¿æ廓。乱码!!
2.1、中文乱码的根本原因:
Servlet3.0规范中有关请求参数编码的解释如下: 当前很多浏览器并不发送带Content-Type头部的字符编码标识符,它会把字符编码的决定留在读取HTTP请求的时候。如果客户端没有指明编码,容器用来创建请求读和解析POST数据的默认编码必须是"ISO-8859-1"。然而,为了提示开发者客户端没有成功发送一个字符编码,容器中getCharacterEncoding方法会返回null。 如果客户端没有设置字符编码,并且请求数据使用了不同编码而不是上述的默认编码,程序将会出现中断。为了纠正这种状态,一个新的方法setCharacterEncoding(String enc) 被添加到ServletRequest接口。开发者调用这个方法能重写容器提供的字符编码。这个方法必须在解析request中任何post数据或者读任何输入之前调用。一旦数据已经被读取,调用这个方法不会影响它的编码。
2.2、另外一种理解:
setCharacterEncoding("utf-8"); 该函数是用来设置HTTP请求或者相应的编码格式 对于HttpServletRequest,是指提交参数的编码,指定后可以通过getParameter()方法直接获取到正确的字符串。如果不指定则默认使用is08859-1编码。参见下述“表单输入“。需要注意的是在执行setCharacterEncoding()之前 ,不能执行任何getParameter()获取参数。java doc上写明:This method must be called prior to reading request parameters or reading input using getReader()。而且该指定只对POST方法有效。对GET方法无效。分析原因:应该是在执行第一个getParameter()的时候。JAVA将会按照编码分析所有的提交参数,而后续的getParameter()将不再分析编码。所以setCharacterEncoding()无效。而对于GET方法请求时。请求的参数在URL上,一开始就已经按照编码分析所有的参数,setCharacterEncoding()自然就无效。 对于response, 则制定输出内容的编码, 同时改设置会传递给浏览器, 通知浏览器输出的内容所采用的编码。
3.1、解决方法:web.xml中配置编码Filter
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:
1、web.xml中,这段配置要放在所有filter的最前面,否则会不生效,根本原因请见上述第三点的解释 2、两个初始化参数的作用,其实看这个Filter的源码就一目了然,这两个参数是用来决定是否要设置request和response中的编码。源码很简洁:
public class CharacterEncodingFilter extends OncePerRequestFilter {
private String encoding;
private boolean forceEncoding = false;
public CharacterEncodingFilter() { }
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public void setForceEncoding(boolean forceEncoding) {
this.forceEncoding = forceEncoding;
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if(this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
}
3.2、解决方法:设置Content-Type
如果post请求方式是x-www-form-urlencoded,那么设置如下: Content-Type=application/x-www-form-urlencoded;charset=utf-8 这样通过request对象取body体里面的中文是正常的。 这种方式有一点需要注意: 如果请求方式是multipart/form-data,如上设置会导致request取不到参数。Content-Type要与传递数据匹配(本文data)
3.3、手动编解码
例如参数为company
String company= new String(request.getParameter("company").getBytes("iso-8859-1"), "utf-8");