2017-06-16 26 views
0

我正在創建一個自定義FreeMarker指令。作爲我的實現的一部分,我想在execute方法內部訪問自定義指令的Body。有沒有辦法從TemplateDirectiveBody body或Environment env中獲取它?FreeMarker:如何在實現TemplateDirectiveModel時將TemplateDirectiveBody作爲字符串獲取?

模板使用

<@loop>My name is ${name}</@loop> 

實施

public class LoopDirective implements TemplateDirectiveModel{ 
    public LoopDirective() { 
    } 
    public void execute(Environment env, 
     Map params, TemplateModel[] loopVars, 
     TemplateDirectiveBody body) 
     throws TemplateException, IOException { 
     System.out.println(body); 
     // I want to print "My name is ${name}" 
    } 
} 

我不想使用類似完整的模板字符串:

Writer w = new StringWriter(); 
env.getCurrentTemplate().dump(w); 

回答

0

我假設的一點是,你不希望${name}得到解決(否則您可以使用TemplateDirectiveBody API)。你不應該這樣做。但是,我認爲你可以通過從env.getCurrentDirectiveCallPlace()獲得來源的職位來拉扯一個詭計。現在你知道你需要刪除原始代碼的哪一部分,儘管它將包含分隔標籤,所以你需要用你自己的程序邏輯去除那些(簡單的解析...)。至於獲取模板的源代碼,理論上Template對象應該沒有。但是,由於一些不良遺產,你得到了Template.getSource(int, int, int, int)。但是,它將用空格替換製表符,除非您在Configuration中將tabSize設置爲1。另一件要知道的事情是Template.getSource有點慢(在內存中字符的拷貝有點浪費),再加上你必須每次刪除分隔標籤。但速度問題也可以通過使用DirectiveCallPlace.getOrCreateCustomData解決,它可以讓您緩存每個調用位置的最終String

+0

謝謝你的迴應。是的,我不想'$ {name}'來解決。當你說「你不應該這樣做」時,有什麼具體原因? 另外我想知道爲什麼[getChildrenBuffer](https://github.com/apache/incubator-freemarker/blob/2.3-gae/src/main/java/freemarker/core/Environment.java#L2807)在這裏不公開? Template.getSource(int,int,int,int)不會幫助我。我正在嘗試使用自定義指令來避免嵌套,但允許重複。 有效 <@loop> $ {ABC}<@loop> $ {XYZ} 無效 <@loop> $ {ABC} <@loop> $ {XYZ}

+0

好吧,如果你指示模板語言的值代入,那麼它是相當不尋常的是要壓制這種行爲,並且對讀取模板的人感到困惑(因爲你改變了記錄的行爲)。但我不明白你想達到什麼。您可以在運行時檢查全局變量來禁止將'loop'嵌套到'loop'中。爲什麼這與解決'$ {exp}'有關? AST API-s,尤其是'getChildrenBuffer',是低層次的實現細節。 – ddekany

+0

再次感謝您的回覆。如何禁止在運行時檢查全局變量來將'loop'嵌套到'loop'中? 我們正在接受來自用戶的模板,所以作爲一個安全的事情,我想避免無限循環或迭代過多。我正在創建一個自定義循環指令'<@loop>',就像'#list'一樣,我可以控制循環迭代的最大次數,並且還可以限制嵌套,即'<@loop><@loop> '。但重複應該工作,像'<@loop><@loop>'。 –

相關問題