Freemaker初接觸(四)宏的瞭解和變量的類型

(本系列參考了大量玄玉大神博客)
首先是java代碼:
package com.joker.test;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class TestMrco {
 public static void main(String[] args) {
  String templateLoaderPath = "/";
  String templateName = "testMrco.ftl";
  Configuration cfg = new Configuration();
  String htmlPath = "D:/freemakerTest";
  String htmlName = "testMrco.html";
  Writer out = null;
  Map<String, Object> parms = new HashMap<String, Object>();
  User user1 = new User();
  user1.setName("反戰聯盟");
  ArrayList<String>names = new ArrayList<String>();
  names.add("name1");
  names.add("name2");
  names.add("name3");
  user1.setNames(names);
  parms.put("user", user1);
  parms.put("varName", "varNameInModel");
  try {
   cfg.setClassForTemplateLoading(TestMrco.class, templateLoaderPath);
   Template temp = cfg.getTemplate(templateName);
   out = new BufferedWriter(new OutputStreamWriter(
     new FileOutputStream(htmlPath + "/" + htmlName), "UTF-8"));
   temp.process(parms, out);
  } catch (IOException e) {
   e.printStackTrace();
  } catch (TemplateException e) {
   e.printStackTrace();
  } finally {
   if (null != out) {
    try {
     out.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }
}
然後是重要的ftl文件:
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<style>
span{
    color:red;
}
</style>
</head>
<body>
<#--定義宏-->
<#macro writeNote str1>
 <span color="red">${str1}</span>
</#macro>
<#macro testMacro>
 <h1> hello </h1>
</#macro>
<@testMacro></@testMacro>
<#macro testParm person>
 <h2>hello ${person}<h2>
</#macro>
<@testParm "123"></@testParm>
<@writeNote "可以使用 user.name這種形式獲取參數值,而不再需要EL表達式輸出"></@writeNote>
<@testParm user.name></@testParm>
${r'${r""}'}這種形式的轉義可以輸出EL表達式
${"<br>"?html} ${"在html元素後面加上?html可以直接輸出元素標籤"}
<#macro testDeafult text="可以對參數設置默認值">
 <h1>${text}</h1>
</#macro>
<@testDeafult></@testDeafult>
<@testDeafult "test"></@testDeafult>

<#macro testNested>
 <#nested>
 <#nested>
</#macro>

<@testNested>
  <@writeNote "${r'<#nested>'} 執行調用宏代碼和結束調用宏之間的代碼,可以理解爲將 @testNested 和 /@testNested 之間的內容 nested 進宏. 所以${r'<#nested>'} 出現了幾次,就會輸出幾次<br>">
  </@writeNote>
</@testNested>
<#macro testNestedWitParm>
<#nested user.name user.name>
</#macro>
<@testNestedWitParm; x,y>
 我的x是${x},我的y是${y} 
</@testNestedWitParm>
<#macro test1>
 <@writeNote '我是被嵌套的代碼開始'></@writeNote>
 <#nested>
 <@writeNote '我是被嵌套的代碼結束'></@writeNote>
</#macro>
<#macro test2>
 "我是嵌套的代碼開始"
 "我是嵌套的代碼結束"
</#macro>
--------------------------------
<@test1>
<@test2>
</@test2>
</@test1>
-------------------
<#assign testBoolean=true/>
${testBoolean?string("true","false")}
----------
<@writeNote "freemaker四種類型的變量  模型變量--存在於rootMap中的變量,模板變量---assign的變量,變量----存在於指令中的變量,循環變量,存在於循環體中的變量"/>
${r"{.globals.XXX}這種方式是直接查找模型變量否則是先去模板變量中尋找XXX,如果沒有,則去模型變量中尋找"}:${.globals.varName}

<br>模型變量${r"${varName}"}:${varName}
<br>模型變量${r"<#assign varName=>"}:<#assign varName="varInModelPlant">:${varName}
<br> 所以這種方式有問題,問題在於可能將模型變量覆蓋,所以產生了存在於宏中的變量,局部變量
<#macro testVarName>
 <#local varName="varInMacro">
 使用${r"<#local varName= 'varInMacro'"}對varName賦值 所以varName 變量只存在於 macro中${varName}
</#macro>
<br>
而執行完畢的varName還是${varName},不受macro中的影響
<@testVarName/>
此時外面的${r"${varName}的值爲:"} ${varName}

<br>最後一個是循環變量,該作用範圍只在循環內,不會影響外面的${r"${varName}"}:
 <#list user.names as varName>
 <br>
 循環體內的值爲:${varName}
 </#list>
<br>
此時外面的${r"${varName}的值爲:"}${varName}
</body>
</html>

最後是運行結果:
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<style>
span{
    color:red;
}
</style>
</head>
<body>
 <h1> hello </h1>
 <h2>hello 123<h2>
 <span color="red">可以使用 user.name這種形式獲取參數值,而不再需要EL表達式輸出</span>
 <h2>hello 反戰聯盟<h2>
${r""}這種形式的轉義可以輸出EL表達式
&lt;br&gt; 在html元素後面加上?html可以直接輸出元素標籤
 <h1>可以對參數設置默認值</h1>
 <h1>test</h1>


 <span color="red"><#nested> 執行調用宏代碼和結束調用宏之間的代碼,可以理解爲將 @testNested 和 /@testNested 之間的內容 nested 進宏. 所以<#nested> 出現了幾次,就會輸出幾次<br></span>
 <span color="red"><#nested> 執行調用宏代碼和結束調用宏之間的代碼,可以理解爲將 @testNested 和 /@testNested 之間的內容 nested 進宏. 所以<#nested> 出現了幾次,就會輸出幾次<br></span>
 我的x是反戰聯盟,我的y是反戰聯盟 
--------------------------------
 <span color="red">我是被嵌套的代碼開始</span>
 "我是嵌套的代碼開始"
 "我是嵌套的代碼結束"
 <span color="red">我是被嵌套的代碼結束</span>
-------------------
true
----------
 <span color="red">freemaker四種類型的變量  模型變量--存在於rootMap中的變量,模板變量---assign的變量,變量----存在於指令中的變量,循環變量,存在於循環體中的變量</span>
{.globals.XXX}這種方式是直接查找模型變量否則是先去模板變量中尋找XXX,如果沒有,則去模型變量中尋找:varNameInModel

<br>模型變量${varName}:varNameInModel
<br>模型變量<#assign varName=>::varInModelPlant
<br> 所以這種方式有問題,問題在於可能將模型變量覆蓋,所以產生了存在於宏中的變量,局部變量
<br>
而執行完畢的varName還是varInModelPlant,不受macro中的影響
 使用<#local varName= 'varInMacro'對varName賦值 所以varName 變量只存在於 macro中varInMacro
此時外面的${varName}的值爲: varInModelPlant

<br>最後一個是循環變量,該作用範圍只在循環內,不會影響外面的${varName}:
 <br>
 循環體內的值爲:name1
 <br>
 循環體內的值爲:name2
 <br>
 循環體內的值爲:name3
<br>
此時外面的${varName}的值爲:varInModelPlant
</body>
</html>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章