低代码探索:freemarker 的模板和表达式
系列文章:
一 概述
在低代码探索:Java 模板引擎技术 中,我们介绍了 freemarker 的概念和简单使用示例。本篇会详细介绍一下 freemarker 中的表达式,这在使用时很重要。我们通过模板定义要生成的页面框架,通过表达式来实现参数占位/替换,输入变量的首字母大/小写转换,以及 for 循环遍历等等。通过模板与表达式的配合,生成所需的页面/代码文件。
二 模板
关于模板的介绍,可以先看看freemarker在线手册的内容。FTL (即 FreeMarker template language),就是 freemarker 为编写模板设计的非常简单的编程语言。
2.1 FTL 介绍
模板(FTL 编程)是由如下部分混合而成的:
文本:文本会照着原样来输出。
插值:这部分的输出会被计算的值来替换,相当于模板中的“变量”。插值由
${
and}
所分隔(或者#{
and}
,这种风格已经不建议再使用了,使用 number_format 设置项 和 the string 内建函数 来代替。对于计算机使用 (也就非本地的格式化)的格式化,使用 c 内建函数 (比如number?c
)。)。例如,我们有两个变量 x 和 y,x
=2.582
而y
=4
,那么常用的插值表达式和对应的取值如下面所示:
FTL 标签:FTL 标签和 HTML 标签很相似,但是它们却是给 FreeMarker 的指示, 而且不会打印在输出内容中。
注释:注释和 HTML 的注释也很相似,但它们是由
<#--
和-->
来分隔的。注释会被 FreeMarker 直接忽略, 更不会在输出内容中显示。
2.2 模板示例
下面是手册中提供的一个 HTML 页面的模板示例:其中,蓝色代表文本,橘黄色代表插值(${user}),黄色代表 FTL 标签(<#list animals ...),而绿色是注释, [BR]是为了在页面上显式可见的换行:
FTL 有几点注意事项需要特别指出:
1、FTL 区分大小写,例如 list 是指令的名称,而 List 不是(切记!),${name} 和 ${Name}
或 ${NAME}
也不相同。
2、插值 仅仅可以在 文本(或字符串表达式)中使用。
3、FTL 标签 不可以在其他 FTL 标签 和 插值中使用。比如, 这样做是 错误 的: <#if <#include 'foo'>='bar'>...</#if>
4、注释 可以放在 FTL 标签 和 插值中。示例:
2.3 指令
FTL 的指令是通过标签来调用,例如上面用到的<#list animals as animal>,使用到了 list 这个指令,代表遍历 list 中的每个变量。除了 list 之外,常用的还有<#if>
FTL 的指令有两种类型: 预定义指令 和 用户自定义指令。详细说明可以参见链接,这里不再赘述,有疑问可以共同探讨。
2.4 表达式
FTL 的表达式主要包括 直接确定值(字符串、数字、布尔值、序列、值域、哈希表)、检索变量、字符串操作、序列操作、哈希表操作等等。在定义模板时,使用最多的是直接确定值(字符串、数字),其次是检索变量和字符串操作。
检索变量示例:我们在外层定义好一个 user 对象,包含 name, age 等属性,那么在模板中应用时,可以通过 ${user.name}, ${user.age}来获取对应的值并替换到模板中对应的位置;
字符串操作示例:字符串连接:"Hello ${user}!" ;获取一个字符:name[0];字符串切分: 包含结尾: name[0..4]
,不包含结尾: name[0..<5]
,基于长度(宽容处理): name[0..*5]
,去除开头: name[5..]
。
2.5 插值
插值是用来给 表达式
插入具体值然后转换为文本(字符串)。用我们更熟悉的表述,就是模板中的占位符,用来标记某个位置是一个变量,在生成代码时,可以通过传入我们定义好的值,模板进行识别并完成替换,从而生成我们最终想要的文件。
插值的使用格式: ${expression}
,这里的 expression
可以是所有种类的表达式(比如 ${100 + x}
)。
完整的示例和说明还是推荐查看手册:插值。
三 模板使用和生成示例
接下来,我们还是通过 demo 来阐述 freemarker 模板定义到生成文件的整个过程,jar 包的引入方式在低代码探索:Java 模板引擎技术中已经有过说明,这里只列举模板和代码部分。
3.1 模板定义
test.java.ftl:
这个模板定义了一个典型的实体类,也就是 POJO。属性列表我们通过 colList 参数传入,并在外层加了 if 的判断,避免参数为空的情况;对于 list 中的每个变量,都是一个 col 对象,里面有 type 和 name 两个属性,上述模板先逐个生成 private Integer id; xxx 这些字段,然后再依次生成对应的 getId setId。。。 方法。
因为 get set 方法需要的是变量名的首字母大写,所以这里还使用了 get${col.name?cap_first}来对首字母进行大写处理。
3.2 column 实体类定义
Column 用于封装参数,有 type 和 name 两个属性。 这里为了简化代码 引入了 lombok,在 pom.xml 中增加相关依赖引入即可:
3.3 生成代码方法
主要就是完成参数封装,模板加载和生成方法与上一篇内容相似。
我们执行 FreemarkerTest 的 main 方法,生成 Test.java 文件如下:
四 总结
本篇对 freemarker 进行了深入一些的描述,并对上一篇的示例做了部分调整,使用了 list、if 等表达式、指令、插值这些 freemarker 的概念。
完整工程代码,可关注公众号回复 freemarker 引擎获取。
版权声明: 本文为 InfoQ 作者【程序员架构进阶】的原创文章。
原文链接:【http://xie.infoq.cn/article/d14013cd395849902aa5921d5】。文章转载请联系作者。
评论