项目中用到 FreeMarker,在 eclipse 里用 maven 插件 跑 jetty:run,看上去挺美好的。但是一旦修改 FreeMarker 的模版文件(包含中文,UTF-8 编码,无 BOM ),页面一刷新,乱码就出来了。关掉重开可以解决问题。但是总想不明白到底哪里出的问题。

我一开始猜测是 FreeMarker 的读取模版时候的编码问题,经过网上一轮 Google 之后,尝试了各式各样的设置 encoding 方法都不能解决问题。这个问题太困扰了,网上又找不到类似于这种第一轮启动没问题,一修改就出问题的情况,而这个情况在其他人哪里是可以重现的。难道就没有人遇到过?原本只是想简单用用,现在看来得调试进去看看到底出什么问题了。至少需要确认一个问题,究竟是哪个环节出现问题。

又经过一番逐行 debug,得到一个让人惊讶的线索。源代码显示,无论是第几次加载模版,调的都是同一个方法,这部分代码出错的几率不高。而逐行到加载得到模版内容(未经 parse 之前),修改前后加载得到的内容是不一样的,修改后重新加载得到的内容本身就有乱码。

至少,可以还 FreeMarker 一个清白了。凶手又会是谁呢?

整个过程涉及到的还有 maven 和 eclipse。如果是 maven,在 pom 里给 maven-resource-plugin 添加编码设定 应该能解决问题。尝试了,问题依旧。只剩下 eclipse 了。再来回顾完整的重现过程可以发现,第一次拷贝模版文件到 classes 下是由 maven 的 resource-plugin 完成的,而更新后,是由 eclipse 自动进行拷贝的,这个拷贝的内容出现了乱码。但是奇怪的是,eclipse 里面所有涉及到编码的地方都统一修改成 UTF-8 了,因此一开始怎么也不会怀疑它。而道理上 eclipse 应该按照设定来操作,这个算不算是一个 bug 呢?

但是要怎么使 eclipse 用设定的编码来操作文件,所有涉及编码的地方都修改成 UTF-8 了。还记得在 maven 里修改过 MAVEN_OPTS 添加一个 -Dfile.encoding=UTF-8 来使 maven 运行时以 UTF-8 作为默认编码,此举可以省略许多代码里设置编码的需要,只在需要使用其它编码的时候再进行指定。类似地,在 eclipse.ini 文件中加入

-Dfile.encoding=UTF-8

重启 eclipse,验证,问题解决。

这个解决办法是可行,但是不得不指出,作为 IDE 的 eclipse 应该做好这一点,既然能以指定的编码打开和修改文件,为什么不能以指定编码来拷贝文件,对文件的一切操作都以用户指定的编码来处理才是符合预期的。