• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

解决Servlet请求的文乱码问题,

武飞扬头像
小张hen嚣张
帮助1

       最近在复习java web 相关的内容,在servlet章节有一个非常重要也是在面试中经常会被问到的一个问题,那就是如何解决get请求或者post请求参数的中文乱码问题。下面我将给出解决方案,并进行详细解析,毕竟学习编程不仅要知其然,更要知其所以然嘛。


问题描述

        无论是get请求还是post请求,在没有做任何乱码处理的情况下,接收的中文参数在控制台输出都会出现乱码现象。

@WebServlet("/demo")
public class servletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println(username);
    }
}
学新通

学新通

学新通

如上图所示,“张三”在进行转码过程中出现了中文乱码

下面我将从get请求以及post请求两个方面去解决乱码问题。


POST请求参数中文乱码原因分析及解决方案:

我们想要解决该问题,就需要了解Post请求的底层是如何获取参数的。

      POST底层通过POST.getReader()获取字节输入流,而获取的输入流的字符编码ISO-8859-1。而我们页面大多数支持的字符编码都是UTF-8的,所以这就是Post请求参数会出现中文乱码的问题所在。

      因此,解决方法就显而易见了,我们只需要在接收数据的时候去“通知”tomcat重新定义获取字节输入流的编码(UTF-8)就可以了。

解决方法:

  1.  
    @Override
  2.  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3.  
    // 解决乱码:Post.getReader()
  4.  
    req.setCharacterEncoding("UTF-8"); //设置字节输入流的字符编码
  5.  
    String username = req.getParameter("username");
  6.  
    System.out.println(username);
  7.  
     
  8.  
    }

要注意的是:我们设置的字符编码是跟你的页面中的字符编码相匹配的,如果你页面的字符编码是GBK或者其他,就需要设置GBK……的字符编码。  页面的字符编码如下图所示:

学新通

GET请求参数中文乱码原因分析及解决方案:

 和上文一样,如果想要解决问题,就要知道问题所在。 

首先我们要知道GET底层是如何获取参数的,  GET请求是通过getQueryString()的方法(这也是getParameter()底层方法)来获取参数的,并没有像POST请求那样走字节输入流,所以我们用修改字符编码的方式(因为get底层走的是方法,而方法里的编码方式是写死的。所以不能像POST请求那样直接走字节流,可以直接修改字节流的编码方式来解决)是无法解决乱码问题的。

要想解决GET方式的乱码问题,我们可以通过分析编码解码的过程来寻找突破口。

学新通

        因为浏览器不支持中文,所以在进行前后端交互的时候中文字符串都需要进行转码。如上图所示,整个转码过程分为两部分,第一,浏览器会对你输入的中文字符串进行转码,然后将转好的码去交给tomcat进行解码,从上文我们知道tomcat解码的默认方式是ISO-8859-1,所以编码解码方式的不匹配从而产生了乱码现象。下面我们以”张三“为例来进行上文过程的解析。 

       如上图所示: 浏览器在发送参数时(张三)会根据你自己页面上的字符编码(UTF-8)来进行转码(该转码是浏览器自己做的,下文会向大家展示浏览器的转码结果),因为UTF-8编码对中文转码是一个汉字三个字节,所以“张三”被转为了六个字节。进行完该转码后浏览器还会将转好的UTF-8码进行URL编码,然后将数据转发给tomcat。

  URL编码的逻辑是

       1.将字符串按照编码方式转为二进制数组(如下图)

       2.每个字节转为2个16进制数并在前面加上%,如上图(因为“张三“对应的UTF-8码是六个字节,所以转为二进制是48个二进制数,再将每两个字节对应的二进制数转为16进制就会呈现下图所示的码)。

学新通

浏览器进行的转码结果如下图所示

学新通

         tomcat在接收到浏览器发送的参数码的时候会进行相应的解码,首先进行URL解码,在进行编码解码,但是因为tomcat底层的编码方式默认是ISO-8859-1,所以无法正确的将参数码解码,从而导致了如上图所示的乱码问题。

        相信细心的小伙伴已经发现了,虽然我们乱码的根本原因是前后的编码解码不一致,但是有一个地方是相同的,那就是浏览器的URL编码与tomcat的URL解码。

        因为URL编码和URL解码分别是浏览器发送请求参数码的最后一步和tomcat解码的第一步,所以浏览器进行URL编码的数据与tomcat进行URL解码的数据是一模一样的,那么我们是不是可以将tomcat获取的解码后的乱码参数重新转成字节数据,然后再根据字节数据重新按照UTF-8的编码进行二次解码呢?答案是肯定的!我们解决get请求中文乱码问题的关键也就在这里。

        所以我们的解决方法可以分为两部分:

                第一:对于得到的数据进行二次编码,转为字节数组。

                第二:对编码后的数据进行二次解码。

    代码如下:        

  1.  
    @Override
  2.  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3.  
    String username = req.getParameter("username");
  4.  
    System.out.println("解决中文乱码前:" username);
  5.  
     
  6.  
    // 对获取的username进行二次编码 转为字节数组
  7.  
    byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
  8.  
    // 对获得的字节数组进行解码 UTF-8
  9.  
    username = new String(bytes, StandardCharsets.UTF_8);
  10.  
    System.out.println("解决中文乱码后:" username);
  11.  
     
  12.  
    }

学新通


       通过上文,我们知道中文乱码的原因以及解决方案,以及更多的是从原理上去分析、了解问题的根本。我是小张hen嚣张(不嚣张),感谢大家的关照,以后我会继续更新该类文章。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhghafie
系列文章
更多 icon
同类精品
更多 icon
继续加载