字符集转换解决方案
问题的提出:
关于字符串的字符集转换,目前应用系统中主要在对数据库操作的时候。
1. 向数据提交操作请求
会对每一个String类型的变量做一次GBKToUnicode的操作,实际上此操作最终会触发unicodeToGBK操作,而在unicodeToGBK中会调用isGBKString方法用来判定此字符串是否是GBK编码,采用的方式是循环比较字符串数组中的每一个char对象值。
2. 从数据库返回数据信息
会对每一个String类型做一次unicodeToGBK的操作,同样会调用isGBKString方法。
    由于上述操作导致应用服务器的性能产生很大的负载,因此需要及时改进。
已经解决的问题:
对于从数据库返回数据信息而做的unicodeToGBK操作,我们主要是在schemagetString时调用,及exesql中的getdatavalue中调用。Schema中的调用我们通过一个静态变量SysConst.CHANGECHARSET来控制是否执行(目前默认情况下是不执行),而exesql中的调用是强制执行的。
经过民生的近期测试,我们发现可以去掉exesql中的unicodeToGBK操作,而保证数据在返回到前台的时候没有乱码。
尚未解决的问题:
    对于向数据提交操作请求而做的GBKToUnicode的操作,实际上此操作也依赖于SysConst.CHANGECHARSET变量
如果此变量为true
则执行new Bytes("GBK"), "ISO8859_1");
如果此变量为false
则执行new Bytes("ISO8859_1"), "GBK");
    现在系统中SysConst.CHANGECHARSET默认设置为false,而不论此变量为何值,系统都会执行isGBKString这个操作。weblogic管理页面
    问题:如果我们去除这一操作,会导致提交到后台数据库中的中文全部变成??的形式,在查询的时候,也无法使用中文作为查询条件。
以前的存储方式:
    以前的应用是通过unicodeToGBK进行转换,提交给数据库的时候,字符集的编码采用的是GBK。之所以当初要在后台统一字符集处理,是因为无法有效保证前台提交过来的信息编码格式。
问题分析:
    产生上述情况的原因是Jsp/Servlet 不能接收form提交的汉字,也不能解析通过get方式传递的汉字。
    运行于Java 应用服务器的 JSP/Servlet 为 Browser 提供 HTML 内容,其过程如下图所示:
其中有字符编码转换的地方有:
JSP 编译。Java 应用服务器将根据 JVM ding 值读取 JSP 源文件,编译生成 JAVA 源文件,再根据 ding 值写回文件系统。如果当前系统语言支持 GBK,那么这时候不会出现 encoding 问题。如果是英文的系统,如 LANG en_US Linux, AIX Solaris,则要将 JVM ding 值置成 GBK 。系统语言如果是 GB2312,则根据需要,确定要不要设置 ding,将 ding 设为 GBK 可以解决潜在的 GBK 字符乱码问题
Java 需要被编译为 .class 才能在 JVM 中执行,这个过程存在与a.同样的 ding
问题。从这里开始 servlet jsp 的运行就类似了,只不过 Servlet 的编译不是自动进行的。对于JSP程序, 对产生的JAVA 中间文件的编译是自动进行的(在程序中直接调用ls.javac.Main). 因此如果在这一步出现问题的话, 也要检查encodingOS的语言环境,或者将内嵌在JSP JAVA Code 中的静态汉字转为 Unicode, 要么静态文本输出不要放在 JAVA code 中。对于Servlet, javac 编译时手工指定-encoding 参数就可以了。
Servlet 需要将 HTML 页面内容转换为 browser 可接受的 encoding 内容发送出去。依赖于各 JAVA App Server 的实现方式,有的将查询 Browser accept-charset accept-language 参数或以其它猜的方式确定 encoding 值,有的则不管。因此采用固定encoding 也许是最好的解决方法。对于中文网页,可在 JSP Servlet 中设置 contentType="text/html; charset=GB2312";如果页面中有GBK字符,则设置为contentType="text/html; charset=GBK",由于IE NetscapeGBK的支持程度不一样,作这种设置时需要测试一下。因为16 JAVA char在网络传送时高8位会被丢弃,也为了确保Servlet页面中的汉字(包括内嵌的和servlet运行过程中得到的)是期望的内码,可以用 PrintWriter Writer() 取代 ServletOutputStream OutputStream(). PrinterWriter 将根据contentType中指定的charset作转换 (ContentType需在此之前指定!);
也可以用OutputStreamWriter封装 ServletOutputStream 类并用write(String)输出汉字字符串。对于 JSPJAVA Application Server 应当能够确保在这个阶段将嵌入的汉字正确传送出去。
这是解释 URL 字符 encoding 问题。如果通过 get/post 方式从 browser 返回的参数值中包含汉字信息, servlet 将无法得到正确的值。SUN J2SDK 中,HttpUtils.parseName 在解析参数时根本没有考虑 browser 的语言设置,而是将得到的值按 byte 方式解析。这是网上讨论得最多的 encoding 问题。因为这是设计缺陷,只能以 bin 方式重新解析得到的字符串;或者以 hack HttpUtils 类的方式解决。参考文章 2 均有介绍,不过最好将其中的中文 encoding GB2312 CP1381 都改为 GBK,否则遇到 GBK 汉字时,还是会有问题。 Servlet API 2.3 提供一个新的函数 HttpServeletRequest.setCharacterEncoding 用于在调用 Parameter(param_name) 前指定应用程序希望的 encoding,这将有助于彻底解决这个问题。
提出的解决方法:   
    通过在中间件上设置、或者在servelt上设置,避免应用程序执行字符集转换操作。
方法一:
数据提交的方式有两种,一种是get的方式,一种是post的方式。经测试,Java中接收到前台传入的信息的时候,中文字符就已经转换为??,原因未明。可能是Tomcat在接收到请求后,并没有能够根据request中的信息提前正确的编码方式。
解决:可以添加一个设置字符集的Filter,来保证Servlet能够正确按照指定的字符集解析。同时配置l文件如下:
    <filter>
        <filter-name>Set Character Encoding</filter-name>
        <display-name>Set Character Encoding</display-name>
        <filter-class>filters.SetCharacterEncodingFilter</filter-class>    --实现类
        <init-param>
            <param-name>encoding</param-name>
            <param-value>GBK</param-value>    --字符集设置
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>Set Character Encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    这是一种比较常用的规范提交数据字符集的方式。
    试验结果:
    在tomcat、websphere、weblogic上分别测试应用的情况。
Tomcat下
使用filter后,采用form的提交能够被有效的转换为gbk模式到数据库中,并且在查询返回后,没有出现乱码。但是在用get的方式传递变量的时候出现乱码,使得无法进行中文信息查询,解决的方法是在tomcat的l文件中的<Connector >对象中添加URIEncoding="GBK"属性。
Websphere下
使用filter后,post、get两种方式都能够正常的解析gbk编码
Weblogic下
使用filter后,post、get两种方式都能够正常的解析gbk编码。不过在应用中出现比较多的乱码,解决的方案是在应用的web-inf中添加l文件,其中设置如下信息
    <jsp-descriptor>
        <jsp-param>
            <param-name>encoding</param-name>
            <param-value>GBK</param-value>    --好像不同的平台设置不太一样
        </jsp-param>
        <jsp-param>
            <param-name>compilerSupportsEncoding</param-name>
            <param-value>true</param-value>
        </jsp-param>
    </jsp-descriptor>
   
    注:测试是基于oracle数据库,字符集ZHS16GBK。同时在tomcat上也进行了db2的测试,字符集是UTF-8
    测试环境:
Window中文平台:tomcat5.0websphere5.1weblogic8.1
Window英文平台:websphere5.1weblogic8.1
Unix平台:weblogic
数据库:oracle数据库,字符集ZHS16GBK
   
测试结果:以上平台下都没有问题,能够保证数据已GBK的模式存入数据库中,并查询出来。
    测试疑问:websphereweblogic下,使用get方式来提交信息的时候,会根据客户端的字符集设置产生问题。(如果客户端的地域是中国,则查询是能够正常的提交GBK编码给后台,如果前台的地域不是中国,则提交给后台的编码为地域所设的国家编码模式)
方法二:
通过配置xml文件来实现filter的方法。
针对不同的中间件产品,各自都有一些比较特殊的xml配置信息,因此如果能够通过xml文件的配置来达到filter的效果,那么就能够更好的提高应用平台的性能。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。