老生常谈之HTTP乱码问题

最后的结论?

对于get请求 在Servlet中调用request.setCharacterEncoding()设置编码是没有意义的不管你使用任何编码方式对于你的数据解码没有任何影响

问题的引出,在tomcat9之后,不管你在setCharacterEncoding()设置什么编码都不会乱码,哪怕是最基础的ACSII,那有人就说了,那不挺好的,不乱吗就行了呗;

没办法,我喜欢问自己为什么,凭什么不乱吗,那设置这个编码有什么意义?

网上找了一下,只有问为什么乱码,没人问为啥不乱码,总有人会说设置编码要放在获取参数前,诸如此类,说的一套一套,人云亦云!

带着这个问题我写了一个简单的socket程序 目的就是想服务器发送一个HTTP请求手动控制编码环节,

第一次测试,直接把中文写在url中,最后用utf-8来发送给服务器

服务器返回400请求解析失败

Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

这啥玩意?,原来RFC 3986中规定URL中只允许包含24个英文字母以及基本的字符,中文编码后其对应的二进制超过了规定返回导致报错,这一点很重要

这导致了我们在URL中不能传递中文参数,那不行,得解决这个问题,于是就出现了URLEncoding

URLEncoding

我们想要在url中包含中文,就必须先把中文转换为基本的字符,其原理是字符转为16进制的字符然后在每个字节前加一个%,就像下面这样

结果:%e4%bd%a0

把这个字符拿到网页中URL解码

没问题

模拟浏览器发送请求

注意这里数据依然是字符串格式的,要想通过socket发送则必须在进行编码,例如我们要请求的地址为/untitled3/TestServlet?username=你

我们先要使用URLEncoding将转为符合RFC 3986要求的字符串,替换到原本的位置去

处理过的地址为/untitled3/TestServlet?username=%e4%bd%a0

然后在把URL放到我们的HTTP请求报文中

服务器端doGet方法

解析成功

ok服务器已经成功解析了中文但是注意我在服务器端指定的编码为ASCII,这也是我要解决的主要问题,

总结时间:

客户端发送请求时数据一共经过了两次编码,

  • 第一次是把中文转为符合要求的字符(URLEncoding),注意还是字符
  • 第二次就是我们把整个HTTP数据进行统一编码为二进制

那么我们服务器端执行的这个setCharacterEncoding是用在那一次呢?

没错就是第一次,这就是为什么我们无论设置那种编码都不会导致乱码的原因了,

决定是否乱码的核心在第二次,在上面的例子中服务器先是用ASCII来解析http整个数据包,其中的的URL为/untitled3/TestServlet?username=%e4%bd%a0

对于这个URL而言任何编码表都能解析,不会乱码,接下里就需要将里面的参数部分(问号后面的)拿出来进行反向URLEncoding,此时的反向解析就是最重要的要从字符串中提取16进制数据,在通过编码表进行解码 ,

而tomcat9中默认的解码方式为UTF-8,到这里你应该明白了,为什么不乱吗?

说人话:

简单的说:对于get请求而言,调用setCharacterEncoding是没有任何意义的,如果我们要控制URLEncoding的解码方式,必须通过server.xml来修改

在啰嗦一下,对于post请求,我们的数据是包含在请求体中的所以,上面的配置对于post请求没有效果,那如果请求体中包含了中文怎么办,很简单只要与客户端保持相同的解码方式即可,使用request.setCharacterEncoding方法来设置,

还有问题,为什么post就可以呢? 因为RFC 3986只是说URL中的字符字节必须在某个范围内,没有限制请求体中的数据范围,所以对于请求体,你爱放中就放中文,

你也可以这么理解request.setCharacterEncoding只是用来设置请求体的解码方式,对于url中的参数解码方式就必须同 server.xml来配置

另外对于post服务器其实可以不设置编码只要客户端post请求头的ContentType中声明了编码即可,这也侧面印证了post才是用来给服务器传递数据的更优方法,

那为什么大家喜欢用get呢?不知道,或许是因为简单?,累了就到这里吧

补充下1楼的解决乱码方案也是可以的

其原理是将使用错误码表解码的结果还原为二进制,再用正确码表重新解码

当然你不管用哪种方式都必须与对方采用相同的编码方式

只要理解了其中原理,那乱码问题也就迎刃而解了

揉碎HTTP编码过程,从此不乱码的更多相关文章

  1. Mysql 的字符编码机制、中文乱码问题及解决方案【转载】

    本文转载自:http://hi.baidu.com/huabinyin/item/7f51e462df565c97c4d24929.感谢作者及相关博主.        相信很多朋友都会对字符编码敬而远 ...

  2. GET&&POST请求编码过程

    编码.解码 我们在开发过程中不可避免的一个话题就是编码和解码,那么什么是编码什么是解码呢?为什么要进行编码和解码呢?下面我们一一分析! 编码和解码的概念 编码是信息从一种形式或格式转换为另一种形式的过 ...

  3. post和get提交服务器编码过程

    参考资料:http://blog.csdn.net/z55887/article/details/46975679 先说出一个知识点: 如果浏览器端编码是UTF-8,那在服务器端解决乱码问题的方法有两 ...

  4. 使用ffmpeg视频编码过程中踩的一个坑

           今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果:                   ...

  5. 推荐2一个在Java编码过程中得心应手的工具

    推荐2在编码过程中的减小不仅编码的量,挺easy工具上手:可适用Java反思与单探头Assert. 1 Mirror:Java反思 简单介绍 官网:http://projetos.vidageek.n ...

  6. PHP使用UTF8编码读取ACCESS的乱码问题解决方案(转)

    PHP使用UTF8编码读取ACCESS的乱码问题解决方案 http://it.xwstudy.com/readnews.php?id=627 来源:本站编辑 发布日期:2013-05-27 已有 17 ...

  7. qt creator修改程序编码(解决中文乱码问题)的方法

    qt creator修改程序编码(解决中文乱码问题)的方法 qt creator修改程序编码的功能有几处. 1.edit - select encoding 选择载入(显示)编码和储存编码,其中GB2 ...

  8. python基础系列教程——Python中的编码问题,中文乱码问题

    python基础系列教程——Python中的编码问题,中文乱码问题 如果不声明编码,则中文会报错,即使是注释也会报错. # -*- coding: UTF-8 -*- 或者 #coding=utf-8 ...

  9. Linux Centos7设置UTF-8编码,防止中文乱码

    Linux Centos7设置UTF-8编码,防止中文乱码 # localeLANG=zh_CN.gb2312LC_CTYPE="zh_CN.gb2312"LC_NUMERIC=& ...

随机推荐

  1. [Java]Java类和对象内存分配详解

    描述 代码说明: 一.当Person p1 = new Person();第一次被调用时需要做两件事: 1.先判断类加载器是否加载过Person类,如果没有则加载到Person类型到方法区 2.在堆中 ...

  2. NOIP模拟测试19考试反思

    这次考试是存在很大问题的,(如果不是T1T2出乎意料地A了,鬼知道会发生什么) T2A是情理之中,考试的时候测的极限数据跑的很快(无论m什么范围),但是T1真的...... T3没有分配太多的时间+没 ...

  3. Hybrid App: 了解JavaScript如何与Native实现混合开发

    一.简介 Hybrid Development混合开发是目前移动端开发异常火热的新兴技术,它能够实现跨平台开发,极大地节约了人力和资源成本.跨平台开发催生了很多新的开源框架,就目前而言,在混合开发中比 ...

  4. 算法笔记codeup-Contest100000567

    A 1 #include <stdio.h> 2 #include <math.h> 3 int main() 4 { 5 double a=0; 6 double b=0; ...

  5. kubernetes 控制器详解【持续完善中】

    目录 资源创建详解 一:Pod及常用参数 1.简介 2.模板 3.删除pod 4.设置Pod主机名 5.镜像拉取策略(ImagePullPolicy) 二:RC 1.简介 2.模板 三:Deploym ...

  6. 设置eclipse的字体大小

    window->preferences->general->Appearance->Colors and Fonts->basic->text font->点 ...

  7. Maven系列第6篇:生命周期和插件详解,此篇看过之后在maven的理解上可以超越同级别90%的人!

    maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能. 这是maven系列第6篇. 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部 ...

  8. mybatis的parameterType为map,map里带有多个list

    我写这个主要是为了解决sql注入 原sql有sql注入, 结果:select req_msg_id from account_message_info where req_msg_id in ('12 ...

  9. Appium+python自动化(四十二)-Appium自动化测试框架综合实践- 寿终正寝完结篇(超详解)

    1.简介 按照上一篇的计划,今天给小伙伴们分享执行测试用例,生成测试报告,以及自动化平台.今天这篇分享讲解完.Appium自动化测试框架就要告一段落了. 2.执行测试用例&报告生成 测试报告, ...

  10. BootStrap中的collapse插件堆叠效果

    通过网络上的一系列查找,总结出的collapse插件堆叠效果(网上没有找到,只能自己弄了,帮助那些和我遇到一样状况的同学) 首先感谢一位网友的知识总结给了我灵感,在这里先帮他推荐一波(https:// ...