第一:
HTTL只有六个指令:#set, #if, #else, #for, #break, #macro,并且不会增加。
<!--## 定义变量类型,未定义的变量以Object类型处理 -->
<!--#set(User user, List<Book> books)-->
<html>
<body>
<!--## 定义宏,可当变量或方法执行 -->
<!--#macro(cover(Book book))-->
<img alt="${book.title}" src="${book.cover}" />
<!--#end-->
<!--## 条件判断 -->
<!--#if(user.role =="admin")-->
<table>
<!--## 循环输出,类型可省,将基于泛型推导 -->
<!--#for(Book book : books)-->
<tr>
<!--## 变量输出 -->
<td>${book.title}</td>
<!--## 执行宏输出,也可以用${cover} -->
<td>$!{cover(book)}</td>
<!--## 变量赋值,类型可省,将基于表达式推导 -->
<!--#set(int price = book.price * book.discount)-->
<td>${price}</td>
</tr>
<!--## 条件中断循环 -->
<!--#break(for.index == 10)-->
<!--## 当循环数据为空时执行 -->
<!--#else-->
没有数据。
<!--#end-->
</table>
<!--#else(user)-->
没有权限。
<!--#else-->
没有登录。
<!--#end-->
</body>
</html>
变量指令
#set变量类型
声明变量的类型,模板内部其它变量类型基于此类型推导。
1
2
3
4
5
|
格式:
#set(type name, type name)
示例:
#set(User user, List<
Book
> books)
|
注:暂时只支持List和Map的一级泛型,多级泛型能解析,但不能推导。
多次设置变量的类型,如果类型为父子关系,以子类型优先:
1
2
|
#set(ParentClass var1)
#set(ChildClass var1)
|
不管先后顺序,都以子类型优先:
1
2
|
#set(ChildClass var1)
#set(ParentClass var1)
|
如果是两个完全不同的类型,将报错:
1
2
|
#set(OriginClass var1)
#set(DiffrentClass var1)
|
#set变量赋值
将表达式的计算结果存入变量中。
1
2
3
4
5
6
7
8
9
10
|
格式:
#set(name = expression)
#set(type name = expression)
#set(name := expression)
#set(type name := expression)
示例:
#set(price = book.price * book.discount)
#set(int price = book.price * book.discount)
|
注意,为了简化模板的书写,#set的变量全模板有效,不限制在块指令内:
1
2
3
4
|
#if(xxx)
#set(var ="value") // 变量全模板有效,而不是if块内有效
#end
${var} // 可以访问到if块内var的值
|
不需要像Java那样:
1
2
3
4
5
|
#set(var = null)
#if(xxx)
#set(var ="value")
#end
${var}
|
类型的声明,同时可以用作强制转型,比如:
1
|
#set(Book book = bookentry.value)
|
如果bookentry.value的类型丢失,上面的写法可以恢复book的类型。
一个set指令可同时有多个类型声明或赋值,用逗号分隔,但类型声明和赋值要分开写,如:
1
2
|
#set(User user, List<
Book
> books)
#set(price = book.price, discount = book.discount)
|
赋值会在生成局部变量的同时,写入当前Context中, 如果有include()子模板,在子模板中也可以读到该变量。
指令对比
Velocity | HTTL | 异同 | 功能 | 变化 |
${xxx.yyy} $xxx.yyy | ${xxx.yyy} | 相同 | 输出占位符 | HTTL大括号必需 |
$!{xxx.yyy} $!xxx.yyy | $!{xxx.yyy} | 不同 | 空值不显示源码 | VM为空值不显示源码 HTTL改为不过滤输出 |
## ... #* ... *# | ## ... #* ... *# | 相同 | 不显示注释块 | |
#[[ ... ]]# | #[ ... ]# | 相似 | 不解析文本块 | HTTL少一对方括号 |
\# \$ \\ | \# \$ \\ | 相同 | 特殊符转义 | |
#set($xxx = $yyy) | #set(xxx = yyy) #set(Type xxx = yyy) #set(Type xxx) | 相同 | 给变量赋值 | HTTL可带类型声明 |
#if($xxx == $yyy) | #if(xxx == yyy) | 相同 | 条件判断 | |
#elseif($xxx == $yyy) | #else(xxx == yyy) | 相似 | 否则条件判断 | HTTL复用#else指令 |
#else | #else | 相同 | 否则判断 | |
#end | #end #endif #end(if) | 相同 | 结束指令 | HTTL可带配对指令名 |
#foreach($item in $list) | #for(item : list) #for(Type item : list) | 相似 | 列表循环 | HTTL改为Java格式 |
#break | #break #break(xxx == yyy) | 相同 | 中断循环 | HTTL可以直接带条件 |
#stop | #break #break(xxx == yyy) | 相似 | 停止模板解析 | HTTL复用#break指令 |
#macro($xxx) | #macro(xxx) | 不同 | 可复用模板片段宏 | VM将宏作为指令执行 HTTL作为函数执行 |
#define($xxx) | #macro(xxx = xxxmacro) | 相似 | 捕获块输出到变量中 | HTTL复用#macro指令 |
#include("xxx.txt") | ${read("xxx.txt")} | 相似 | 读取文本文件内容 | HTTL改为函数扩展 |
#parse("xxx.vm") | ${include("xxx.httl")} | 相似 | 包含另一模板输出 | HTTL改为函数扩展 |
#evaluate("${1 + 2}") | ${render("${1 + 2}")} | 相似 | 模板求值 | HTTL改为函数扩展 |