Servlet一次乱码排查后的总结(转)

原文地址:http://my.oschina.net/looly/blog/287255

由来

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

补充:其实不管是表单提交,还是android,iOS客户端提交,都会出现以上的问题,原因还是跟服务器解析有关系,就是服务器接收到的字符集有关系。

原理解析

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

  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头的一些信息做修改。

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

时间: 2024-08-02 07:44:08

Servlet一次乱码排查后的总结(转)的相关文章

JSP和Servlet的中文乱码处理

JSP和Servlet的中文乱码处理 前几天学习了JSP和Servlet中有关中文乱码的一些问题,写成了博客,今天进行更新一下.应该是可以解决日常的乱码问题了.现在作以下总结希望对需要的人有所帮助.我也是刚学,所以有不足之处希望谅解. 一.表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我一直以为get请求和post请求方式出现的乱码的解决方式是一

JSP/Servlet编码导致乱码问题

JSP/Servlet编码导致乱码问题 jsp页面的三处编码:       1.<%@ page language="java" pageEncoding="UTF-8"%>         作用:告诉jsp编译器将jsp编译成Servlet时使用的字符编码         例如,你的JSP文件是以GBK为编码保存的 (右击jsp-->Properties --> Text file encoding                设置成与p

解决servlet请求中文乱码的通用过滤器程序

import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletExcepti

Servlet解决参数乱码问题

为什么会产生乱码? 之所以会产生乱码,是由于服务器端和客户端的编码方式不一致造成的.客户端与服务器端的交互过程中,存在着两次数据交换:第一次,客户端向服务器端发起请求,第二次数据交换,服务器端响应客户端的请求后做出应答,将处理结果返回给客户端. 前提了解,无论服务器端是在接受数据还是在返回数据时,如果不指定其数据编码格式,那么他就会以其默认的“iso8859-1”来编码. 首先看客户端向服务器端发出请求: 客户端的页面以何种编码方式打开某个页面,通过http协议发送请求给服务器端时,就以何种编码

(原)一次揪心的乱码排查过程

序)很多时候其实问题很简单,问题在于自己懂得过于肤浅 项目中需要用到一个功能,机器人模拟和人类聊天,玩家说出一句话之后,机器人本能的和他开始聊天,这破B玩意儿我觉得只要有强大的词库和拆分算法,就那么点东西,但是要自己做还真是压力满满的.于是果断的在网上搜索,轻松的找到了这个东西: 这玩意儿给我的第一感觉就是实在,可以,完全能够满足需求,不过貌似它没有提供接口,这不是事儿,果断的翻网页源码,找到post的地方,是一个ajax的post请求,带了一个参数,很简单,于是果断的来个java模拟HTTP,

servlet中中文乱码问题

在web项目中经常回碰到中文乱码的问题,特此整理一下,有不足的地方,希望大家纠正. 1从前台往后台传数据,.以get方式发送请求,发送的参数不乱,但是后台接收到参数乱码 在Tomcat的server.xml文件中设置URIEncoding属性值为UTF-8%CATALINA_HOME%\conf\server.xml <Connector port="8888" protocol="HTTP/1.1" connectionTimeout="20000

关于servlet和jsp 乱码的问题

一.表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我一直以为get请求和post请求方式出现的乱码的解决方式是一样的,但是今天才知道两种请求方式所产生的乱码的解决方式是不同的.每种方式都有着不同的解决方法,之所以出现乱码,原因就在于get请求时,其传递给服务器的数据是附加在URL地址之后的:而post的请求时,其传递给服务器的数据是作为请求体的一

处理Servlet响应中文乱码

首先,response返回有两种,一种是字节流outputstream,一种是字符流printwrite. 申明:这里为了方便起见,所有输出都统一用UTF-8编码. 先说字节流,要输出"中国",给输出流的必须是转换为utf-8的"中国",还要告诉浏览器,用utf8来解析数据 [html] view plain copy //这句话的意思,是让浏览器用utf8来解析返回的数据 response.setHeader("Content-type", &

处理servlet中中文乱码问题

平时coding时,经常遇到一些乱码问题,现在总结一下在使用Servlet时遇到的一些乱码问题,简单的解决办法两种 第一种简单处理方式 在servlet中数据的处理是通过request和response进行处理的,提交数据有两种方式:post+get ①post提交方式--只要事先设置request.setCharacterEncoding("UTF-8");-------注:只对POS提交有效 ②get提交方式--通过ISO8859-1得到客户端发送的数据,再转成UTF-8类型.(或