当前位置: 首页 > ai >正文

常见中文乱码问题

日常工作中,中文乱码算是比较常见的问题了,大家或多或少都遇到过。这里简单分析下我遇到过的乱码场景,错误和遗漏之处,欢迎大家补充、纠正和交流。

 

一、常见乱码问题

1.1 Ajax请求中文参数乱码

      发送Ajax请求时,如果参数中有中文,服务端获取到参数后,有可能乱码。

1.2 外联js代码中文字符乱码

      外联方式引入js文件,如果js的代码中有中文,有可能乱码。

下面就来依次分析这两个场景。

 

二、Ajax请求中文参数乱码

      Ajax请求分为GET和POST两种方式,对于这2种方式,Webx框架的处理不尽相同。此外,在客户端浏览器的处理上,也有可能出现一些中文编码字符集的不确定性。

 

     2.1 知识点

     首先介绍下encodeURIComponent('xxx'),这个js原生函数采用UTF-8编码,js代码中对中文字符进行显式编码时,基本上用的都是该函数。

     接下来介绍下编码的基本知识,在此copy一下Webx文档的一段话,如下。

alt

     2.1.1 GET请求

     对于GET方式的Ajax请求,如果未显式执行encodeURIComponent对中文参数进行编码,那么浏览器会根据“输出字符集”对中文字符进行编码,Webx默认配置的是GBK输出字符集,也就是说浏览器极有可能采用GBK字符集进行中文字符编码。当前,也不排除个别浏览器在实现上不是这个套路。如果使用了某些JS库的Ajax组件,JS库也有可能额外搞一些动作。而对于英文操作系统,由于我没有测试过,也不确定是否会影响到浏览器的编码字符集。因此存在着一定的编码字符集不确定性。

      在服务端对GET请求的处理过程中,Webx框架没有采用Servlet引擎的解码方式,而是另起炉灶,特殊进行了参数解析和字符解码。需要特别说明的是,Webx在此之前,统一设置了CharacterEncodingWebx默认配置的是GBK输入字符集GET请求参数解析和字符解码的关键代码如下图所示。

   alt

key = decode(key);
value = decode(value);

    详细代码可参见Webx3的com.alibaba.citrus.service.requestcontext.parser.impl.ParameterParserImpl类,以构造函数为入口进行阅读。

 

    2.1.2 POST请求

    对于POST方式的Ajax请求,字符编码一律采用UTF-8,这应该是Ajax的一个规范。在KISSY的代码和Webx的文档中都有阐述,Ajax规范还有待进一步研究确认。​

    对于非Ajax的正常表单提交,字符编码会采用web页面的字符集,对于淘宝的页面来讲,通常就是GBK。

    在服务端对POST请求的处理过程中,Webx框架采用了Servlet引擎提供的解码方式。仍然需要特别说明的是,Webx在Servlet引擎解码之前,也统一设置了HttpServletRequest的CharacterEncoding,即“输入字符集”,Webx默认配置的是GBK,与GET请求设置CharacterEncoding是在同一个地方。如下所示。

// 试图从queryString中取得inputCharset
String queryString = getRequest().getQueryString();
String inputCharset = locale.getCharset().name();
if (queryString != null) {Matcher matcher = inputCharsetPattern.matcher(queryString);if (matcher.find()) {String charset = matcher.group(1);if (LocaleUtil.isCharsetSupported(charset)) {inputCharset = charset;}}
}
getRequest().setCharacterEncoding(inputCharset);

详细代码可参见Webx3的com.alibaba.citrus.service.requestcontext.locale.impl.SetLocaleRequestContextImpl类,以prepare方法为入口进行阅读。

 

    2.2 乱码原因

    由以上知识点可知,我们通常遇到的乱码一般是由于客户端对中文采用了UTF-8编码,而服务端采用GBK解码导致。

 

    2.3 解决方法

    2.3.1 对于GET请求产生的乱码,通常需要做两件事情。第一,使用encodeURIComponent对中文字符进行编码,消除编码字符集的不确定性。第二,需要在url中额外增加 _input_charset 参数,值为UTF-8,这个参数是Webx预留的参数,可以优先设置本次请求的解码字符集,核心代码同2.1.2的代码贴图,这里补充一下webx.xml的配置和匹配_input_charset 参数的正则Pattern,如下所示。

<set-locale defaultLocale="zh_CN" defaultCharset="GBK" />
String INPUT_CHARSET_PARAM_DEFAULT = "_input_charset";inputCharsetParam = defaultIfNull(inputCharsetParam, INPUT_CHARSET_PARAM_DEFAULT);
inputCharsetPattern = Pattern.compile(inputCharsetParam + "=([w-]+)");

    这里还有另外一种处理方式,即寻找第三方js库,提供GBK编码的encodeUri函数,可以免去url中的_input_charset 参数。

 

    2.3.2 对于POST请求产生的乱码,通常只需要在url(请注意是url,不是表单参数)中额外增加 _input_charset 参数,值为UTF-8即可。

    如果这样处理仍然有问题,并且使用的是KISSY库的Ajax组件,那么可以先使用encodeURIComponent对中文字符进行编码,然后再发送Ajax请求,这时候url中是否有_input_charset 参数已经无关紧要。之后,服务端业务代码要显式执行URLDecoder.decode("xxx","UTF-8"),即可获取到正确的中文字符。这里面发生了一些有趣的事情,简单YY下。在显式执行encodeURIComponent之后,发送Ajax请求之前,KISSY的Ajax组件又额外进行了一次encodeURIComponent。以“测试”举例,经过一次encodeURIComponent处理后的值是“测试,再经过一次encodeURIComponent,值变成了“%25E6%25B5%258B%25E8%25AF%2595,这样无论Webx框架采用何种输入字符集,Servlet引擎解码后,值都会恢复成“测试”,之后业务代码再显式执行URLDecoder # decode,就拿到中文字符了。

    KISSY额外的一次encodeURIComponent,发生在对传入的表单数组进行S.param的时候,可以参看源码。

 

三、外联js代码中文字符乱码

     3.1 知识点

     web页面引用外联JS,若未加特殊处理,一般会按照web页面的字符集对外联JS进行解码。

     浏览器解码的字符集,一般按照以下优先级判断。http header(”content-type:text/html; charset=xxx”)优先级最高,如http-header未指定则依据html <META http-equiv=”content-type” content=”text/html; charset=xxx”>,如果http-header和html-meta都没有指定,那么一般就是依据文件的BOM编码格式。

     3.2 乱码原因

     我遇到的乱码都是发生在daily环境。

     淘宝的web页面基本都是GBK字符集。

     淘宝外联的JS,daily环境放在assets测试服务器上,线上环境放在tbcdn上,编码字符集由JS文件的BOM决定。

     前端同学编写JS代码,在保存时一般都采用UTF-8编码。

     因此,用GBK解析UTF-8编码的中文字符,就出现乱码了。

     3.3 解决方法

     3.3.1 对script单独设置解码字符集,<script type=”text/javascript” src=”xxx.js” charset=”UTF-8″></script>,这样处理后,该script的解码就按照指定的charset进行。

     3.3.2 前端采用GBK字符集保存代码并提交。这个应该不太可行,前端采用UTF-8编码应该有一些原因,至于是对压缩有影响,还是其它的原因,有待深入探究。

     3.3.3 采用ucool等工具作代理,并将代理文件以GBK字符集保存。

     3.3.4 直接引用压缩之后的-min.js,这样会给debug带来困难,但肯定不会有乱码问题。因为淘宝使用的压缩工具,会将所有的中文字符替换成Unicode编码。因为线上引用的都是-min.js,所以就没有乱码问题。由此可见,压缩JS不单是缩短客户端下载时间,也能够避免乱码问题。

http://www.xdnf.cn/news/11254.html

相关文章:

  • DB2备份和还原数据库+代码详解
  • HTTP/HTTPS(超细精讲)
  • 彻底理解面向对象,看完这一篇就够了
  • 谈谈Parser --王垠
  • 拓扑排序(Topological Sorting)
  • Wireshark TS | Ping Google DNS 8.8.8.8 特殊结果解析
  • centos 7 RAID0磁盘阵列步骤_如何重做raid但是不格式化磁盘
  • strtok函数
  • FastReport Avalonia 2024
  • 初识 ABP 框架
  • FFMPEG开发手册
  • Python 十五个炫酷代码
  • 开源 SPL 消灭数以万计的数据库中间表
  • 轻松两招,告诉你电脑怎么定时关机!
  • 央视解说之韩乔生巅峰之作--夏普
  • 我有七种实现web实时消息推送的方案
  • 多普达与O2之间的关系
  • 【编译原理】-- 第一章(翻译程序、编译程序、汇编程序、解释程序、编译过程概述)
  • 码率(kbps)、帧率(FPS)、分辨率和清晰度的正反比关系
  • 【收藏】计算机专业常用学习网站
  • 红旗Linux:国产操作系统的领军者!
  • gridview修改,添加,删除等
  • standard.jar是干什么的有什么用?
  • 程序员们平时都喜欢逛什么论坛呢?
  • 海量数据处理分析方法
  • 虚拟软驱的3种方法
  • WOW表情
  • 谷歌chrome浏览器源码分析
  • 【黑客零基础入门必知必会】常见的网站攻击方式
  • 无线网络密码破解软件BackTrack3+spoonwep2中文包+闪盘制作教程