tomcat版本升级带来的编码问题

前几天在定位一个中文乱码的问题,尝试使用了几种方式,包括设置tomcat server.xml中的属性URIEncoding为UTF-8、在项目web.xml文件中使用Spring的CharacterEncodingFilter设置属性encoding为UTF-8作为整个项目的filter,甚至查看了Linux的环境变量(UTF-8)编码,也无济于事,这个问题怪异的地方在于:这个搜索接口的中文字符的编解码方式代码已经很久没有动过了,按道理来说不应该会出现问题,生产环境中中文搜索也没有出现问题,偏偏在测试环境出现了中文乱码的问题,一时之间毫无思路。

查看代码时发现如下的代码片段:

String word = request.getParameter("keyword");//keyword=中文

String keyword = new String(word.getBytes("ISO-8859-1"),"UTF-8");

调试发现keyword的值为 ?? ,很明显是因为编码不对导致乱码,断点调试发现变量word值已为"中文",根本不需要再做编码转换,当然,要解决当前环境的乱码问题已经很简单了,就是直接去掉不需要的编码转换逻辑即可,但是考虑到生产环境中这种逻辑是没有问题的,中文字符并没有出现乱码的情况,一时之间不敢乱改,后来咨询了组内的同事,他们建议再观察下,可以加上一个开关来控制是否需要做编码转换,虽然这种方式有点挫,但是当时考虑到版本快要上线了,时间紧急,实属无奈之举,在编码转换前加了一个开关控制的逻辑,代码片段类似这种:

if(isEncodeOpen())

{

       keyword = new String(word.getBytes("ISO-8859-1"),"UTF-8");

}

上线时开关是开启的,即是允许做编码转换的,怀着忐忑的心情等待版本上线,上线后验证了下相关的搜索接口,发现一切正常,中文搜索没有问题!!!

一句话总结就是:真是奇了怪了。。。但是因为当时比较忙,看着相关功能正常也就没有太多去关注这个问题了,但是总是有一种如鲠在喉的感觉。

这两天终于有空可以回溯下这个问题的根源了。

乱码产生的原因:解码时采用的encoding和编码时采用的encoding不一致造成的

这里有两个问题:

1. 为啥在做编码转换时写死由ISO-8859-1转换为UTF-8?

2. 同样的代码,为啥生产环境没有问题,测试环境会出问题?

排查原因时主要分析了以下三个方面:

1. 项目是否使用了统一的编码filter

2. 搜索接口是否设置了单独的编解码方式

3. tomcat的版本以及server.xml文件的配置

关于第一点,项目设置统一编码filter的问题,在项目的web.xml中是有设置统一的编码filter:CharacterEncodingFilter为UTF-8

因此排除第一个问题的疑问。

同样在查看搜索相关的代码时也没有发现有针对搜索接口做单数的编码设置,类似request.setCachacterEncoding("ISO-8859-1")之类的代码。

针对第三个问题,当在百度和Google搜索中文乱码问题时,大部分的答案都是说在tomcat的server.xml文件中设置URIEncoding=UTF-8即可解决乱码的问题,尝试过后无果,依旧乱码,后来尝试去比较了下生产环境跟测试环境server.xml文件的配置,也没有发现有编码设置相关的差异,但是在比较过程中发现了一个很重要的不同--tomcat版本不一致,生产环境的tomcat版本是7.x的版本,而测试环境的tomcat版本是8.x版本。

顺着上面的思路,既然网上有人说设置URIEncoding可以解决中文乱码的问题,那么就要看下tomcat7.x跟8.x版本对该属性URIEncoding是否存在不一样的地方,如果不设置,默认的值是否不一样?

首先先看下是如何设置URIEncoding属性的:

<Connector port="8080" protocol="HTTP/1.1"

     connectionTimeout="20000"

     redirectPort="8443"

     URIEncoding="UTF-8"

/>

查看tomcatMigrating from 7.0.x to 8.0.x官方文档时发现关于URIEncoding的相关说明:

Default URL encoding

The default value of URIEncoding attribute for HTTP and AJP connectors has been changed from "ISO-8859-1" to be "UTF-8" (if "strict servlet compliance" mode is off, which is the default). This setting specifies what character encoding is used to decode '%xx'-encoded bytes in path and query of a request URI.

If server is configured with "strict servlet compliance" on, the default value of URIEncoding attribute of connectors is "ISO-8859-1", the same as in older versions of Tomcat.

大意是tomcat由7.x版本升级到8.x版本时,默认的URL编码方式由ISO-8859-1变为UTF-8,看到这里应该可以解决这次有关中文乱码的疑问了。

更详细的来看下tomcat官方文档在7.x和8.x版本对URIEncoding属性的说明:

8.x版本:tomcat 8.x版本 URIEncoding

URIEncoding

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless the org.apache.catalina.STRICTSERVLETCOMPLIANCE system property is set to true in which case ISO-8859-1 will be used.

大意是如果不设置属性org.apache.catalina.STRICTSERVLETCOMPLIANCE=true,那么默认的编码方式会是UTF-8。

7.x版本:tomcat 7.x版本 URIEncoding

URIEncoding

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

大意是如果不设置的话,那么默认的编码方式会是ISO-8859-1.

看到这里,我想我上面提出的两个问题已经可以很好的解释了.

1.代码写死ISO-8859-1转换为UTF-8,是因为tomcat7.x版本默认的编码方式ISO-8859-1,因此需要做相应的转换

2.同样的代码,生产环境没有问题,测试环境有问题,是因为测试环境升级了tomcat的版本为8.x版本,而生产环境未做升级,仍为7.x版本,两个版本关于URIEncoding属性的默认值不一样,7.x默认是ISO-8859-1, 8.x默认是UTF-8。

现在想想,当初加开关是正确的选择,可以完美解决tomcat版本不一致带来的编码问题。。。哈哈哈

不过仍然有很多值得总结的地方:

1.环境不一致:测试环境跟生产环境tomcat版本应该要保持一致,可以及时发现和预防tomcat版本升级带来的问题,当然也不仅仅是tomcat的版本,包括MySQL、JDK等的版本都应该保持一致。

2.代码写死编码转换方式,这种做法并不是很好,应该通过配置文件的方式来配置相关的属性值,可以通过tomcat容器的配置或者项目自身的配置来实现。

3.版本升级一定要看官方文档说明,看是否存在升级指导、changlog之类的文档,有问题查看官方文档才是正解。

4.关于编码,最好统一设置成UTF-8,不要采用默认的编码方式,显式的将编码方式设置成UTF-8,这样就不会因为版本升级或者环境变更带来编码的问题,同时也不会出现上面那种ISO-8859-1转换为UTF-8编码的代码了~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容