中文乱码解决办法

3,283 阅读3分钟
1、实际项目遇到的问题

客户端发送POST请求访问接口, 请求参数放在Body当中。每个参数utf-8编码,从获取出来的中文参数时乱码 请求截图:

image.png
服务器端获取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");