第一.服务器接收客户端请求乱码
1.先用request.getParameter(xxx)获取参数值,然后对此参数值用ISO-8859-1解码再用UTF-8编码,对GET请求和POST请求都有效
2.在用request.getParameter(xxx)方法获取参数值前,用request.setCharacterEncoding(encoding)方法设置字符集。但是这种方式只对POST请求(enctype="application/x-www-form-urlencoded")有效,对GET请求无效,GET请求数据还需要用ISO-8859-1解码再用UTF-8编码。
第二.客户端解析服务器响应乱码
使用request.setContentType("text/html;charset=UTF-8")即可解决。
在spring-web-xxx.RELEASE.jar包中有一个专门处理请求、响应字符编码的Filter,CharacterEncodingFilter。这个Filter内部封装了request.setCharacterEncoding(encoding)和response.setCharacterEncoding(encoding)方法,这个Filter可以处理POST请求的乱码问题,但是处理不了GET请求的乱码问题,也处理不了客户端解析服务器响应时的乱码问题。鉴于此,我们可以自己写一个Filter来处理编码问题,核心方法doFilter()如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
这样我们就能处理POST请求的乱码问题和客户端解析服务器响应时的乱码问题,但还是解决不了GET请求时的乱码问题。所以还是得在对应的控制器中对参数值先用ISO-8859-1解码再用UTF-8编码。
request、response的get/setCharacterEncoding()方法源码注释:
/**
* Returns the name of the character encoding used in the body of this
* request. This method returns <code>null</code> if the request
* does not specify a character encoding
*
* @return a <code>String</code> containing the name of the character
* encoding, or <code>null</code> if the request does not specify a
* character encoding
*/
public String getCharacterEncoding();
request.getCharacterEncoding():如果没有调用request.setCharacterEncoding(xxx)方法的话就会返回null。
/**
* 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(). Otherwise, it has no effect.
*
* @param env <code>String</code> containing the name of
* the character encoding.
*
* @throws UnsupportedEncodingException if this ServletRequest is still
* in a state where a character encoding may be set,
* but the specified encoding is invalid
*/
public void setCharacterEncoding(String env) throws UnsupportedEncodingException;
request.setCharacterEncoding():需在request.getParameter(xxx)之前调用,否则无效,对get请求也无效。
/**
* Returns the name of the character encoding (MIME charset)
* used for the body sent in this response.
* The character encoding may have been specified explicitly
* using the {@link #setCharacterEncoding} or
* {@link #setContentType} methods, or implicitly using the
* {@link #setLocale} method. Explicit specifications take
* precedence over implicit specifications. Calls made
* to these methods after <code>getWriter</code> has been
* called or after the response has been committed have no
* effect on the character encoding. If no character encoding
* has been specified, <code>ISO-8859-1</code> is returned.
* <p>See RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)
* for more information about character encoding and MIME.
*
* @return a <code>String</code> specifying the name of
* the character encoding, for example, <code>UTF-8</code>
*/
public String getCharacterEncoding();
response.getCharacterEncoding():如果之前没有调用response.setCharacterEncoding(xxx)或者response.setContentType(xxx)的话,会返回ISO-8859-1。
/**
* Sets the character encoding (MIME charset) of the response
* being sent to the client, for example, to UTF-8.
* If the character encoding has already been set by
* {@link #setContentType} or {@link #setLocale},
* this method overrides it.
* Calling {@link #setContentType} with the <code>String</code>
* of <code>text/html</code> and calling
* this method with the <code>String</code> of <code>UTF-8</code>
* is equivalent with calling
* <code>setContentType</code> with the <code>String</code> of
* <code>text/html; charset=UTF-8</code>.
* <p>This method can be called repeatedly to change the character
* encoding.
* This method has no effect if it is called after
* <code>getWriter</code> has been
* called or after the response has been committed.
* <p>Containers must communicate the character encoding used for
* the servlet response's writer to the client if the protocol
* provides a way for doing so. In the case of HTTP, the character
* encoding is communicated as part of the <code>Content-Type</code>
* header for text media types. Note that the character encoding
* cannot be communicated via HTTP headers if the servlet does not
* specify a content type; however, it is still used to encode text
* written via the servlet response's writer.
*
* @param charset a String specifying only the character set
* defined by IANA Character Sets
* (http://www.iana.org/assignments/character-sets)
*
* @see #setContentType
* @see #setLocale
*
* @since Servlet 2.4
*/
public void setCharacterEncoding(String charset);
response.setCharacterEncoding(xxx):
可以覆盖response.setContentType(xxx)设置的字符集;
response.setContentType("text/html")与response.setCharacterEncoding("UTF-8")一起使用的效果,等同于response.setContentType("text/html;charset=UTF-8");
若要客户端正确解析服务器响应不乱吗,必须明确指定ContentType的值;
需在response.getWriter()之前调用,否则无效。