• Java Web乱码分析及解决方式(二)——POST请求乱码


    引言

        GET请求的本质表现是将请求參数放在URL地址栏中。form表单的Method为GET的情况。參数会被浏览器默认编码,所以乱码处理方案是一样的。

    对于POST请求乱码。解决起来要比GET简单。我们关心的重点是在Request Body中。


    请求乱码——Method方式

        使用Method方式发送HTTP请求时,依据HTTP协议的规定,查询參数应该在Request的Body中。比如在Chrome下能够看到URL中不含有查询參数。


    浏览器的编码

        浏览器对POST的Request Body编码会採用页面指定的编码。这句话是我们听到最多也是众口相传的,可是究竟什么是“页面指定的编码”?这个问题就涉及到我们的响应乱码问题了。用句废话就是页面显示时採用的编码,通过浏览器右键能够看到的。可是假设页面乱码了,那么页面使用的编码就是Content-Type里面指定的编码,假设Content-Type没有指定,那么就是meta标签中指定的charset,这两个编码即影响了浏览器对Page页面的解码。又影响了POST请求对Request Body的编码。

    具体能够查看meta标签的http-equiv和Content-Type资料。

       HTTP包传输的是字节码。不会传输字符。所以,无论是GET还是POST都须要编码。

    使用Chrome观察Request的Http包时,我们会发现POST的数据被放在Form Date以下。而GET的数据放在Query String Parameters页签以下。在页面没有乱码情况下,中文參数都会被默认解码。

    切换到View Source以下能够看到提交的编码參数。对于Request Body的长度,浏览器通过加入Content-Length报头来标记字节长度。


    server的解码

        Web容器对POST方法的解码受request.setCharacterEncoding方法的影响。

    对于Tomcat容器,它的官方有这种说明:


    How do I change how POST parameters areinterpreted?

    POST requests should specify the encoding ofthe parameters and values they send. Since many clients fail to set an explicitencoding, the default is used (ISO-8859-1). In many cases this is not thepreferred interpretation so one can employ a javax.servlet.Filter to setrequest encodings. Writing such a filter is trivial.


    翻译过来就是:

       对于POST请求,client应该明白的指明參数和值採用的编码类型。可是很多client并没有这么做。所以Tomcat会默认使用ISO-8859-1来解码POST的參数和值。

    很多时候,我们能够使用一个Filter来设定Request的编码,写这么个Filter是微不足道的一件小事。

     

       简单说就是Tomcat默认使用ISO-8859-1来解码POST的參数和值,能够使用Filter来设定Request Body的字符集。方法就是调用request的setCharsetEncoding。

       文档中并没有说明client应该怎样明白说明POST请求的编码类型,可是我想可能是通过Http协议的标准报头:Accept-Charset来指定的吧。我们不是必需去做这个实验。由于我们的程序绝对不应该把这件事全然托管给“不靠谱”的client。

       所以大多数情况下,我们会在getParameter方法前调用request的setCharacterEncoding方法。就像Tomcat文档中说的,用一个自己写的或者官方提供的Filter完毕这项工作就好了,Spring MVC提供的Filter也是简单的调用了这种方法:

    Spring MVC 字符编码过滤器源代码: 

    @Override
       protected void doFilterInternal(
             HttpServletRequestrequest,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);
       }

    出现乱码:

       POST方法出现乱码时。首先确定下我们的页面使用的是哪种编码方案,然后调用request的setCharsetEncoding,一定要在getParameter前调用这种方法。

       假设仍然是乱码通过这样一个小实验就能知道哪里出错了。

       (1)先获取我们的乱码,String param = req.getParameter("xx");

       (2)对param = new String(param.getBytes(“server编码”,“页面编码”))。

       (3)server编码、页面编码要有“合理”的推測。页面编码通过浏览器菜单观察。别相信自己写的HTML标签。server编码能够试验ISO-8859-1和自己set的charset encoding。然后看看哪里和自己设计的不一致,问题自然就清楚了。


    总结:

       POST方式的乱码比GET处理要简单。我们不用关心URL的编码,也不用编码解码URL。

    POST乱码。一般调用setCharsetEncoding就能够攻克了。可是要注意的是,POST的数据一样是经过编码、解码的。!仅仅只是是不用手动进行而已。


  • 相关阅读:
    PyTorch深度学习:60分钟入门(Translation)
    强化学习入门·
    leetcode 697. Degree of an Array
    耶路撒冷圣城起源笔记
    仓储机器人路径规划笔记
    算术编码原理
    ★房贷计算器 APP
    Sublime
    CocoaPods
    Xcode 6 创建 Objective-C category
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7052673.html
Copyright © 2020-2023  润新知