Servlet是一种古老的Java Web技能,在开拓中除了祖传的项目,已经很少见到它的身影,但是作为Java Web的主要组成部分,Servlet还是值得深入学习的,形形色色框架再好用,底层终归还是Servlet,Service ,JDBC这些根本的东西,学好Servlet有助于大家审理理解框架的底层源码深入学习,也为大家在口试过程中取得一线活气,但是在servlet常常会碰着一些乱码问题,本日我们来聊聊办理Servlet中的乱码问题。

一、request要求参数涌现的乱码问题

get要求:

get要求的参数是在url后面提交过来的,也便是在要求行中,

jsp获取request返回的参数乱码深刻进修Java Web二Servlet中Request和Response乱码解决计划 CSS

MyServlet是一个普通的Servlet,浏览器访问它时,利用get要求办法提交了一个name=小明的参数值,在doGet中获取该参数值,并且打印到掌握台,创造涌现乱码

涌现乱码的缘故原由:

条件知识:须要理解码表,编码,解码这三个名词的意思。
我大略说一下常规的,

码表:是一种规则,用来让我们看得懂的措辞转换为电脑能够认识的措辞的一种规则,有很多中码表,IS0-8859-1,GBK,UTF-8,UTF-16等一系列码表,比如GBK,UTF-8,UTF-16都可以标识一个汉字,而如果要标识英文,就可以用IS0-8859-1等别的码表。

编码:将我们看得懂的措辞转换为电脑能够认识的措辞。
这个过程便是编码的浸染

解码:将电脑认识的措辞转换为我们能看得懂得措辞。
这个过程便是解码的浸染

详细请参考这篇博文。

这里只能够代表经由一次编码例子,有些程序中,会将一个汉字或者一个字母用不同的码表连续编码几次,那么第一次编码还是上面所说的浸染,第二次编码的话,便是将电脑能够认识的措辞转换为电脑能够认识的措辞(转换规则不同),那么该解码过程,就必须要经由两次解码,也便是编码的逆过程,下面这个例子就很好的解释了这个问题。

浏览器利用的是UTF-8码表,通过http协议传输,http协议只支持IS0-8859-1,到了做事器,默认也是利用的是IS0-8859-1的码表,看图

也便是三个过程,经历了两次编码,以是就须要进行两次解码,

1、浏览器将\"大众小明\"大众利用UTF-8码表进行编码(由于小明这个是汉字,以是利用能标识中文的码表,这也是我们可以在浏览器上可以手动设置的,如果利用了不能标识中文的码表,那么就将会涌现乱码,由于码表中找不到中文对应的打算机符号,就可能会用??等其他符号表示),编码后得到的为 1234 ,将其通过http协议传输。

2、在http协议传输,只能用ISO-8859-1码表中所代表的符号,以是会将我们原来的1234再次进行一次编码,这次利用的是ISO-8859-1,得到的为 ???? ,然后传输到做事器

3、做事器获取到该数据是经由了两次编码后得到的数据,以是必须跟原来编码的过程逆过来解码,先是UTF-8编码,然后在ISO-8859-1编码,那么解码的过程,就必须是先ISO-8859-1解码,然后在用UTF-8解码,这样就能够得到精确的数据。
????.getBytes(\"大众ISO-8859-1\公众);//第一次解码,转换为电脑能够识别的措辞, new String(1234,\"大众UTF-8\公众);//第二次解码,转换为我们认识的措辞

办理代码

Post要求:

post要求办法的参数是在要求体中,相对付get要求大略很多,没有经由http协议这一步的编码过程,以是只须要在做事器端,设置做事器解码的码表跟浏览器编码的码表是一样的就行了,在这里浏览器利用的是UTF-8码表编码,那么做事器端就设置解码所用码表也为UTF-8就OK了

设置做事器端利用UTF-8码表解码

request.setCharacterEncoding(\"大众UTF-8\公众); //命令Tomcat利用UTF-8码表解码,而不用默认的ISO-8859-1了。

以是在很多时候,在doPost方法的第一句,便是这句代码,防止获取要求参数时乱码。

总结要求参数乱码问题

get要乞降post要求办法的中文乱码问题处理办法不同

get:要求参数在要求行中,涉及了http协议,手动办理乱码问题,知道涌现乱码的根本缘故原由,对症下药,其事理便是进行两次编码,两次解码的过程

new String(xxx.getBytes(\"大众ISO-8859-1\"大众),\"大众UTF-8\公众);

post:要求参数在要求体中,利用servlet API办理乱码问题,其事理便是一次编码一次解码,命令tomcat利用特定的码表解码。

request.setCharaterEncoding(\公众UTF-8\"大众);

二、response相应回浏览器涌现的中文乱码。

首先先容一下,response工具是如何向浏览器发送数据的。
两种方法,一种getOutputStream,一种getWrite。

ServletOutputStream getOutputStream(); //获取输出字节流。
供应write() 和 print() 两个输出方法

PrintWriter getWrite(); //获取输出字符流 供应write() 和 print()两个输出方法

print()方法底层都是利用write()方法的,相称于print()方法便是将write()方法进行了封装,使开拓者更方便快捷的利用,想输出什么,就直接选择得当的print()方法,而不用考虑如何转换字节。

1、ServeltOutputStream getOutputStream();

不能直接输出中文,直接输出中文会报非常,

报非常的源代码

办理:

resp.getoutputStream().write(\公众哈哈哈,我要输出到浏览器\"大众.getBytes(\"大众UTF-8\"大众));

将要输出的汉字先用UTF-8进行编码,而不用让tomcat来进行编码,这样如果浏览器用的是UTF-8码表进行解码的话,那么就会精确输出,如果浏览器用的不是UTF-8,那么还是会涌现乱码,以是说这个关键要看浏览器用的什么码表,这个就不太好,这里还要把稳一点,便是利用的是write(byte)方法,由于print()方法没有输出byte类型的方法。

2、PrintWriter getWrite();

直接输出中文,不会报非常,但是肯定会报非常,由于用ISO-8859-1的码表不能标识中文,一开始便是错的,怎么解码编码读没用了

有三种方法来让其精确输出中文

1、利用Servlet API response.setCharacterEncoding()

response.setCharacterEncoding(\"大众UTF-8\公众); //让tomcat将我们要相应到浏览器的中文用UTF-8进行编码,而不该用默认的ISO-8859-1了,这个还是要取决于浏览器是不是用的UTF-8的码表,跟上面的一样有缺陷

2、关照tomcat和浏览器都利用同一张码表

response.setHeader(\"大众content-type\"大众,\"大众text/html;charset=uft-8\公众); //手动设置相应内容,关照tomcat和浏览器利用utf-8来进行编码和解码。

charset=uft-8就相称于response.setCharacterEncoding(\"大众UTF-8\公众);//关照tomcat利用utf-8进行编码

response.setHeader(\"大众content-type\公众,\公众text/html;charset=uft-8\"大众);//合起来,便是既关照tomcat用utf-8编码,又关照浏览器用UTF-8进行解码。

response.setContentType(\"大众text/html;charset=uft-8\"大众); //利用Servlet API 来关照tomcaat和逼迫浏览器利用UTF-8来进行编码解码,这个的底层代码便是上一行的代码,进行了大略的封装而已。

3、关照tomcat,在利用html<meta>关照浏览器 (html源码),把稳:<meta>建议浏览器该当利用编码,不能逼迫哀求

进行两步

以是response在相应时,只要关照tomcat和浏览器利用同一张码表,一样平常利用第二种方法,那么就可以办理相应的乱码问题了

三、总结

在上面讲解的时候总是看起来很繁琐,实在知道了个中的事理,很大略,现在来总结一下,

要求乱码

get要求:

经由了两次编码,以是就要两次解码

第一次解码:xxx.getBytes(\"大众ISO-8859-1\"大众);得到yyy

第二次解码:new String(yyy,\公众utf-8\"大众);

连续写:new String(xxx.getBytes(\"大众ISO-8859-1\"大众),\"大众UTF-8\公众);

post要求:

只经由一次编码,以是也就只要一次解码,利用Servlet API request.setCharacterEncoding();

request.setCharacterEncoding(\公众UTF-8\"大众); //不一定办理,取决于浏览器是用什么码表来编码,浏览器用UTF-8,那么这里就写UTF-8。

相应乱码

getOutputStream();

利用该字节输出流,不能直接输出中文,会出非常,要想输出中文,办理方法如下

办理:getOutputStream().write(xxx.getBytes(\"大众UTF-8\"大众)); //手动将中文用UTF-8码表编码,变成字节传输,变成字节后,就不会报非常,并且tomcat也不会在编码,由于已经编码过了,以是到浏览器后,如果浏览器利用的是UTF-8码表解码,那么就不会涌现中文乱码,反之则涌现中文乱码,以是这个方法,不能完备担保中文不乱码

getWrite();

利用字符输出流,能直接输出中文,不会出非常,但是会涌现乱码。
能用三种方法办理,一贯利用第二种方法

办理:关照tomcat和浏览器利用同一张码表。

response.setContentType(\"大众text/html;charset=utf-8\"大众); //关照浏览器利用UTF-8解码

关照tomcat和浏览器利用UTF-8编码和解码。
这个方法的底层事理是这句话:response.setHeader(\公众contentType\"大众,\"大众text/html;charset=utf-8\"大众);

把稳:getOutputStream()和getWrite() 这两个方法不能够同时利用,一次只能利用一个,否则报非常。

上一篇:深入学习Java Web(一):深入理解Servlet