上次的gsp中文編碼問(wèn)題,我在grails的源碼找到了問(wèn)題的所在。
grails的gsp servlet程序是通過(guò)org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine對(duì)gsp進(jìn)行編譯和解釋的,再此過(guò)程中同包下的Parse類負(fù)責(zé)了最基本的詞法檢查。但是Parse的readStream(InputStream in)讀取gsp文件時(shí),簡(jiǎn)單采用了ByteArrayOutputStream的toString()函數(shù),這個(gè)函數(shù)只采用系統(tǒng)默認(rèn)編碼進(jìn)行識(shí)別。也就是在這里產(chǎn)生了gsp依賴與操作系統(tǒng)默認(rèn)編碼集的問(wèn)題。
既然如此,猜測(cè)有一個(gè)并不完美的解決方法:通過(guò)file.encoding系統(tǒng)屬性來(lái)指定虛擬機(jī)的默認(rèn)編碼集。
比如:grails run-app -Dfile.encoding=GBK
結(jié)果又出乎我的意料,這樣并不能工作,似乎是由于grails本身生成幾個(gè)文件是UTF8編碼的,強(qiáng)行指定GBK編碼后會(huì)有問(wèn)題。
看起來(lái),如果你希望部署打包好的war程序包的話,沒(méi)有好方法,只能選擇編碼集相同的環(huán)境!
我認(rèn)為好的方法應(yīng)該是grails支持在gsp的servlet配置中增加一個(gè)叫做fileEncoding的初始化參數(shù),在讀取文件時(shí)應(yīng)用此參數(shù)。這樣大家就可以根據(jù)自己的喜好選擇開(kāi)發(fā)grails的環(huán)境了。不過(guò)目前GroobyPagesServlet類與Parse類之間還隔了GroovyPagesTemplateEngine,并且這個(gè)GroovyPagesTemplateEngine的單例初始化是在其他地方完成的,要想實(shí)現(xiàn)這個(gè)參數(shù)比較繁瑣。
或者要想簡(jiǎn)單的話就干脆寫死Parse中使用UTF8,這也是個(gè)不錯(cuò)的選擇,eclipse之類的開(kāi)發(fā)工具對(duì)UTF8的支持很好,其他開(kāi)發(fā)工具應(yīng)該沒(méi)有不支持UTF8的吧。這樣就要求大家都是用UTF8編寫gsp,反正文件中絕大多數(shù)都還是英文字符,也沒(méi)多占幾個(gè)字節(jié)。
如果上面的方法都不喜歡怎么辦?我還有一個(gè)辦法,就是不要在gsp中寫ISO-8859-1字符以外的任何東西,使用i18n輸出你期望的中文字符。其實(shí)也就是順帶著把網(wǎng)站所有資源國(guó)際化了,呵呵,一舉兩得。不過(guò)以我的體驗(yàn)來(lái)說(shuō),真要這樣做的話,通常你是會(huì)抓狂的,properties文件將超出你想象的瘋長(zhǎng),那個(gè)郁悶呀。
而且還要注意,雖然grails說(shuō)可以配置在發(fā)布時(shí)把properties文件自動(dòng)做native2ascii,但是現(xiàn)有會(huì)有類似的問(wèn)題:原始的properties文件的native編碼是什么?最好還是找個(gè)properties的編輯工具,直接保存成ascii的unicode轉(zhuǎn)碼比較好。