項目簡介:
項目是基於spring+Hessian+ibatis構建的一個類webservice服務系統,供客戶端如delphi,donet等調用。
問題描述:
有個sqlmap文件(該xml文件encoding=”gbk”)中有一sql語句:Select * from table1 where status=’有效’,該sql語句在windows下和其中一臺Linux(簡稱ServerA,操作系統版本爲:Red Hat Enterprise Linux Server release 5)下運行正常,能查出數據來;而在另一臺Linux(簡稱ServerB,操作系統版本爲:Red Hat Linux release 9)上卻怎麼也查不出數據,ServerA和ServerB的JDK和Tomcat版本一致,分別是1.5和6.0.
將日誌級別設置成debug,查看日誌信息獲悉,在Red Hat Linux release 9上,執行Select * from table1 where status=’有效’時,debug出來的信息是Select * from table1 where status=’????’,難怪查不出來數據。
解決方案:
第一反應肯定是linux操作系統默認字符集問題惹的禍,於是先找出ServerA機器的字符集信息,然後將ServerB機器的字符集設置成跟ServerA一樣,重啓服務器即可。查看ServerA的i18n(more /etc/sysconfig/i18n)信息爲:
LANG="zh_CN.gbk"
LANGUAGE="zh_CN.gbk:zh_CN.GB2312:zh_CN"
SUPPORTED="zh_CN.gbk:zh_CN:zh:en_US.UTF-8:en_US:en"
SYSFONT="lat0-sun16"
修改ServerB的i18n信息,並重啓ServerB,重啓tomcat,心想這次在ServerB下,上述Sql語句肯定能正常執行了。讓我悲傷的事情再次發生,在ServerB下,debug出來的信息還是Select * from table1 where status=’????’,我無語。。。
後調式ibatis源代碼發現,ibatis在初始化sqlmapclient的時候,會調用Resources.java類文件的getResourceAs*方法,該系列方法裏很多都會先判斷charset是否爲空,如果charset不爲空,在用指定的charset來讀取sqlmap文件。於是在web.xml文件裏,我新增一個Listener,在該Listener裏設置charset,代碼如下:
com.ibatis.common.resources.Resources.setCharset(Charset.forName("gbk"));
最好將gbk作爲參數配置到context-param裏,這樣就不需要gbk硬編碼死,可增加程序靈活性,切記新增的Listener,其在web.xml文件裏的順序一定要在Spring的ContextLoaderListener之前。
重新部署ServerB的應用,並啓動Tomcat,執行上述sql語句,終於可以查出結果來了,debug信息顯示也是:Select * from table1 where status=’有效’。