javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码

乱码是一个经常出现的问题

请求中,参数传递的过程中也是经常出现乱码的问题

本文主要整理了请求乱码中的问题以及解决思路

先要理解一个概念前提:

编码就是把图形变成数值码所以说:

图形的字符  ---->  字节数组  是编码

字节数组-------->图形的字符 是解码


为什么会乱码?

计算机数据只能是二进制的

数值类型的数据转换成二进制很简单,

但字符类型如何转换成二进制呢?这就需要使用字符编码!

在编码表中,每个字符都有对应的编码,编码是整数,最终在计算机中存储的是字符的编码

而不是字符本身(因为计算机数据都是二进制数值,所以字符本身是无法存储的)。

假如说两种编码

红框1    橘色框 2 ,不用较真数值是多少,符号是什么,只为表达概念

每种编码方式内部,字符和数值是一 一对应的

但是如果使用A------>65进行编码 

然后使用      65------>$ 另外一种解码方式解读,显然A就变成了$,这不就是乱码了么

不同的编码方式不同,同一个字符的二进制也基本是不同的,如果没有正确的进行解读,那么就会出现乱码问题

发起请求时,不管是什么字符,计算机都不认识,必须编码转换为数值.

接收到请求的地方想要使用,就必须在编码成为字符

乱码的根本在于 编码和解码方式的前后不一致


如何解决乱码问题,也就是正确编码的问题

请求响应的编码问题

1.直接在地址栏中给出中文

请求数据是由客户端浏览器发送服务器的,请求数据的编码是由浏览器决定的。

例如在浏览器地址栏中给出:http://localhost:8080/servlet/AServlet?name=张三,那么其中“张三”是什么编码的呢?

不同浏览器使用不同的编码,所以这是不确定的!

Chrome:使用UTF-8;

IE:使用GB2312;

FireFox:使用GB2312;

(这几个说的不一定对,反正重点是要知道,不同的浏览器,直接地址栏输入的参数的字符编码是不固定的,也说不定未来或许会统一)

2. 响应编码

当使用response.getWriter()来向客户端发送字符数据时,如果在之前没有设置编码,那么默认使用iso,因为iso不支持中文,一定乱码

response.getWriter().println("ServletA");

response.getWriter().println("你好");

在使用response.getWriter()之前

可以使用response.setCharacterEncoding()来设置字符流的编码为gbk或utf-8

当然我们通常会选择utf-8

response.setCharacterEncoding("utf-8");

这样使用response.getWriter()发送的字符就是使用utf-8编码的。但还是会出现乱码!

因为浏览器并不知道服务器发送过来的是什么编码的数据!这时浏览器一般会使用gbk来解码,所以乱码!

所以需要设置响应的编码,以及通知浏览器应该使用何种编码方式去解读

在使用response.getWriter()之前

可以使用

response.setHeader("Content-type","text/html;charset=utf-8")

来设置响应头,通知浏览器服务器这边使用的是utf-8编码

而且在调用setHeader()后

还会自动执行setCharacterEncding()方法。

这样浏览器会使用utf-8解码,所以就不会乱码了!

response.setHeader("Content-type","text/html;charset=utf-8");

response.getWriter().println("ServletA");

response.getWriter().println("你好");

setHeader("Content-Type", "text/html;charset=utf-8")的快捷方法是:

response.setContentType("text/html;charset=utf-8);

总结:输出响应,想要不乱码

只需要在使用getWriter()方法前:

response.setContentType("text/html;charset=utf-8);

如果是静态页面中,使用<meta>来设置content-type响应头,例如:

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

补充说明: 

UTF-8 中  三个字节表示一个中文

E4BDA0=你  E5A5BD=好  

发送的时候是UTF-8 也就是发送的  E4BDA0E5A5BD

GBK中两个字节表示一个中文

也就是

E4BD   A0E5    A5BD

查表可得:


3.在页面中发出请求

通常向服务器发送请求数据都需要先请求一个页面,然后用户在页面中输入数据。

页面中有超链接和表单,通过超链接和表单就可以向服务器发送数据了。

用户在页面中输入的数据是由页面本身的编码决定的 又因为页面是服务器发送到客户端浏览器的,所以这个页面本身的编码又由服务器响应决定

用户在页面中输入的数据是由页面本身的编码决定的 又因为页面是服务器发送到客户端浏览器的,所以这个页面本身的编码又由服务器响应决定

用户在页面中输入的数据是由页面本身的编码决定的 又因为页面是服务器发送到客户端浏览器的,所以这个页面本身的编码又由服务器响应决定

服务器返回当前页面的响应时,设置响应头content-type,指定当前页面的编码为utf-8

如果设置了那么可以通过浏览器查看响应信息看到

如果是

Content-Type:text/html;  而没有后面的charset=utf-8

可以看下输出的响应页面上是否有这一句,也是一样的

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

归根结底是看响应中是否有 Content-type utf-8 的相关信息   有了charset的信息,就按照他来

4.GET请求解读编码

当客户端通过GET请求发送数据给服务器时

使用request.getParameter()获取的数据是被服务器误认为ISO-8859-1编码的

也就是说客户端发送过来的数据无论是UTF-8还是GBK,服务器都认为是ISO-8859-1  

tomcat8以后默认编码格式是utf-8;7之前的都是iso8859-1

是否需要在使用request.getParameter()获取数据后,再转发成正确的编码 要看你实际使用的tomcat 版本 例如客户端以UTF-8发送的数据,使用tomcat7 以及之前的版本 需要使用如下转码方式:

String name = request.getParameter(“name”);

name = new String(name.getBytes(“iso-8859-1”), “utf-8”);

重点是要理解逻辑:

 tomcat 默认的使用某种编码对传递过来的数据进行了解码

 如果说正好是我们传递过来的,那么不需要做处理

 如果不是,就需要按照他解码的方式,重新编码成字符数组,在使用字节数组 按照编码规则重新解码为字符串

 (字符到字节数组是编码   字节数组到字符是解码)

示例:

在utf8页面上 get请求  http://127.0.0.1:8080/servlet/ServletA?name=张三

Servlet中

String name = request.getParameter("name");
System.out.println("request.getParameter(\"name\"): "+name);

name = new String(name.getBytes("iso-8859-1"), "utf-8");
System.out.println("new String(name.getBytes(\"iso-8859-1\"), \"utf-8\"): "+name);

页面是utf8 自然请求是utf8编码规则

tomcat8  默认utf8  解码

tomcat7 默认iso

当然也是可以修改Server.xml中设置URIEncoding的值为UTF-8

但是不建议这么做,代码不能依赖tomcat的设置,严重破坏可移植性

5.POST请求解读编码

当客户端通过POST请求发送数据给服务器时,可以在使用request.getParameter()获取请求参数之前

先通过request.setCharacterEncoding()来指定编码,然后再使用reuqest.getParameter()方法来获取请求参数

那么就是用指定的编码来读取了。

也就是说,如果是POST请求,服务器可以指定编码!

但如果没有指定编码,那么仍旧也还是使用默认的来解读

request.setCharacterEncoding(“utf-8”);
String name = request.getParameter(“name”);

6. URL编码

POST表单提交的类型:

Content-Type: application/x-www-form-urlencoded

  • 首先,Content-Type 被指定为 application/x-www-form-urlencoded;
  • 其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
  • 大部分服务端语言都对这种方式有很好的支持。

其实就是把中文转换成%后面跟随两位的16进制。

在客户端和服务器之间传递中文时需要把它转换成网络适合的方式

不是字符编码,客户端与服务器之间传递参数用的一种方式

URL编码需要先指定一种字符编码,把字符串解码后,得到byte[],然后把小于0的字节+256,再转换成16进制。前面再添加一个%。

* POST请求默认就使用URL编码!tomcat会自动使用URL解码!

* URL编码:String username = URLEncoder.encode(username, "utf-8"); * URL解码:String username = URLDecoder.decode(username, "utf-8");

这种场景下,编码和解码都是自动的,不需要手动干预

浏览器中显示的"张三"

新建一个测试类 main方法中执行打印结果一样

public static void main(String[] args) throws UnsupportedEncodingException {
String s= "张三";
System.out.println(URLEncoder.encode(s,"UTF-8"));
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏linux、Python学习

十分钟带你了解 Python3 多线程核心知识

每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

23900
来自专栏向治洪

命令模式

命令模式定义 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 作用 命令模式主要应用于将行...

20390
来自专栏Java编程技术

Dubbo剖析-增强SPI的实现

在Duboo剖析-整体架构分析中介绍了dubbo中除了Service 和 Config 层为 API外,其他各层均为SPI,为SPI意味着下面各层都是组件化可以...

15410
来自专栏深度学习之tensorflow实战篇

python如何保存矩阵,保存matrix,保存numpy.ndarray

问题:如何将array保存到txt文件中?如何将存到txt文件中的数据读出为ndarray类型?python如何保存矩阵,保存matrix,保存numpy.nd...

3.5K60
来自专栏电光石火

关于PHP字符编码的函数区别

在以前的学习当中,比方说有一次的写采集过程中转换字符的编码的时候老是失败,转换的结果总没有完全输出,后来经过网络查询得知是iconv有一个“-”漏洞,所以我们有...

27680
来自专栏从零开始学自动化测试

pytest文档2-用例运行规则

1.查看pytest命令行参数,可以用pytest -h 或pytest —help查看

26130
来自专栏决胜机器学习

PHP面向对象核心(三)——反射、异常处理

PHP面向对象核心(三) (原创内容,转载请注明来源,谢谢) 五、反射 1、反射即PHP运行过程中,提取出关于类、方法、属性、参数等信息,包括 注释信息。动态获...

368120
来自专栏杂七杂八

列表、字典、集合中筛选数据

传统迭代法 data = [1,5,-3,-2,8,0,9] res = [] for x in data: if x >=0: res...

39060
来自专栏博客园

Asp.Net Web API(三)

    在Asp.Net Web API中,一个控制器就是一个处理HTTP请求的类,控制器的public方法就被叫做action方法或简单的Action。当We...

19250
来自专栏流柯技术学院

Loadrunner中web_find和web_reg_find函数的使用与区别

总结一下Loadrunner中的检查点函数,主要介绍两个函数:web_find()和web_reg_find();这两个函数均用于内容的查找,但两者也有本质的区...

24320

扫码关注云+社区

领取腾讯云代金券