遇到了一个问题:grails 项目中的 html 文件,浏览器打开全乱码。这些 html 文件全是 UTF-8 编码的,也有
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
头了。java 开发 web 乱码不在是问题的情况下,还让我遇到这事。
一个怪现象:浏览器里指定 GBK 编码可以正常显示(可以怀疑与平台有关);不带 index.html 的方式(即直接访问路径),如 http://localhost:8080/grails-test/ 又是另一套乱码(即乱码不一致,浏览器不能校正的)。
找问题根源吧 ……
开始怀疑 jetty 对 UTF-8 html 文件支持不好,打 war 放到 tomcat 看看,问题依旧。可排除 jetty 正常的。
接着怀疑整个 grails 项目,在 tomcat 新开一个普通的项目,加个几个 utf-8 的 html 文件,访问正常。很有可能 grails 项目中的某些过虑器作的怪。
这问题肯定是与使用了与平台有关的编码相关方法,把编码相关的操作设置平台无关的吧,可以用下面的 java 系统属性,在 tomcat 下设置属性如 bin/catalina.bat:
set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=utf-8 -Ddefault.client.encoding=utf-8 -Duser.language=zh -Duser.region=CN
运行后没问题,正常显示。但还有一个怪现象,没弄明白:用 gsp 生成的页面保存为 utf-8 的 html 文件又可正常访问。对比两个 html 文件,没发现有什么不妥的地方。
还是 google 下吧:grails html 乱码。恩,有重要提示:静态html在sitemesh中乱码的解决方法 ,但是,我不想在启动时设置系统(不想干扰其它程序),我想到在 grails 的 BootStrap init 中设置系统属性。设置如下:
- class BootStrap {
- def init = { servletContext ->
- System.setProperty("file.encoding", "UTF-8")
- System.setProperty("default.client.encoding", "UTF-8")
- System.setProperty("user.language", "zh")
- System.setProperty("user.region", "CN")
- }
- def destroy = {
- }
- }
但还是乱码,于是我再仔细对比上面提到的两种 html 文件(一个我加的,有乱码,叫 A.html;一个是 gsp 生成手动保存下来的,不会乱码),然后尝试
- <meta name="layout" content="main" />
保存到 A.html 里。奇迹出现,不会乱码了。郁闷 sitemesh 会这样,可能是 grails 过的原因。
后来把 BootStrap init 中的编码设置去了,发现 A.html 也可正常,因为 A.html 返回头(或 meta 标签指定了)有正确的编码。但在这情况下有乱码:不带 index.html 的方式(即直接访问路径),上面提到的。用
curl -I http://localhost:8080/grails-test/
返回 Content-Type: text/html; charset=iso-8859-1。这样不得不在 BootStrap init 加上编码相关的系统属性。
小结:
在 html 中用确meta layout 的元素的声明,同时在 Grails 的 BootStrap init 中设置编码相关的系统属性。
另一种简单的方法:直接在服务启动级别设置编码相关的系统属性,这样 html 也不用 layout 声明。