Servlet一次乱码排查后的总结
由来
在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出来的中文显示到页面正常,锁定肯定是request对象那里出了问题。后来经过排查,发现是我封装的框架中出了问题,总结为在setCharacterEncoding方法之前,调用了getParameter方法,导致字符集改变失败。没看过Tomcat实现Servlet的源码,貌似是一旦调用getParameter方法Request的参数就会全部被解析,从而再调用setCharacterEncoding就无效了。
原理解析
其实编码问题本质还是两点:
- 浏览器在封装Http请求的时候的编码和服务器在解析Http请求编码不一致
- 服务器返回数据的时候编码和浏览器解析不同。
那么我们就从这两点入手解析。
浏览器请求
在点击提交表单的那一刻,浏览器把表单内容封装成一个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请求,有两种方式解码:
- 在Servlet容器中设置,例如Tomcat设置URIEncoding="UTF-8",就会对Get请求用utf8解码(貌似Tomcat7会报无效,具体解决请百度,反正我不同这种方法)
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头的一些信息做修改。
如果有什么问题或者理解错误的地方,欢迎指正讨论。
http://luxiaolei.com/servlet-charset
Servlet一次乱码排查后的总结的更多相关文章
- Servlet一次乱码排查后的总结(转)
原文地址:http://my.oschina.net/looly/blog/287255 由来 在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出 ...
- JSP和Servlet的中文乱码处理
JSP和Servlet的中文乱码处理 前几天学习了JSP和Servlet中有关中文乱码的一些问题,写成了博客,今天进行更新一下.应该是可以解决日常的乱码问题了.现在作以下总结希望对需要的人有所帮助.我 ...
- Servlet解决参数乱码问题
为什么会产生乱码? 之所以会产生乱码,是由于服务器端和客户端的编码方式不一致造成的.客户端与服务器端的交互过程中,存在着两次数据交换:第一次,客户端向服务器端发起请求,第二次数据交换,服务器端响应客户 ...
- 解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题
问题描述: 在springmvc中实现文件下载功能一般都会使用javax.servlet.ServletOutputStream out = response.getOutputStream();封装 ...
- Servlet中的乱码问题及解决办法
假设现在有个form表单,当页面中提交一个包含中文的请求时,在服务端有可能出现中文乱码问题. <!DOCTYPE html> <html> <head> <m ...
- 数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)
背景 公司有一个数据处理线,上面的数据经过不同环境处理,然后上线到正式库.其中一个环节需要将数据进行处理然后导入到另外一个库(Sql Server).这个处理的程序是老大用python写的,处理完后进 ...
- servlet中中文乱码问题
在web项目中经常回碰到中文乱码的问题,特此整理一下,有不足的地方,希望大家纠正. 1从前台往后台传数据,.以get方式发送请求,发送的参数不乱,但是后台接收到参数乱码 在Tomcat的server. ...
- JSP与Servlet的中文乱码处理
注:百度来的,改了改... jsp页面的的头要设置好 <%@ page language="java" contentType="text/html; charse ...
- Servlet -- 跳转到页面后的绝对路径与相对路径的问题
我们在使用servlet或其它框架,从后台跳转到视图层的时候.常会遇到这种情况,CSS和JS文件失效了,可是假设通过网址直接訪问JSP是没问题的. 这就是由于绝对路径和相对路径导致的. 绝对路径.就是 ...
随机推荐
- android studio 3.4配置Android -jni 开发基础
首先下载配置android studio ndk 1.打开sdkManager下载CMake和LLDB 2.配置ndk 项目新建 项目建立完毕后,工程目录如下,cpp文件夹是系统自动生成的 3.自定义 ...
- 知识图谱基础之RDF,RDFS与OWL 2
https://zhuanlan.zhihu.com/p/32122644 看过之前两篇文章([1](为什么需要知识图谱?什么是知识图谱?——KG的前世今生), [2](语义网络,语义网,链接数据和知 ...
- 并发编程~~~协程~~~greenlet模块, gevent模块
一 协程 1. 协程: 单线程下的并发,又称微线程,纤程.协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 并发真正的核心: 切换并且保持状态. 开启协程并发的执行,自己的程序把控着C ...
- [Go] 实现websocket服务端
直接使用官方子包可以实现websocket协议, golang.org/x/net/websocket 如果在这个目录没有这个包就去github下载net库,放进这个目录$GOPATH/src/gol ...
- unittest---unittest断言
在unittest单元测试中也提供了断言的方式,通过断言判断用例有没有成功. unittest常用断言 unittest框架的TestCase类提供以下方法用于测试结果的判断 方法 检查 assert ...
- git 分布式控制版本管理器(上)
git的作用: 1.更方便的存储版本 2.恢复之前的版本 3.更方便的对比 4.协同合作 下载地址git官网: https://git-scm.com/ 可自选自己电脑的操作系统 安装: 一路next ...
- vuex的学习
vuex是什么? vuex是专为vue.js应用程序开发的状态管理模式 它采用集中式存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化 vuex也集成到vue的官方调式工具d ...
- 传统jdbc存在的问题总结
1.数据库连接创建.释放频繁造成系统资源浪费,影响系统性能,可使用数据库连接池解决此问题. 2.sql语句中在代码中硬编码,代码不易维护,sql变动需要改变java代码. 3.使用preparedSt ...
- ABAP - AT END OF 的使用
TYPES: begin of ty_tab , num() type i, str() type c, end of ty_tab. data: gw_tab TYPE ty_tab , gt_ta ...
- 爬虫模拟有道字典进行翻译,还发现了一条好玩的js
08.14自我总结 爬虫模拟有道字典进行翻译 一.代码 import requests from lxml.html import etree # headers= { # 'User-Agent': ...