jsp/servlet取参数乱码问题分析


1、问题的来源和根本原因:

    这个话题是个很古老的话题,从jsp/servlet一出现就有了,对经常和汉字打交道的朋友来说,遇到最多的就是表单页面提交的中文参数 在服务器端直接用String myparam=request.getParameter("myparam");这里myparam的值将会是乱码。于是,有了这个解决方案:String myparam=new String(request.getParameter("myparam")。getBytes("ISO-8859-1"),"GBK");那么这个问题的本质是什么呢?大家如果看过servlet的规范,或者研究过tomcat的源码,就会发现问题的原因:实际上在 servlet引擎实现 request.getParameter("myparam")时,会先在一个缓存里找一下,如果没有,就会开始解析参数并把解析后的参数和其对应的值放入缓存中。而在解析参数时,servlet规范中规定:首先按照 request.getCharacterEncoding获取的编码对解析出来的byte进行编码,创建新的字符串。如果request.getCharacterEncoding 的值是null,则按照ISO-8859-1来进行编码。而现在大多的浏览器在发送数据时都没有发送客户端的数据编码。所以在没有预先设置过的情况下,引擎应该都是按着ISO-8859-1来处理参数的值。

    假如表单的参数实际值是“中国” 那么按着GBK的编码提交到服务器端的myparam的值对应的应是4个byte.假设 解析出来的byte 是paramBytes,那么引擎为我们放入参数缓存中的参数值就是这样的 new String(paramBytes,encoding);很明显本来2个字节参能表达一个汉字 ISO-8859-1来编码之后,每个字节都成了单独的一个字符:4个字节成了四个字符,这就是我们看到的乱码出现的原因。

    所以 new String(request.getParameter("myparam")。getBytes("ISO-8859-1"),"GBK"); 实际上在进行还原操作。

    需要注意的是按GBK进行编码还原的前提是你表单页面的表单数据是按GBK进行编码的。这个主要是通过<meta http-equiv="Content-Type" content="text/html; charset=GBK">来保证的。当然如果你的页面是jsp,并且在jsp页面头上设置了<%@ page contentType="text/html;charset=GBK" language="java" %>那么在浏览器里打开这个页面时浏览器会自动设置页面编码为GBK

    2、说说UTF-8

    虽然我们主要处理汉字,但是也有遇到其他诸如日语,阿拉伯语,俄语等的情况。那么用GBK进行字符处理肯定是不行的。所以现在比较流行的就是用UTF-8来进行。那么为什么UTF-8就可以解决国际化的问题呢?

    这个问题简单解释就是 大多语言的字符都可以在UTF-8的字符表中找到对应的位置。比如如果我们用GBK来处理俄语之所以不行就是因为俄语的某些字符在GBK的编码表里没有对应的,所以也就无所适从。 由于我对编码理论不是很熟悉,所以不能深入去解释。

    基于UTF-8的解决方案的做法就是页面和字符的处理全部采用UTF-8,而唯一比较麻烦的就是页面的汉字或者放在资源文件中,或者在页面上,当然都得先进行相应的编码转换,这里就不再说了。

    3、更方便的解决方案

    第一种:request.setCharacterEncoding("GBK");String htmlContent=request.getParameter("content");即在获取参数之前,主动设置CharacterEncoding,这就使得在解析参数时,会按着给定的编码进行。

    第二种:filter,这个现在用的比较多但是其背后理论和第一种是一样的,只是换了一种实现方式而已

本文作者:
« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3