为什么80%的码农都做不了架构师?>>>   

由来

在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出来的中文显示到页面正常,锁定肯定是request对象那里出了问题。后来经过排查,发现是我封装的框架中出了问题,总结为在setCharacterEncoding方法之前,调用了getParameter方法,导致字符集改变失败。没看过Tomcat实现Servlet的源码,貌似是一旦调用getParameter方法Request的参数就会全部被解析,从而再调用setCharacterEncoding就无效了。

原理解析

其实编码问题本质还是两点:

  1. 浏览器在封装Http请求的时候的编码和服务器在解析Http请求编码不一致
  2. 服务器返回数据的时候编码和浏览器解析不同。

那么我们就从这两点入手解析。

浏览器请求

在点击提交表单的那一刻,浏览器把表单内容封装成一个Http请求,数据通过a=1&b=2这样的形式直接请求服务器,表单值会被浏览器最一次urlencode,对于不同的请求方式编码不同:

Get和Post请求

浏览器会读取页面的编码(页面编码会在Content-type头中体现),用此编码对表单值做urlencode,那么到服务器的编码方式就是你Content-Type里的编码。很多通过JS提交表单为了规避浏览器的urlencode带来的编码混淆,会对数据首先做一次urlencode,这样在服务器上做一次urldecode既可(因为js做完urlencode后内容为ASCII字符,所以这样的字符无论浏览器用什么编码解码出来都是一样的)

AJAX请求

在Jquery中AJAX请求全部使用utf8编码封装请求,如果你的页面和项目用的非utf8编码,一定会出现乱码

浏览器地址栏直接输入带参数的地址

这种情况就比较复杂,不同的浏览器编码也不相同。Chrome之类的浏览器默认使用utf8编码(urlencode),而IE则使用GBK(死变态IE!!!)。

服务器端解码

对于服务器端我在此只讨论Servlet。

Get请求

对于Get请求,有两种方式解码:

  1. 在Servlet容器中设置,例如Tomcat设置URIEncoding="UTF-8",就会对Get请求用utf8解码(貌似Tomcat7会报无效,具体解决请百度,反正我不同这种方法)
  2. String name = new String(request.getParameter("name").getBytes("iso-8859-1"),"GBK"));第一个编码就是你Servlet容器(例如Tomcat)里设置的编码,默认iso-8859-1,第二个参数就是你浏览器使用的编码格式。如果你用表单提交,那这个编码就是页面的编码(Content-Type里的charset=XXX),如果你直接用浏览器地址栏里敲,恭喜你,你得判断userAgent来使用不同编码了。这也是我为啥不提倡第一种方式,因为它遇到浏览器直接敲出来的参数就非常不灵活。

至于为什么要使用getBytes("iso-8859-1"),是因为在你浏览器用某种编码后,Servlet容器自作多情给你用iso-8859-1解码了一下,如果你设置了URIEncoding="UTF-8"它就会用utf8给你解码,运气好你浏览器用的也是这种编码,那解出来就直接用了,所以在ISO-8859-1的情况下你得再“原路返回”到二进制,重新用正确的编码解码一下。

Post请求和Ajax请求

Post请求就比较简单一点了,同样你可以使用Get请求中的方法2来解决,不过比较麻烦,这时候我们就可以使用Servlet里的方法request.setCharacterEncoding方法设置你的解码类型,例如你的页面编码是utf8,表单则urlencode成utf8了,那么你在调用getParameter方法之前(记住,一定要之前!!在第一次调用getParameter之前!)使用setCharacterEncoding方法。 Ajax请求同理。

响应请求

响应也是相同道理,这回轮到服务器做编码,浏览器做解码。只需要设置response.setCharacterEncoding,就会自动在响应头的Content-Type中加入charset=XXX,返回的内容就可以被正常解析啦~

我想我说的相对比较清楚了,网上很多解决乱码的帖子都只是讲你加上某句代码就会解决,这样是不科学的,一定也要知道原理,也要知道每句代码背后做了哪些工作。其实我们在操作HttpServlet对象的时候,本质上是对Http头的一些信息做修改。

如果有什么问题或者理解错误的地方,欢迎指正讨论。

转载于:https://my.oschina.net/looly/blog/287255

Servlet一次乱码排查后的总结相关推荐

  1. linux servlet 乱码问题,Servlet一次乱码排查后的总结

    由来 在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出来的中文显示到页面正常,锁定肯定是request对象那里出了问题.后来经过排查,发现是我封 ...

  2. Servlet 输出中文乱码的新收获(1)

    又碰到servlet 输出中文乱码的问题,恼火.研究了一下,有了新的发现和认识. 原始代码: java 代码 protected void doGet(HttpServletRequest reque ...

  3. Servlet解决中文乱码

    一.出现乱码原因 乱码原因:传输方和接收方采用的编码不一致.传输方对参数采用的是UTF-8编码而接收方却用GBK进行解析,当然是乱码,且Tomcat服务器默认采用的ISO8859-1编码得到参数值,如 ...

  4. servlet response 中文乱码

    先,response返回有两种,一种是字节流outputstream,一种是字符流printwrite. 申明:这里为了方便起见,所有输出都统一用UTF-8编码. 先说字节流,要输出"中国& ...

  5. jsp servlet mysql 乱码_关于jsp和servlet中的乱码问题

    在jsp和servlet的开发中,今天自己做的一个小例子中出现了中文乱码问题,用了许多方法,发现还是解决不了.最后我用了过滤器,才算终结. 此方法总结如下:在jsp页面中使用 ,这里的pageEnco ...

  6. Servlet 传输中文乱码解决方法

    就一句话,而且要用于讲所要转换的变量之下: name = new String(name.getBytes("iso-8859-1"),"utf-8"); 整体 ...

  7. 注意语句顺序 防止Servlet Request Response乱码

    今天在项目中.想在控制层,用response来输出中文.发现有乱码. 本来代码是 PrintWriter out = response.getWriter(); response.setContent ...

  8. MySql 中文乱码排查解决方案

    MySQL会出现中文乱码的原因不外乎下列几点: server本身设定问题,例如还停留在latin1 table的语系设定问题(包含character与collation) 客户端程式(例如php)的连 ...

  9. 关于 jsp java servlet 中文汉字乱码的解决方法

    在servlet类中的get,post最前面加上 req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding(&quo ...

最新文章

  1. android 无法接收广播_别告诉我你不认识Android中广播接收者(二)
  2. ArcBruTile 0.2.2
  3. c++区块链实例_确定技术任务了解区块链限制 开发区块链你该做哪些准备工作?...
  4. 【Matlab 控制】求函数极限
  5. 启动设备ar1失败 错误代码2_设备启动系列(2)寿力空压机
  6. java.util.UnknownFormatConversionException: Conversion = ‘,‘ 解决
  7. 超级干货!31 条2020 年最新版 ZooKeeper面试题,先收藏再看!| 博文精选
  8. Ethercat解析(十二)之命令行工具的使用
  9. 用PHP制作饼图调查表
  10. PJ可能会用到的动态规划选讲-学习笔记
  11. unix网络编程之简介和运输层TCP/UDP
  12. mastercam加工报表生成_如何使用 Mastercam 进行角度头编程?丨角度头铣削轮毂内腔案例分享...
  13. 金鳞岂是池中物,一遇风云便化龙
  14. [Inferior 1 (process 17260) exited normally] Debugger finished with status 0
  15. Endnote导入知网、EI、IEEE数据库文献
  16. 打破校史!双非高校,迎来首位杰青!
  17. 什么样的故障让阿里云换了总裁?
  18. 华为网络配置(IPSec)
  19. 一加6可以刷的rom_一加6刷机包
  20. 关于前端flex的使用

热门文章

  1. Java中的引用与C中的指针
  2. python中lt方法_Python的富比较方法__lt__、__gt__之间的关联关系分析
  3. 什么是分布式_终于搞懂分布式锁是什么了
  4. python编程前面需要一个空格怎么做_初学python,不明白代码之间时空格的用处
  5. spring boot和spring cloud的区别_Spring聊聊application和bootstrap
  6. 领域驱动设计在互联网业务开发中的实践
  7. Deep Learning 中文翻译
  8. JavaScript 常用函数
  9. 如何用 C++ 在 10 行内写出八皇后?
  10. 从古希腊神话说起,讲讲英语里的偏旁部首