JavaWeb 之 GET请求和POST请求的乱码问题

一、乱码的原因

  乱码:当编码与解码不一致时,就会出现乱码的情况。(本质:编解码不一致)

  根据乱码又可分为:

      (1)请求乱码:客户端编码与服务器解码不一致

      (2)响应乱码:服务器编码与客户端解码不一致

  编码:将字符转换为二进制的过程称之为编码

  解码:将二进制转换为字符的过程称之为解码

二、默认的编解码

  1、服务器端(Tomcat)的编解码

      Tomcat 默认是使用 ISO8859-1来编解码的。(ISO8859-1是不支持中文的)

      注意:① Tomcat8(包含8)以上版本默认编码格式是 UTF-8

         ② HttpServletRequest 和 HttpServletResponse容器默认编码格式是 ISO-8859-1

  2、客户端的编解码

     浏览器的编码:默认是 GB2312。

      影响form提交数据的编码的因素包括:form的accept-charset属性、html文档的编码方案即document.charset。其中,form的accept-charset是否能够有效,依赖具体浏览器的实现,有些浏览器并不支持,如IE。文档编码方案可以通过document.charset来修改。

     浏览器的解码:默认是GBK/GB2312。

      通常来说,浏览器会先按照Content-Type的编码设置来解析文本,然后在解析过程中发现charset设置,再更换编码重新读取。若Content-Type没有设置编码,或者说这个HTML文件根本就不是走的HTTP协议,浏览器通常会猜测编码来解析文本,然后发现charset设置再更换编码读取。

  3、GET 和 Post 解码格式

    request 容器保存的是浏览器的数据,一般是 UTF-8 格式。

    request的方法如:getParameter解码格式会根据Get和Post来设置解码格式。因为Get和Post的取值放在不同地方。所以要分开考虑。

1. Get是 URL 解码方式。默认解码格式是 Tomcat8 编码格式。所以URL解码是 UTF-8,覆盖掉了 request 容器解码格式
2. Post 是实体内容解码方式。默认解码格式是request编码格式。与Tomcat8编码格式无关

三、GET 请求乱码解决

  虽然 Response容器默认以 ISO8859-1 的编码解析数据
  但是对于get请求提交的数据,在不同版本的 Tomcat中有不同的处理方式,在 Tomcat8 及以上的版本,服务器默认以  UTF-8 的编码方式处理请求参数

  1、方案一:Tomcat 版本8以上不用指定编码格式,默认 utf-8

      而对于tomcat8以下的版本,服务器会默认以ISO8859-1的编码方式处理请求参数

  2、方案二:编码二次转换(推荐)

      注意:

utf-8-》iso-8859-1》utf-8          原样
utf-8-》GBK-》utf-8                  乱码  

      具体参考这篇:编码转换问题

    现在基本都是Tomcat8以上版本 ,所以不存在编码问题,而如果是Tomcat8以下版本解决方案:  

// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码,手动解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");

  3、方案三:

      设置指定解码 URL 的编码格式:URIEncoding="UTF-8" (不推荐,依赖服务器,有时候没法设置服务器)

     对于 get 请求需要在修改 Tomcat 服务器里面的server.xml文件的配置:(或者Tomcat目录下的/conf中的 server.xml进行设置)

     

     注意:tomcat8.0以后get请求默认使用UTF-8进行解码,所以此配置只针对tomcat8.0以前的版本!

<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" 
        protocol="HTTP/1.1" redirectPort="8443"/>

  

  4、方案四

    请求参数的编码方式要采用请求体的编码方式(不推荐依赖服务器,有时无法设置服务器)

useBodyEncodingForURI=true是说,。当useBodyEncodingForURI=true时,若请求体采用utf-8解析,则请求参数也要采用utf-8来解析。    

server.xml:
<Connector port="8080" protocol="HTTP/1.1"   connectionTimeout="20000"   redirectPort="8443" useBodyEncodingForURI="true" />

  

Servlet:
doGet(){
request.setCharacterEncoding("utf-8");
}

  分析:

    ① request.setCharacterEncoding("utf-8");只是作用于实体内部,意思就是说对Post有效,对Get无效。
    ② 但是设置useBodyEncodingForURI="true"后URL解码格式和实体内容解码格式一样。
    注意:如果只是设置useBodyEncodingForURI="true那get URL解码格式就是默认iso-8859-1,因为实体内部默认是这个解码格式,即使Tomcat版本8以上默认编码格式为UTF-8也会被iso-8859-1覆盖掉。

四、POST 请求乱码解决

   Tomcat服务器中 Response 容器默认以 ISO8859-1 的编码解析数据,因此如果需要在参数中解析中文,需要设置对于 post 请求的乱码,可以设置 request 对象的编码格式为 UTF-8即可。

request.setCharacterEncoding("UTF-8");

  注意:

    ① 要写在 request.getParameter 前面,不然无法生效;

    ② 设置参数查询的编码;

    ③ 该方法只能对Response容器的请求实体内容的数据编码起作用。POST提交的数据在实体内容中,所以该方法对POST方法有效!

    ④ GET 方法的参数放在 URI 后面,所以对 GET 方式无效  

  扩展:也可以为整个 JavaWeb 项目配置字符过滤器。

 1     <filter>
 2         <description>字符集过滤器</description>
 3         <filter-name>encodingFilter</filter-name>
 4         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
 5         <init-param>
 6           <description>字符集编码</description>
 7           <param-name>encoding</param-name>
 8           <param-value>UTF-8</param-value>
 9         </init-param>
10      </filter>
11      <filter-mapping>
12           <filter-name>encodingFilter</filter-name>
13           <url-pattern>/*</url-pattern>
14      </filter-mapping>

五、响应乱码解决

    响应乱码解决方案:给服务器和浏览器设置统一的编解码

    方案一:(不推荐)

// 设置服务器字符集为 UTF-8
response.setCharacterEncoding("UTF-8");
// 通过响应头, 设置浏览器也使用 UTF-8 字符集
response.setHeader("Content-Type", "text/html; charset=UTF-8");

    方案二:(推荐使用)

// 它会同时设置服务器和客户端都使用 UTF-8 字符集, 还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
response.setContentType("text/html; charset=UTF-8");

  

六、总结

  1、中文建议使用post而不是get

  2、Tomcat8版本以上默认是UTF-8对GET方法来说,对POST无效,因为request.getParameter默认调用·iso-8859-1·

  3、get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value&parame2=value2的形式附加在URI字段之后,而Post是放在实体内部。

  4、request.setCharacterEncoding(charset);只对消息体中的数据起作用,对于URI字段中的参数不起作用。默认作用于POST,对GET无效。

    当使用request.setCharacterEncoding(charset);时,只能解决表单方法为POST的中文乱码情况,而方法为GET的依然为乱码。

  5、request.setCharacterEncoding(“UTF-8”) 解决 post 乱码

  6、useBodyEncodingForURI=”true”目的是URL解码格式和实体内部解码格式相同。

  7、如果使用JS编程时,在浏览器可以使用encodeURIComponent函数对中文参数进行编码后再拼装参数。

猜你喜欢

转载自www.cnblogs.com/niujifei/p/12428034.html