
 
笨蛋学习FreeMarker
- FreeMarker
- 参考网址
- 创建实例
- 引入Maven
- 创建工具类
- 创建实例并进行输出
 
- FreeMarker数据类型
- 布尔型:
- 日期型:
- 数值型:
- 字符型:
- 需要处理字符串为null的情况,否则会报错
- 字符串为空不会报错
- cap_first
- uncap_first
- upper_case
- lower_case
- capitalize
- chop_linebreak
- contains
- ends_with
- ensure_ends_with
- ensure_starts_with
- groups
- html
- index_of
- j_string
- js_string
- json_string
- keep_after
- keep_after_last
- keep_before
- keep_before_last
- last_index_of
- length
- lower_case
- matches
- number
- replace
- rtf
- split
- starts_with
- trim
- word_list
- xhtml
- xml
 
- sequence类型:
- hash类型:
 
- FreeMarker指令
- #assign定义变量
- #if #elseif #else逻辑判断
- #list遍历
- #macro自定义
- 创建自定义指令
- 使用自定义指令
 
- nested占位
- import导入模板
- include包含模板或文件
 
- FreeMarker运算符
- 算术运算符
- 逻辑运算符
- 比较运算符
- 空值运算符
 
 
FreeMarker
参考网址
http://freemarker.foofun.cn/
创建实例
引入Maven
<!-- 模板引擎-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.33</version>
</dependency>
创建工具类
/**
 * FreeMarker 工具类,用于处理模板和生成输出文件
 */
public class FreeMarkerTemplate{
    private Configuration configuration;
    /**
     * 构造函数,初始化 FreeMarker 配置
     *
     * @param templateDirectory 模板文件存放的目录
     */
    public FreeMarkerTemplate(String templateDirectory) {
        configuration = new Configuration(Configuration.VERSION_2_3_31);
        configuration.setClassForTemplateLoading(FreeMarkerTemplate.class, templateDirectory);
        configuration.setDefaultEncoding("UTF-8");
    }
    /**
     * 处理模板并生成输出文件
     *
     * @param templateName    模板文件名
     * @param model           模板数据模型,即要传递给模板的参数
     * @param outputFilePath  输出文件路径
     */
    public void processTemplate(String templateName, Map<String, Object> model, String outputFilePath) {
        try {
            // 加载指定的模板文件
            Template template = configuration.getTemplate(templateName);
            // 生成输出文件
            try (Writer out = new FileWriter(new File(outputFilePath))) {
                template.process(model, out); // 将模型数据填充到模板中
            }
            System.out.println("输出已生成: " + outputFilePath);
        } catch (IOException | TemplateException e) {
            e.printStackTrace(); // 处理异常,可以根据需要完善异常处理
        }
    }
}
创建实例并进行输出
Map<String, Object> model = new HashMap<>();
model.put("msg", "TodaySaturday");
// 创建 FreeMarker 工具类实例,指定模板目录(一般在resource目录下创建一个文件夹存放模板)
FreeMarkerTemplate freeMarkerUtil = new FreeMarkerTemplate("/templates");
// 调用工具类方法处理模板,生成输出文件
freeMarkerUtil.processTemplate("convertHtml.ftl", model, "TodaySaturday-GenApi.html");
FreeMarker数据类型
布尔型:
相当于boolean类型,但是不能直接输出,需要转字符串输出
-  使用 ?c和?msg来进行转字符串
-  ${msg?c} ${msg?string} <!--如果是true返回yes,否则返回false--> ${msg?string("yes","no")}
日期型:
相当于date类型,但是不能直接输出,需要转字符串输出
-  年月日: ?date
-  时分秒: ?time
-  年月日时分秒: ?datetime
-  指定格式: ?string("自定义格式")- y:年
- M:月
- d:日
- H:时
- m:分
- s:秒
 
-  ${myDate?date} ${myDate?time} ${myDate?datetime} ${myDate?string("yyyy年MM月dd日 HH时mm分ss秒")}
数值型:
相当于int、float、double、lang等数值类型
- 可以转换为数值型、货币型、百分比型
- 转字符串:?c
- 转货币型字符串:?string.currency
- 转百分比型字符串:?string.percent
- 保留小数:?string["0.##"],#表示一个小数位
字符型:
相当于字符串,有很多内置函数
-  需要处理字符串为null的情况,否则会报错- !:指定缺失变量的默认值,- ${value!}: 如果value值为空,则默认值是空字符串
- ${value!"默认值"}:如果value值为空,则默认值为 ”默认值“
 
- ??:判断变量是否存在,如果变量存在,返回true,否则返回false- ${value??}?string
 
 
-  字符串为空不会报错
-  cap_first字符串中的首单词的首字母大写。 ${" green mouse"?cap_first} ${"GreEN mouse"?cap_first} ${"- green mouse"?cap_first}
-  uncap_first
和 cap_first 相反。 字符串中所有单词的首字母小写。
字符串的大写形式。比如 "GrEeN MoUsE" 将会是 "GREEN MOUSE".
字符串的小写形式。比如 "GrEeN MoUsE" 将会是 "green mouse".
字符串中所有单词的首字母大写。
${"  green  mouse"?capitalize}
${"GreEN mouse"?capitalize}
在末尾没有 换行符 的字符串, 那么可以换行,否则不改变字符串。
如果函数中的参数指定的子串出现在源字符串中, 那么返回true。
<#if "piceous"?contains("ice")>It contains "ice"</#if>
返回是否这个字符串以参数中指定的子串结尾。
"ahead"?ends_with("head") 返回 true
"head"?ends_with("head") 返回 true。
如果字符串没有以第一个参数指定的子串结尾, 那么就会将它加到字符串后面,否则返回原字符串。
"foo"?ensure_ends_with("/")
"foo/"?ensure_ends_with("/") 返回 "foo/"。
如果字符串没有以第一个参数指定的子串开头, 那么就会将它加到字符串开头,否则返回原字符串。
"foo"?ensure_starts_with("/")
"/foo"?ensure_starts_with("/") 返回 "/foo"。
这个函数只作用于内建函数 matches 的结果。请参考 这里…。
<input type=text name=user value="${user?html}">
返回第一次字符串中出现子串时的索引位置。
"abcabc"?index_of("bc") 将会返回1 (不要忘了第一个字符的索引是0)。而且,你可以指定开始搜索的索引位置: "abcabc"?index_of("bc", 2) 将会返回4。 这对第二个参数的数值没有限制:如果它是负数,那就和是0是相同效果了, 如果它比字符串的长度还大,那么就和它是字符串长度那个数值是一个效果。 小数会被切成整数。
根据Java语言字符串转义规则来转义字符串, 所以它很安全的将值插入到字符串类型中。要注意它 不会 在被插入的值的两侧添加引号; 你需要在字符串值 内部 来使用。
<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";
String BEAN_NAME = "The \"foo\" bean.";
根据JavaScript语言字符串转义规则来转义字符串, 所以它很安全的将值插入到字符串类型中。要注意, 它不会在被插入的值两侧添加引号
引号(")和单引号(')要被转义。 也要将 > 转义为 \>(为了避免 </script>)。
<#assign user = "Big Joe's \"right hand\"">
<script>
  alert("Welcome ${user?js_string}!");
</script>
将会输出:
<script>
  alert("Welcome Big Joe\'s \"right hand\"!");
</script>
根据JSON语言的字符串规则来转义字符串, 所以在字符串中插入值是安全的。 要注意它 不会 在被插入的值两侧添加引号; 你需要在字符串值 内部 来使用。
这不会转义 ' 字符,因为JSON字符串必须使用 " 来括起来。它会在 < 之后直接出现的 /(斜杠)字符转义为 \/, 来避免 </script> 等。 它也会在 ]] 之后转义 > 字符为 \u003E,来避免退出XML的 CDATA 段。
移除字符串中的一部分内容,该部分是给定子串第一次出现之前的部分。
${"abcdefgh"?keep_after("de")}
如果参数字符串没有找到,它会返回空串。如果参数是长度为0的字符串, 它会返回源字符串,不会改变。
该方法接受可选的 标志位参数,作为它的第二个参数:
${"foo : bar"?keep_after(r"\s*:\s*", "r")}
和 keep_after 相同, 但是它会保留参数最后一次出现后的部分,而不是第一次。比如:
${"foo.bar.txt"?keep_after_last(".")}
若使用 keep_after 则会得到 bar.txt。
移除字符串的一部分,该部分是从给定子串开始的部分。 比如:
${"abcdef"?keep_before("de")}
如果参数字符串没有找到,它会返回源字符串,不会改变。 如果参数是长度为0的字符串,它会返回空串。
该方法接受可选的 标志位参数,作为它的第二个参数:
${"foo : bar"?keep_before(r"\s*:\s*", "r")}
和 keep_before 相同, 但是保留参数最后一次出现之前的部分,而不是第一次出现之前。
${"foo.bar.txt"?keep_after_last(".")}
返回最后一次(最右边)字符串中出现子串时的索引位置。 它返回子串第一个(最左边)字符所在位置的索引。例如: "abcabc"?last_index_of("ab"):将会返回3。
字符串中字符的数量。
字符串的小写形式。
"GrEeN MoUsE"?lower_case 将会是 "green mouse"。
-  matches- 布尔值:如果字符串整体匹配了模式,就是 true, 否则就是false。比如:"fooo"?matches('fo*')就是true,但是"fooo bar"?matches('fo*')是false。
- 序列:字符串匹配的子串的列表。很有可能是长度为0的序列。
 
- 布尔值:如果字符串整体匹配了模式,就是 
-  number
字符串转化为数字格式。这个数字必须是 “计算机语言” 格式。也就是说, 它必须是本地化独立的形式,小数的分隔符就是一个点,没有分组。
在源字符串中,用另外一个字符串来替换原字符串中出现它的部分。 它不处理词的边界。比如:
${"this is a car acarus"?replace("car", ulldozer")}
将会输出:
this is a bulldozer abulldozerus
替换是从左向右执行的。这就意味着:
${"aaaaa"?replace("aaa", "X")}
如果第一个参数是空字符串,那么所有的空字符串将会被替换, 比如 "foo"?replace("","|"),就会得到 "|f|o|o|"。
replace 接受可选的 标志位参数,作为它的第三参数。
它被用来根据另外一个字符串的出现将原字符串分割成字符串序列。 比如:
<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>
- "some"
- ""
- "test"
- "text"
- ""
split 接受可选的 标志位参数, 作为它的第二个参数。由于历史使用 r (正则表达式)标志的差错;它会从结果列表中移除空元素, 所以在最后示例中使用 ?split(",", "r"), "" 会从输出中消失。
如果字符串以指定的子字符串开头,那么返回true。
"redirect"?starts_with("red") 返回布尔值 true,
"red"?starts_with("red") 也返回 true。
去掉字符串首尾的空格。例如:
(${"  green mouse  "?trim})
包含字符串中所有单词的序列,顺序为出现在字符串中的顺序。 单词是不间断的字符序列,包含了任意字符,但是没有 空白。例如:
<#assign words = "   a bcd, .   1-2-3"?word_list>
<#list words as word>[${word}]</#list>
将会输出:
[a][bcd,][.][1-2-3]
该内建函数和 xml 内建函数的唯一不同是 xhtml内建函数转义 ' 为 ',而不是 ', 因为一些老版本的浏览器不能正确解释 '。
sequence类型:
相当于数组、List、Set等集合类型
-  不能直接操作数组 ${arr},需要使用指令来输出序列类型
-  输出序列 -  <#list arr as ele> ${ele}-${ele?index} </#list>
 
-  
-  获取序列的长度: ${arr?sizt}
-  获取序列的第一个元素: ${arr?first}
-  获取序列的最后一个元素: ${arr?last}
-  倒叙输出序列: -  <#list arr?reverse as ele> ${ele}-${ele?index} </#list>
 
-  
-  升序输出序列: -  <#list arr?sort as ele> ${ele}-${ele?index} </#list>
 
-  
-  降序输出序列: -  <#list arr?sort?reverse as ele> ${ele}-${ele?index} </#list>
 
-  
hash类型:
相当于map类型
- 不能直接操作hash ${maps},需要使用指令来输出hash类型
<#list maps?keys as key>
	${key}-${maps[key]}
</#list>
<#list maps?values as value>
	${value}
</#list>
FreeMarker指令
#assign定义变量
<#assign str="hello">
${str}
<#assign num=1 >
#if #elseif #else逻辑判断
<#assign sum=60 >
<#if>
	<#elseif sum gt 60 && sum lt 80>
		合格
	<#else >
		不合格
</#if>
#list遍历
<#if user??>
	<#list arr?sort?reverse as ele>
        ${ele}-${ele?index}
    </#list>
</#if>
<#assign arr=[]>
<#list arr?sort?reverse as ele>
    ${ele}-${ele?index}
    <#else>
        如果arr为空,就执行这里的内容
</#list>
#macro自定义
创建自定义指令
<#macro hello>
Hello World
<#macro>
-----------------------
<#macro sum num1 num2>
${num1} + ${num2}
<#macro>
-----------------------
<#macro chengfabiao>
    <#list 1..9 as i>
         <#list 1..i as j>
       		  ${j} * ${i} = ${j*i}  
    	 </#list>
    </#list>
<#macro>
使用自定义指令
<@hello></@hello>
------------------------
<@sum 10 10></@sum 10 10>
------------------------
<@chengfabiao></@chengfabiao>
nested占位
- <@ 指令名>占位内容</@ 指令名> 
  - 占位内容会替换掉自定义指令中的<#nested>
 
<#macro hello>
Hello <#nested>
<#macro>
--------------------------
<@hello>World</@hello>
import导入模板
- 创建一个模板 ftlOne.ftl
<#macro hello>
Hello <#nested>
<#macro>
<#macro helloworld>
Hello World!!!
<#macro>
- 在ftlTwo.ftl中调用ftlOne.ftl
<#import "ftlOne.ftl" as one>
<@one.hello World>
<@one.helloworld>
include包含模板或文件
- 定义一个html文件 index.html(模板同理)
- 在indexDemo.html中调用
<#include "index.html">
FreeMarker运算符
算术运算符
- +、-、*、/、%,如果是多个字段必须在 ${}中使用
逻辑运算符
- &&、||、!
比较运算符
- > (gt):大于
- < (gl):小于
- > (gte):大于等于
- < (gle):小于等于
- ==:等于
- !=:不等于
空值运算符
- !:指定缺失变量的默认值,- ${value!}: 如果value值为空,则默认值是空字符串
- ${value!"默认值"}:如果value值为空,则默认值为 ”默认值“
 
- ??:判断变量是否存在,如果变量存在,返回true,否则返回false- ${value??}?string
 



















