TinyTemplate(Velocity Plus版)即将火热推出~~~

原本是没有本身写一个模板引擎的计划的,由于按个人理解,一直认识这种“语言”级的引擎,难度是很是大的。总感受本身的水平不够,所以不敢有这个念头。直到大量使用Velocty的时候,碰到velocty诸多尽如人意的地方,可是又无能为力,退回到JSP吧,又心不有甘。因而就指望着寻找一种语法结构接近velocty,可是又没有Velocity这些不方便之处的模板语言。因而进到一个模板语言群,一群大佬们个个至少是一个模板语言的做者,因而做者在里面表达了本身的指望,大佬们都介绍了本身的模板引擎,因而做者一个接一个的看源码,看文档。说实际,看文档,感受都很是不错,都有本身的特点,看语法也都不错,除了一部分本身特别关注的点没有以外,其部分都很是不错了。可是距离本身的诉求仍是有差距,怎么办呢?因而就准备找一个最接近的模板引擎来进行必定的扩展,挑来挑去就挑中了jetbrick这个模板语言(在此对Jetbrick致以强烈的衷心的感谢!!)。css

之因此挑这个呢,是由于如下几个缘由:html

  1. Antlr语言文件编写很是清晰,对于我这种Antlr盲来讲,也能够看得懂,甚至能够照葫芦画瓢修改修改,这个很是重要,在后期做者进行了至关的语法改进,这个方面有极度体现java

  2. 代码质量较好,使用sonar进行进行分析,给的结果都仍是至关不错的,在做者看过的全部的模板语言中,算上成之选git

  3. 语法结构与Velocity的很是接近,这点对我也很是重要,由于个人想法就是velocity语法有至关的接受度,与Velocity语法接近,velocity的一些使用者能够方便的进行切换express

  4. 测试用例比较完善,当时也就是这么一看,可是最后Tiny模板引擎完成以后,利用其测试用例进行测试发现了好几个BUG,说明仍是很是有效果的json

因而下载了源码,初端详仍是不错的,可是在实如今几点和笔记诉求有差距:api

第一我但愿是弱类型,jetbrick是强类型,性能是有提升可是开发过程会比较不方便。数组

另外因为jetbrick做者指望在编译器进行强类型推测,所以致使运行期的内容与编译期的内容有比较强的耦合。框架

另外有一些语言特性,属于我的爱好上的缘由,也有一些差别,所以就决定本身编写一个。函数

语法规范

为了更好的说明Tiny的语法规范,所以全程对比Velocity

说明,<>中的内容表示必须有至少一个,[]中的内容表示能够有能够没有。

References

表达式

${表达式}

表达式是指最后的运算结果是一个值,表达式中可使用变量

=>与Velocity区别,这里大括号必须有,不能省略,“-”号不容许出现

${a+b-c+d}

${"abc"+1}

${user.name}

${user.items[1].count+3}

${user.func(1,2,3,4)+map.def+map["aa"]}

变量

<a->[_a-zA-z0-9]

=>与Velocity区别,“-”号不容许出现

示例:

合法

  • abc

  • ab_c

  • Ab9_

非法

  • 9bc

  • _bc

  • a-b

属性值

属性语法与变量名同样

区别大括号必须有,“-”号不能够有

属性值实际上也是个表达式,所以这么写也是能够的

${a.("aa"+bb)},若是bb的值为3,则等同于${a.aa3},等同于a."aa3"

指令

#set - 赋值指令

Format:

#set ( ref = [ ", ' ]arg[ ", ' ] )

示例

#{set}不被支持

变量名前面不能够加$

#set(aa=1)

#set(aa=2,b=2,c=aa+2,d=func("info"))

#set(aa=[aa,"bb",2,3,4]

#set(aa={"aa":1,bb:2,aa.bb.func()+3:5}

#if/#elseif/#else - 判断语句

格式:

#if( [condition] ) [output] [ #elseif( [condition] ) [output] ]* [ # [ { ] else [ } ] [output] ] # [ { ] end [ } ]

用法:

#if(aa)

#end

#if(aa||bb)

#end

这里便可以是逻辑表达式,也能够是非逻辑表达式

状况以下:

若是是null,则false

若是是boolean值,看true/false

若是是String,看长度>0

若是是Collection,看Size>0

若是是Iterator看hasNext

若是是数组,看长度>0

若是是Enumerator,看hasMoreElements

若是是Map看size

其它状况,就返回true

下面全部的逻辑表达式都支持

Operator Name  
Symbol    
Alternative Symbol    
Example

Equals Number  
==    
eq    
#if( $foo == 42 )

Equals String  
==    
eq    
#if( $foo == "bar" )

Object Equivalence  
==    
eq    
#if( $foo == $bar )

Not Equals  
!=    
ne    
#if( $foo != $bar )

Greater Than  
>    
gt    
#if( $foo > 42 )

Less Than  
<    
lt    
#if( $foo < 42 )

Greater Than or Equal To  
>=    
ge    
#if( $foo >= 42 )

Less Than or Equal To  
<=    
le    
#if( $foo <= 42 )

Boolean NOT  
!    
not    
#if( !$foo )

Notes:

  1. ==用的是equals

  2. 能够用下面的方式来避免与显示内容分不开

#if(foo == bar)it's true!#{else}it's not!#end</li>

注意:与Velocity区别:变量名前面不要加“$”符号

#for - for循环指令

Format:

# for(varName : collection) 显示内容1 [#[{]else[}] ]&#160; 显示内容2 # [ { ] end [ } ]

表示对集合进行循环,执行显示内容1,若是集合为空,则执行显示内容2

注意:与Velocity区别:增了了#else指令

能够是collection的内容:

数组、集合、Iterator,Enumeration,Map,对象,甚至null

若是不是集合对象,只是一个普通对象,就只循环次,这比较适合于有时候会返回列表,有时候会返回一个对象的状况,就避免了增长复杂的判断。

#include - 包含指令

Format:

#include(expression[,{aa:1,bb:2}])

示例:

#include("/aa/bb/cc.vm")

#include("/aa/bb/cc.vm")

与Velocity的区别:用于把另外的页面在当前位置进行渲染,后面只能加一个Map用来传递参数

#parse:指令已经没有意义被取消
#stop - Stops the template engine

Format:

#stop[(expresson)]

Usage:

#if(aa==bb)

#stop

#end

等价于

#stop(aa==bb)

#break - Stops the current directive

Format:

#break[(expresson)]

Usage:

#if(aa==bb)

#break

#end

等价于

#break(aa==bb)

#continue[(expresson)]

Usage:

#if(aa==bb)

#continue

#end

等价于

#continue(aa==bb)

#evaluate - Dynamically evaluates a string or reference因为难用被取消,且用处过小被取消

增长指令#[@]call

#call("aa"+"bb",1,2)

等同于

#aabb(1,2)

#call(format("Sys%sMdl%s",1,2),1,2)

等同于

#Sys1Mdl2(1,2)

#@call("aa"+"bb",1,2)

...

#end

等同于

#@aabb(1,2)

...

#end

#@call(format("Sys%sMdl%s",1,2),1,2)

...

#end

等同于

#@Sys1Mdl2(1,2

...

#end

另外支持命名传递,详见宏调用

#define - 因为鸡肋被取消,调用者中的全部变量对于被调用者均可见,再也不须要显式传递
#macro - 定义宏

Format:

# macro macroName( arg1 [, arg2,arg3 ... argn ] ) [ VM VTL code... ] # [ { ] end [ } ]

与 Velocity不一样:macroName由括号里放在了括号外面,避免与参数混一块儿,参数之间必须用逗号隔开

调用宏有两种方式

#vmname( arg1,arg2 )

#@vmname(arg1,args)

....

#end

与Velocity不一样:支持命名调用:

好比下面的方式; #vmname(arg2=3),也能够混用:#vmname(1,2,arg5=3,arg4=4)

注释:

##单行注释

#-- ... --#&#160; #* ... *#,两种格式支持,是考虑到在<!-- -->的时候,改为#-- --#更方便

非解析标记,下面的内容会原样输出

#[[
This has invalid syntax that would normally need "poor man's escaping" like:

    • #define()

  • ${blah

]]#


新增长内容:i18n支持:

$${aaa.bbb.ccc}

表示显示aaa.bbb.ccc对应的国际化内容

固然,还有强大的布局(页面继承),容易的使用(会vm的到如今已经会用),方便的扩展(很是容易扩展),微小的体量(引擎只有2000行代码),还想要什么,能够尽情提出。

新增内容:Java对象方法扩展,即在不修改原类的状况下,对java类添加

好比能够为String增长bold函数,经过下面的方式来进行加粗

${“悠然是个好同志”.bold()}

也能够给 Object增长toJson,toXml等方法,从而直接用下面的方式输出json或xml:

${user.toJson()},${user.toXml()}

固然,如今还有一点计划中的特性没有实现,那就是装饰方式的布局方式,可能有些同窗不了解,那就先留点悬念吧。

下面看看实际演练:

<!DOCTYPE html>
<html>
<head>
    <title>StockModel - Httl</title>
    <meta http-equiv="Content-Type" content="text/html; charset=${outputEncoding}"/>

    <style type="text/css">
        body {
            color: #333333;
            line-height: 150%;
        }

        td {
            text-align: center;
        }

        thead {
            font-weight: bold;
            background-color: #C8FBAF;
        }

        .odd {
            background-color: #F3DEFB;
        }

        .even {
            background-color: #EFFFF8;
        }
    </style>
</head>
<body>
<h1>StockModel - jetbrick-template</h1>
<table>
    <thead>
    <tr>
        <th>#</th>
        <th>id</th>
        <th>code</th>
        <th>name</th>
        <th>price</th>
        <th>range</th>
        <th>amount</th>
        <th>gravity</th>
    </tr>
    </thead>
    <tbody>
    #for(item : items)
    <tr class="${itemFor.index % 2 == 1 ? "even" : "odd"}">
        <td>${itemFor.index}</td>
        <td>${item.id}</td>
        <td>${item.code}</td>
        <td style="text-align: left;">${item.name}</td>
        <td>${item.price}</td>
        <td style="color: ${item.range>=10?'red':'blue'};">${item.range}%</td>
        <td>${item.amount}</td>
        <td style="color: ${item.gravity>=20?'red':'blue'};">${item.gravity}%</td>
    </tr>
    #end
    </tbody>
</table>
</body>
</html>

下面是渲染结果:

<!DOCTYPE html>
<html>
<head>
    <title>StockModel - Httl</title>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk"/>

    <style type="text/css">
        body {
            color: #333333;
            line-height: 150%;
        }

        td {
            text-align: center;
        }

        thead {
            font-weight: bold;
            background-color: #C8FBAF;
        }

        .odd {
            background-color: #F3DEFB;
        }

        .even {
            background-color: #EFFFF8;
        }
    </style>
</head>
<body>
<h1>StockModel - jetbrick-template</h1>
<table>
    <thead>
    <tr>
        <th>#</th>
        <th>id</th>
        <th>code</th>
        <th>name</th>
        <th>price</th>
        <th>range</th>
        <th>amount</th>
        <th>gravity</th>
    </tr>
    </thead>
    <tbody>
    
    <tr class="even">
        <td>1</td>
        <td>1</td>
        <td>600663</td>
        <td style="text-align: left;">Company 01</td>
        <td>20.55</td>
        <td style="color: red;">10.01%</td>
        <td>2.13 HM</td>
        <td style="color: red;">24.29%</td>
    </tr>
    
    <tr class="odd">
        <td>2</td>
        <td>2</td>
        <td>600822</td>
        <td style="text-align: left;">Company 02</td>
        <td>14.69</td>
        <td style="color: red;">10.04%</td>
        <td>1.56 HM</td>
        <td style="color: red;">36.79%</td>
    </tr>    
    </tbody>
</table>
</body>

补充一下,上面原本是有20行数据的,为了节省空间,给删除了18行。

下面是程序代码:

    public static void main(String[] args) throws TemplateException {
        TemplateEngine engine = new TemplateEngineDefault();
        TemplateContext context=new TemplateContextDefault();
        context.put("outputEncoding","GBK");
        context.put("items", StockModel.dummyItems());
        engine.addTemplateLoader(new FileObjectTemplateLoader("jetSample", "D:\\git\\ebm\\src\\main\\resources\\templates"));
        engine.renderTemplate("/tiny.html",context,new OutputStreamWriter(System.out));
    }

固然了,可能你们对性能很是感兴趣。

Tiny框架的性能比Beetl-1.26稍微落后一点点,可是明显比Velocity和FreeMarker是快多了。

与前面几个引擎比较,性能差别主要在:

1.强类型与弱类型方面的差别,TinyTemplate采用的是弱类型,而一些模板引擎采用的是强类型。

2.其它引擎都已经通过了长时间的优化,而 TinyTemplate只是刚二通过不到一周的初始期。经过后面的一些优化,他将有必定的提高(可是达不到Jetbrick这个程度)

这天这个只是开胃菜,亲们耐心等待个人正式发布吧。

附录:

TinyTemplate历史三天编写,代码行数量截止发稿为在3410,预计完稿后,在3700行左右。

JetBrick为1.3万+

Beetl为1.7万+

对于Velocity用户来讲,迁移很是容易。

原本但愿velocity升级2.0的可是实在等不到,所以只好本身动手升级了。

凡有好的意见、建议、需求的,所有采纳并快速实现,在此提早致以感谢!

相关文章
相关标签/搜索