web中的乱码问题

转载参考于:  https://www.cnblogs.com/LuckyBao/p/5950607.html 

https://www.cnblogs.com/keyi/p/6365649.html

https://www.cnblogs.com/liushuncheng/p/6891307.html 

https://blog.csdn.net/afgasdg/article/details/6941712                                   

                                        第一章 什么是编码

我们平时看到的是字符串,但是字符串在计算机中并不能进行存储,要把字符转换成字节存储在计算机里,需要一定的标准,这个标准定义该怎么转换,我们把这种标准叫做字符集.

常用的有UTF-8字符集,字符“中”使用UTF-8字符集映射的字节为:E4 B8 AD 三个字节,同样反过来,这三个字节通过UTF-8字符集映射便能得到“中”这个字符.

不同的字符集映射规则不一样,能表示的范围也不一样,例如“中”在GB2312中对应的字节表示为:D6 D0 两个字节,字符和字节之间的转换,描述为编码和解码:

字符->字节:编码,例如:“中”的UTF-8编码为 E4 B8 AD

字节->字符:解码,例如:字节数组D0 D6根据GB2312解码为字符“中”

还有一类编码称为URI编码和URI解码,不过URI编码和解码不是字符串和字节流之间的转换,而是由一个字符串表示另一个字符串,例如:

“中”的UTF-8 URI编码为 %E4%B8%AD

字符串%E4%B8%AD根据UTF-8进行URI解码为字符“中”

可以看出来,URI编码就是将一个字符串用%+对应字符集的编码组织的字符串来表示的,在Java中String类有两个常用的方法进行编码和解码:

getBytes :例如“中”.getBytes(“字符集”),根据指定的字符集进行编码

String(bytes[],”字符集”):根据自定的字符集对字节数组进行解码

                                第二章 web上为什么会出现乱码问题

2.1 乱码问题简介

浏览器和服务器通过网络相连,浏览器请求编码成字节流在网络上传输,应用服务器接收到浏览器发送过来的字节流后通过相应的字符集再解码为字符串,如果浏览器和服务器端使用了不同的字符集或者不兼容的字符集就会导致乱码问题,例如,浏览器将“中”按照UTF-8编码为字节E4 B8 AD,在网络上传输,应用服务器接收到字节后按照GBK进行解码,那么前两个字节首先被解码为“涓”了,这只是个简单的过程说明,实际的过程比这要复杂。

因此要搞清web的编码问题,很有必要先弄清请求的过程和过程中的编码和解码。web是请求响应模式,用户操作浏览器,例如点击一个按钮提交表单,或者点击一个超链接,这时浏览器就会向应用服务器发送请求,servlet容器接受到请求后,根据web.xml的设置调用相应的应用程序,应用程序根据发送的请求进行一定的逻辑处理后返回给浏览器一段html代码,浏览器根据html解析并展现给用户,这就是一次请求应答的过程.

                       第三章 数据从浏览器传递到服务器时的编码情况

3.1 表单提交

表单提交又分为post和get两种方法,

采用post方法时,浏览器会将表单中的字符串,采用页面的字符集编码为字节流发送到服务器.

采用get方法时,浏览器首先会将表单中的值通过页面的字符集进行URI编码后拼接到action的URL后面发送到应用服务器.

3.2 放在超链接中提交

在超链接中一般会传递参数,有时候也会传递中文,如这段代码:<a href="http://www.google.com/?test=中">link</a>,其中的“中”不属于asc字符集,因此浏览器会对其进行URI编码以进行传送.

但是不同的浏览器采用的字符集却不一样,有的浏览器采用的编码方式和页面编码一样,页面编码就是类似于在页面中标明content="text/html; charset=utf-8这种的,有的编码与系统有关.

UTF-8编码为 E4 B8 AD      GB2312编码为D6 D6

为了避免浏览器进行不确定的URI编码,需要在程序中将中文进行URI编码后在放到URL中,JavaScript提供了encodeURI()函数,它提供的是UTF-8的URI编码,也可以通过java.net.URLEncoder.encode(str,"字符集")进行编码.

3.3 ajax提交

1. GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送给WEB服务器。当然在Ajax请求中,这种区别对用户是不可见的。

具体的get与post的编码方式与第一种类似.

                             第四章 服务器获取参数时的编码情况

       在servlet中一般通过request.getParameter()来获得浏览器发送过来的参数,需要注意的是,服务器Servlet的最底层接受到的是InputStream,也就是字节流,request.getParameter()返回的是一个字符串,因此在getParameter()方法的内部存在解码的过程,而解码所采用的字符集根据应用服务器和操作系统的不同有可能不同.ServletRequest接口提供了一个方法:setCharacterEncoding()来设置getParameter解码的字符集,这个方法必需在getParameter之前调用.

       通过查看tomcat的源代码发现getParameter在第一次调用时会去初始化一个map的对象,map中存储的就是参数名和参数值,这些值就是根据设置的字符集进行解码的,一旦这些对象解码完毕,下次调用就直接从map中取值,而不需要重新去解码了,所以setCharacterEncoding必需在getParameter之前调用才有作用.

     但是这个方法在低版本的tomcat中只对post方法有效,对get就无效了.对于get的话,request设置编码无效,即使用setCharacterEncoding设置了UTF-8还是会去查ISO8859-1,所以我们需要在tomcat中的conf中的server.xml中设置编码,据说tomcat8的默认编码变成了utf8,有待测试.

 或者就是编码再转码.

或者是如下设置,request的setCharacterEncoding设置什么编码,连接器就用什么编码

对于别的服务器,设置setCharacterEncoding还是有点用的

提一个小细节:URL地址后面如果跟了中文数据,一定要经过URL编码。表单提交的参数有中文数据,浏览器会自动帮我们编码,但如果是通过链接直接带中文参数,浏览器是不会帮我们编码的,我们应该通过URLEncoding.encode(,"UTF-8")先编码

                                  第五章 数据库上的乱码问题

一般会在连接数据库的字符串后加上useUnicode=true&characterEncoding=UTF-8

解释:存数据时数据库在存放项目数据的时候会先用UTF-8格式将数据解码成字节码,然后再将解码后的字节码重新使用GBK编码存放到数据库中

取数据时在从数据库中取数据的时候,数据库会先将数据库中的数据按GBK格式解码成字节码,然后再将解码后的字节码重新按UTF-8格式编码数据,最后再将数据返回给客户端。

然后再将数据库与表的编码格式设置为UTF-8就行了.

                           第六章 数据从浏览器返回时的编码控制

服务器向浏览器发送的也是经过编码成字节流在网络上传输,浏览器接收到字节流之后使用指定的字符集解码成字符串再进行展现,如果这两个环节的字符集不一致也会导致乱码的问题.

数据从服务器返回给浏览器的编码格式可以通过response.setCharacterEncoding("UTF-8");来设置

浏览器使用UTF-8格式进行的解码可以进行如下设置

如果是jsp可以通过<%@ page contentType="text/html; charset=UTF-8" language="java" %>来进行设置,

静态文件可以通过 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 进行设置,

如果在servlet中直接进行输出,可以通过response.setCharacterEncoding("UTF-8"),setContentType("text/html;charset=UTF-8"),setHeader("Content-Type","text/html;charset=UTF-8")进行设置

额外的知识:

我们在jsp中一般会进行如下图所示的配置

pageEncoding是jsp文件本身的编码
contentType的charset是指浏览器解码的格式(不确定).

pageEncoding与contentType的问题请参考https://blog.csdn.net/dragon4s/article/details/6604624

猜你喜欢

转载自blog.csdn.net/q610376681/article/details/83001681