Tomcat字符编码的常见问题.doc

上传人:飞****2 文档编号:51831261 上传时间:2022-10-20 格式:DOC 页数:10 大小:217.50KB
返回 下载 相关 举报
Tomcat字符编码的常见问题.doc_第1页
第1页 / 共10页
Tomcat字符编码的常见问题.doc_第2页
第2页 / 共10页
点击查看更多>>
资源描述

《Tomcat字符编码的常见问题.doc》由会员分享,可在线阅读,更多相关《Tomcat字符编码的常见问题.doc(10页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、Tomcat字符编码的常见问题 1.默认的字符编码是什么? 如果没有指定字符编码,Servlet规范规定使用ISO 8859-1作为默认的编码。 2.我怎样改变GET方法的解析? 在server.xml中的Connector中指定URIEncoding参数。 3.我怎样改变POST方法的解析? POST请求需要指定它发送的参数和值的编码,因为大多数客户端可能没有设置一个明确的编码,默认使用的是ISO 8859-1。大多数情况下它可能不是我们希望的编码,因此可以使用一个javax.servlet.Filter来改变编码。Tomcat已经提供了完成这个功能的过滤器的例子。请参看: 4.x weba

2、pps/examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.java 5.x webapps/servlets-examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.javawebapps/jsp-examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.java 6.x webapps/examples/WEB-INF/classes/filters/SetCharacterEncodingFilt

3、er.java 4.我如何测试我配置工作正常? 下面这个JSP代码能够工作在一个没做任何改变新安装的Tomcat上。如果你设置了URIEncoding=UTF-8,它也能工作在GET方式上。 Character encoding test page Data posted to this form was: 5.我如何在HTTP Header中发送高位字符? 你必须在插入到header之前使用某种方式对其编码。使用url-encoding(% + high byte number + low byte number)是一个好的方法。 6.如何确保其正确运行,请给个建议。 使用UTF-8作为字符

4、编码是一个好的办法,这在大多数情况下工作良好。为了确保完全使用UTF-8,你需要做如下改变: 1.在server.xml中为你的设置 URIEncoding=UTF-8 2.使用上面Tomcat例子提供的字符编码过滤器保证默认的编码为UTF-8 3.改变所有JSP页面的Content-Type类型为UTF-8 (使用) 4.把所有servlets的Content-Type设置为UTF-8 5.改变你用来生成内容的类库(如Velocity, Freemarker,等等.)的Content-Type为UTF-8深入理解tomcat处理编码的机制2010年09月21日 星期二 上午 3:09本文从t

5、omcat源码的鲜为人知的UDecoder类入手,试图讲解Tomcat内部处理编码的机制。只涉及Tomcat处理请求的编码机制,不涉及响应的编码机制。1. 关于UDecoder类 查看tomcat5和tomcat6版本的源码,可以看到org.apache.tomcat.util.buf.UDecoder类。这个类有什么特别的地方呢? 用简单的一句话概括UDecoder类做的事情:修改所输入的字节流, 将每3个以百分号%开头的字节(如“%HH”,占3个字节),转换成1个十六进制的字节码(如“0xHH”,占1个字节),且将加号+变成空格“ ”。如图举例描述了6个以百分号%开头的字节“%D6%D0”

6、变成了2个十六进制的字节码“0xD60xD0”。(注:我用中括号“ ”来表示其中的内容代表的是1个十六进制形式的字节,下同。) 我们知道UDecoder类的功能后,进一步想知道的是,tomcat用这个类做了什么事情?答案是:用于修改http请求中的表单参数的值, 将每1个“%HH”(占3个字节)变成“0xHH”(占1个字节),且将加号+(占1个字节)变成空格“ ”(占1个字节)。其中表单参数包括:get方式的url参数和post方式的 application/x-www-form-urlencoded的参数。举个例子,当我们访问这样的url时,第1点,我们了解UDecoder类就好,继续看第2

7、点。2. 关于tomcat的Character Encoding(参考 http:/wiki.apache.org/tomcat/FAQ/CharacterEncoding) 我们使用tomcat时知道,要用request.getParameter(keywords)来获取get或post的参数值,而当keywords不是ISO-8859-1编码的字符时,为了获取到正确的keywords值,我们知道有以下几种方式可以解决(假设参数以GBK编码):第一种:自己编程实现转换:String ISOkeywords = request.getParameter(keywords);/ISOkeywor

8、ds是乱码 String keywords = new String(ISOkeywords.getBytes(ISO-8859-1), GBK);/keywords=“啤酒”第二种:设置$tomcat_home/config/server.xml中的URIEncode配置项的值为“GBK”第三种:设置$tomcat_home/config/server.xml中的useBodyEncodingForURI配 置项的值为true,并实现一个SetCharacterEncodingFilter.java,在tomcat的目录 webapps/servlets-examples/WEB-INF/c

9、lasses/filters /SetCharacterEncodingFilter.java中存在这个范例。3. 结合UDecoder和Character Encoding,分析访问 tomcat的处理流程大致可以看作以下四个步骤(具体可参见本文最后的流程图): (1)访问 (2)UDecoder将%C6%A1%BE%C6转换为0xC60xA10xBE0xC6,tomcat持有变量bytes=0xC60xA10xBE0xC6。 (3)如果设置了URIEncode配置项或者useBodyEncodingForURI配置项为“GBK”,则tomcat会做以下转换: String gbkKeywo

10、rds = new String(bytes,GBK);/bytes=0xC60xA10xBE0xC6,gbkKeywords=“啤酒” 程序员使用request.getParameter(keywords)得到的就是上面的gbkKeywords,因此是正确的关键字“啤酒”。如下图。(4)如果未设置了URIEncode配置项或者useBodyEncodingForURI配置项 ,则tomcat相当于执行了以下转换: String keywords = new String(bytes,ISO-8859-1);/bytes=0xC60xA10xBE0xC6,keywords是乱码 程序员使用re

11、quest.getParameter(keywords)得到的就是上面的keywords,因此是乱码。如下图。 所以,此时我们需要自己编程实现转换: String isoKeywords = request.getParameter(keywords); /isoKeywords是乱码 String keywords = new String(isoKeywords.getBytes(ISO-8859-1), GBK);/keywords=“啤酒”4. UDecoder带来的启发 (1) 使用UDecoder,可以使得经过URLEncoding和未经过URLEncoding的请求都正确的得到解

12、析。当然,前提是,未经过经过URLEncoding的URL编码和未经过URLEncoding的请求的字节码的编码是同样的一种编码,如都是GBK或UTF-8。如和 想象一下,假如没有UDecoder,那么如果要正确处理keywords=%C6%A1%BE%C6和keywords=0xC60xA10xBE0xC6,tomcat就必须分2种情况去处理: 当keywords=%C6%A1%BE%C6时,tomcat获得字符串“%C6%A1%BE%C6”,然后使用URLDecoder.decode(%C6%A1%BE%C6)得到“啤酒”; 当keywords=0xC60xA10xBE0xC6时,tomc

13、at直接获取字节码bytes=0xC60xA10xBE0xC6,然后使用new String(bytes, GBK);得到“啤酒”; 这样远远没有UDecoder的实现那么美观和简单。补充,总结一下,在写Servlet时,应该怎么做: (1)如果URIEncoding=“ISO-8859-1”,而浏览器的keywords可能是中文或urlencoding的,好像这样也行:(这种只针对我部门的开发环境)String keywords = request.getParameter(keywords);/?或%C6%A1%BE%C6String keywords2 = new String(keyw

14、ords.getBytes(ISO-8859-1),GBK);/“中文”或%C6%A1%BE%C6String keywords3 = URLDecoder.decode(keywords2,GBK);/“中文”(这种针对tomcat,配置了URIEncoding=“ISO-8859-1”,tomcat) (2)如果未知URIEncoding=“GBK”还是“ISO-8859-1”,已知浏览器的keywords是urlencoding的:String keywords = request.getParameter(keywords);/中文或%C6%A1%BE%C6String keyword

15、s2 = URLDecoder.decode(keywords2,GBK);/“中文” (3)如果未知URIEncoding=“GBK”还是“ISO-8859-1”,已知浏览器的keywords是中文的:String keywords = request.getParameter(keywords);/中文或?String keywords2 = new String(keywords.getBytes(ISO-8859-1),GBK);/则不行! (4)如果URIEncoding=“GBK”,而浏览器的keywords可能是中文或urlencoding的:String keywords =

16、request.getParameter(keywords);/“中文” 这样即可。 (4)是我们推荐使用的,(1)在没使用tomcat或者不希望应用和容器相关时,使用。 另外,其实.URLDecoder和UDecoder是类似的,不过URLDecoder是缺陷的。URLDecoder.decode的参数是String,它通过str.charAt()来解码%HH-0xHH,然后new String(bytes, 0, pos, enc).而UDecoder.decode()的参数是字节数组。区别看出来了吗? URLDecoder.decode(?)时,charAt是什么,是“?”,结果还是UR

17、LDecoder.decode(?)=?. 而UDecoder.decode(字节数组)是可以正确解码的。 (2) 为了SEO,有些网站会将参数放到pathInfo中,对于pathInfo的参数解析,我们也可以模仿UDecoder机制。据说前段时间百度爬虫访问阿里巴巴时使用的url就是未URLEncoding的(例如5. 最后附上一张图,作为总结。图是有问题的,form的enctype = content-type 取值有:如multipart/form-data和application/x-www-form-urlencoded其中multipart/form-data的情况,是指分多个部分

18、,每个部分都有自己的content-type,且默认也是application/x-www-form-urlencoded 。可以详细见这里 http:/www.w3.org/TR/html4/interact/forms.html#form-content-typeTomcat处理编码的流程(有废话有点啰嗦未完成版)2010年09月20日 星期一 下午 8:40请看这篇吧 各位- 深入理解tomcat处理编码的机制Tomcat是如何处理query/post的编码问题的?首先我们看看get方式时,tomcat如何获取querystring。比如我们的url是: (其中%C6%A1%BE%C6是

19、啤酒的GBK的URLEncode编码)当请求来到服务器的tomcat(也可以说是Servlet)这一层面时,我们可以通过request获取这个keywords。获取的方式有两种:(1) 直接使用getParameter(keywords)得到keywords参数(2) 先使用getQueryString(),再手动解析出keywords参数我们看看这两种方式。(1) getParameter(keywords)这里涉及 config/server.xml中URIEncode的配置项,假设我没对tomcat作任何URIEncoding的配置,它默认使用ISO-8859-1的编码。 当访问http

20、:/localhost/?keywords=%C6%A1%BE%C6后,我们试图打印出getParameter(keywords)的值,你猜看到什么?乱码!我们试图质问tomcat:“为什么是乱码?!如果我输入的keywords是“啤酒”这样的字符,得到乱码我可以接受,但是我输入的可是“%C6%A1%BE%C6”这样一串ISO-8859-1编码的字符啊!有人猜测,那是浏览器在搞鬼,浏览器发送的不是“%C6%A1%BE%C6”这样的可见字符的,而是发送“啤酒”这个非ascii字符(当然,我们应该理解本质上传送的“啤酒”肯定是“啤酒”的某某编码格式的字节码,这个编码可以是常见的GBK或UTF-8)

21、。但是,其实不是浏览器搞鬼,浏览器发送的就是“%C6%A1%BE%C6”,你可以通过打印request.getQueryString();看到,它输出“keywords=%C6%A1%BE%C6”。那到底是怎么回事呢?源于tomcat对表单提交的参数(包括Get方式和Post方式)有个UDecode类的处理过程。什么是UDecode类的处理过程,详细你可以看tomcat源码的UDecode类,这里用简单的一句话概括UDecode类做的事情:修改request中的parameter(包括get方式的url参数的value和post方式的application/x-www-form-urlenco

22、ded的参数的value)的字节, 将每1个“%HH”(占3个字节)变成“0xHH”(占1个字节),且将加号+(占1个字节)变成空格“ ”(占1个字节)。下面的图直观的描述了这个UDecode过程:我们看到6个字节的“%D6%D0”变成了2个字节的“0xD60xD0”,我用中括号“ ”来表示其中的内容合起来是一个字节。 到这里,我们至少知道了tomcat有个UDecode的过程,所以我们从中推理出这样的一个现象:客户端发送的keywords参数无论是啤酒的GBK字节码“0xC60xA10xBE0xC6”还是啤酒的GBKURLEncode字符“%C6%A1%BE%C6”,经过tomcat的UDe

23、code后,到变成前者,即“0xC60xA10xBE0xC6”。说到这,我再次问上面一开始的那个问题:getParameter(keywords)的值为什么是乱码?我给个提示:和UDecode有关!答案现在还不是很明显,但我们脑海可能浮现了这幅图:从UDecode的结果“0xC60xA10xBE0xC6”到getParameter(keywords)的乱码。你想到问号的部分是什么吗?很抽象地为你解开答案:所以,getParameter(keywords)的值为什么是乱码?因为上面的bytes是GBK的字节码,而tomcat错误地将bytes作为ISO-8859-1进行解码了!难怪keyword

24、s会是乱码!这.是tomcat的错吗?坦诚说不是,因为上面“String keywords = new String(bytes,ISO-8859-1);”中的编码ISO-8859-1是可配置的,大家还记得 config/server.xml中的URIEncode配置项吧?就是这个URIEncode配置项,决定是上面的式子用什么编码。到了这里,大家都清楚了,设置配置项URIEncode=“GBK”就可以用getParameter(keywords)得到正确的keywords:“啤酒”。另外配置项useBodyEncodingForURI使得http:/wiki.apache.org/tomca

25、t/FAQ/CharacterEncoding#Q2-现在,我问大家一个问题,当你知道,浏览器无论访问“http:/localhost/?keywords=%C6%A1%BE%C6” 还是 “http:/localhost/?keywords=0xC60xA10xBE0xC6”,tomcat都会将keywords变成“0xC60xA10xBE0xC6”后,大家觉得要怎么去解码还原keywords为“啤酒”呢?相信答案大家都很一致:byte bit = new byte(byte)0xD6,(byte)0xD0; 中的字节码,是URLDecode之后的字节码String w = new String(bit, GBK); 用配置的URIEncoding将其解码,变成字符中String ISOkeywords = request.getParameter(keywords);String keywords = null;request.getQueryString();/keywords=%C6%A1%BE%C6if(StringUtil.isNotBlank(ISOkeywords)try keywords = new String(ISOkeywords.getBytes(ISO-8859-1), GBK);

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁