freemarker源碼解讀之一--概述

最近在思考爲如何xsoup添加自定義函數支持,基於這個目的,想起了最經常使用的模板引擎freemarker。因而down了源碼下來,開始瀏覽一番。本文基於https://github.com/freemarker/freemarker上的2.3.20版本。java

思考

看源碼前,先思考一下,一個模板引擎,到底須要哪些東西?一門模板引擎實際上是一個完整的語言,只不過它只具備單純的輸入/輸出,不須要考慮其餘的功能。node

  • 語法解析,轉換爲AST(抽象語法樹)git

  • 語義分析,爲AST附加上執行語義github

  • 上下文環境的注入框架

  • 內置函數及外部函數支持函數

  • 其餘外圍機制(與框架/工具的集成等)工具

源碼結構

打開freemarker的代碼,core包裏110個類一字排開,還有如下劃線開頭的「建議不要看」的類,看的人眼花繚亂啊!這一切都是由於Java規範的大師們,設計了一個「包級可見「的概念,大概就是,我寫給本身用的代碼,不要讓你用!這一來,別人用是用不了了,好像看起來也變得很困難了…ui

還好如今的IDE都很強大,刷刷兩下就給重構了,把一些類按照類型挪到多個包裏,頓時清爽不少!惋惜好多類/方法/字段都是包級可見,爲了讓這個重構版freemarker沒那麼多紅叉,lz加了好幾百個public,寫到意識都模糊了…最後把本身的勞動成果共享出來吧:https://github.com/code4craft/freemarker-learning。主要是將freemarker.core包裏內容拆開了,語法樹相關的內容放到了freemarker.core.nodes包,異常放到了freemarker.core.exception包,一些模板內置功能放到了freemarker.core.buildin包,還有工具類放到了freemarker.core.util包。.net

順便將freemarker的流程整理了一下:設計

流程

這是一個很經典的模板引擎的執行流程:

  • Configuration能夠理解爲一個工廠,它負責產生一個對外接口Template類。它首先會從cache中查找是否已經有編譯好的Template,若是不存在,則對模板進行編譯。
  • Template其實是一個帶執行語義的語法樹,樹的節點是TemplateObject。
  • FMParser是javacc生成的語法解析類,它最終輸出是以FMParser.root()爲根的語法樹。
  • dataModel是外部對模板引擎的數據輸入,它會被轉化爲TemplateModel,並代入模板的渲染過程。
  • 最後的步驟是根據數據,遍歷編譯好的語法樹,並輸出結果,這一步的入口時TemplateElement.accept()。

關於JavaCC

freemarker使用了JavaCC(Java Compiler Compiler)作parser。關於JavaCC,有一篇很好的入門帖,順帶複習一下編譯原理:LL(0)文法,消除左遞歸等東西。http://cs.lmu.edu/~ray/notes/javacc/

JavaCC的下載在這裏:http://javacc.java.net/,不知是我操做失誤仍是怎樣,下載JavaCC-6.0以後,bin目錄只有lib/javacc.jar文件。下載JavaCC-5.0src以後,才找到javacc腳本。難道就這麼幾百K的東西,還要搞增量更新?

總之下載成功以後,用javacc FTL.jj,便可生成一堆Parser文件。核心是FMParser,解析完的語法樹在FMParser.root()裏。

相關文章
相關標籤/搜索