1. 程式人生 > >FreeMarker的FTL頁面中include引用UTF-8檔案導致錯位的問題處理

FreeMarker的FTL頁面中include引用UTF-8檔案導致錯位的問題處理

首先簡單介紹下,FreeMarker是一個模板引擎,一個基於模板生成文字輸出的通用工具,用來生成HTML Web頁面,特別是基於MVC模式的應用程式,其作用跟JSP有點類似,不過它不允許在頁面中寫JAVA程式碼,所有內容必須提前生成,因此它比JSP能更好地保持介面設計同應用程式邏輯的分離。

今天有同事碰到這個問題,一個FreeMarker的FTL頁面程式碼如下:
[html] view plaincopy

<html>  
...  
<body>  
<#include "/WEB-INF/ftl/AHeader.ftl">  
<div class="adlist3">...  
</div>  
...  
</body>  
</html>  

其中在body後緊跟著包含引用了一個公共的導航頁標頭檔案,內容如下:
[html] view plaincopy

<div class="nn">  
    <a href="http://xxx.yyy/j/i.action" class="menu">主頁</a>  
    ...  
</div>  

兩個FTL檔案都是UTF-8編碼。挺簡單的一個頁面,但執行後發現頁頭有一點白邊,非常奇怪:
這裡寫圖片描述
IE8、FF、OPERA均有此問題,只有IE9是正常地貼到到頂邊。研究了半天原始碼,也沒發現有CSS或空行之類的東西在影響。

進一步測試發現,如果去掉<#include>,直接把內容貼到同一個FTL檔案裡是不會有問題的;因此可以確認是<#include>導致的問題。

繼續除錯,發現如果把AHeader.ftl的檔案編碼修改為GBK,並用<#include “/WEB-INF/ftl/CtWaeHeader.ftl” encoding=”GBK”>的方式引用,也能避免此問題;因此初步認定問題可能是UTF-8編碼引起的。

於是懷疑檔案的編碼並非真的是UTF-8。用UE開啟AHeader.ftl並進入HEX模式,發現居然是UNICODE的:
這裡寫圖片描述
心想這下找著問題了,連忙用記事本開啟,另存為UTF-8,滿懷希望地開啟瀏覽器,結果非常失望,問題依舊。

再用UE開啟,結果還是UNICODE。原來UE對UTF-8的支援不太好,其實檔案可能已經是UTF-8,但被UE開啟後自動切換成UNICODE了。

再找到另一個二進位制工具,開啟AHeader.ftl,發現它確實是UTF-8編碼,非常正確的。但這時檔案頭的前幾個BOM位元組引起了我的懷疑:
這裡寫圖片描述
文字編輯器儲存UTF-8、UNICODE格式檔案時,會在檔案頭上加一個標記說明它的編碼,稱為Byte Order Mark,即BOM。

正常情況下,FreeMarker直譯器應該要自動識別UTF-8的BOM標記的,但如果它沒有識別,直接把BOM輸出給瀏覽器了,就有可能在頁面上留下空白了。

於是我嘗試用EditPlus去掉BOM。EditPlus有一個儲存時不寫BOM的選項:
這裡寫圖片描述
勾上此選項,用EditPlus開啟AHeader.ftl再另存回去,這時再用瀏覽器開啟,果然已經沒有白邊了:
這裡寫圖片描述
至此問題解決,原因是FreeMarker在引用UTF-8的檔案時,沒有把檔案的BOM處理掉,直接扔給瀏覽器了。解決辦法是在被引用的檔案中把BOM標記全去掉。