文档章节

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

悠悠然然
 悠悠然然
发布于 2014/06/11 20:13
字数 2669
阅读 633
收藏 11

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

之所以挑这个呢,是因为以下几个原因:

  1. Antlr语言文件编写非常清晰,对于我这种Antlr盲来说,也可以看得懂,甚至可以照葫芦画瓢修改修改,这个非常重要,在后期作者进行了相当的语法改进,这个方面有极度体现

  2. 代码质量较好,使用sonar进行进行分析,给的结果都还是相当不错的,在作者看过的所有的模板语言中,算上成之选

  3. 语法结构与Velocity的非常接近,这点对我也非常重要,因为我的想法就是velocity语法有相当的接受度,与Velocity语法接近,velocity的一些使用者可以方便的进行切换

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

于是下载了源码,初端详还是不错的,但是在实现在几点和笔记诉求有差距:

第一我希望是弱类型,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的但是实在等不到,因此只好自己动手升级了。

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

© 著作权归作者所有

共有 人打赏支持
悠悠然然

悠悠然然

粉丝 2381
博文 184
码字总数 360373
作品 14
杭州
架构师
加载中

评论(11)

悠悠然然
悠悠然然

引用来自“真爱无情”的评论

我已经指定为 GBK编码
你加入群吧。
天水神一
天水神一
这些问到要到哪里发啊
天水神一
天水神一
他指定的的GBK也报错的
天水神一
天水神一
我已经指定为 GBK编码
悠悠然然
悠悠然然

引用来自“真爱无情”的评论

你们tinyspider爬一些网站有乱码问题,比如爬这个网址:http://www.siluke.com/0/104/104663/15739132.html
我把你们HttpVisitorImpl.java文件的 <dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>这个版本的换成这个版本的
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
乱码问题就解决了........................我建议你们赶快把这个升级了吧......不升级好多网站爬不了的
你发错地方了。 另外,默认的HttpVisitor获取是采用UTF-8的,如果需要别的编码如GBK,请注入一个指定为 GBK编码的即可。 谢谢,使用。
天水神一
天水神一
你们tinyspider爬一些网站有乱码问题,比如爬这个网址:http://www.siluke.com/0/104/104663/15739132.html
我把你们HttpVisitorImpl.java文件的 <dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>这个版本的换成这个版本的
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
乱码问题就解决了........................我建议你们赶快把这个升级了吧......不升级好多网站爬不了的
Sub
Sub
友情支持一下!13
悠悠然然
悠悠然然

引用来自“restmad”的评论

很好
正在添加高级特性,请持续关注。
悠悠然然
悠悠然然

引用来自“Dead_knight”的评论

支持~喜欢httl的飘过~
httl使用强类型,效率比tinytemplate高一些。 呵呵,如果不用考虑IO,大约效率是TinyTemplate的二倍 如果考虑IO,速度都会被IO拉下来,偏差就没有那么大了。 弱类型有个好处是,在展现层,更灵活,即使model层进行重构,只要类结构移动也没有问题,而强类型在这种情况就必须要重构了。 我个人比较倾向于使用弱类型。 谢谢关注
Dead_knight
Dead_knight
支持~喜欢httl的飘过~
【Java模板语言】TinyTemplate 实战 :Serlvet集成

Writer :BYSocket(泥沙砖瓦浆木匠) 一、什么是TinyTemplate 什么是模板语言? 模板语言是为了使用户界面与业务数据(内容)分离而产生的,并能生成特定格式的文档。 什么是TinyTemplate?...

泥沙砖瓦浆木匠
2015/11/04
0
4
TinyTemplate模板引擎火热出炉,正式开源了~~~

涉水模板引擎领域,纯属不小心。 在此对以下人员表示强烈感谢与致敬: @sub jetbrick作者 @sept @webit webit作者 @罗格林 rythm作者 @闲.大赋 beetl作者 以及许许多多虽然没有列出来,但是在...

悠悠然然
2014/06/18
0
29
Tiny模板引擎(Velocity Plus)应用示例

把TinyTemplate当成是Velocity的升级版其实也是可以的,毕竟它的语法是基到Veloccity扩展而来的,兼容度在80%以上。 至于TinyTemplate的实例是怎样的,且看下面: 宏的可变参数 在Java中的可...

悠悠然然
2015/02/05
0
8
Tiny快速入门之Web界面快速开发实践

前面讲了基于Tiny做服务,这篇来讲讲用Tiny怎么做界面。f 下面是一些常用的链接,供大家使用: GIT地址(必须是OSC家的):https://git.oschina.net/tinyframework/tiny 问题报告:https://git...

悠悠然然
2014/11/25
0
43
Tiny模板引擎--TinyTemplate

Tiny模板引擎 是一个基于Java技术构建的模板引擎,它具有体量小、性能高和扩展易的特点。 适合于所有通过文本模板生成文本类型内容的场景,如:XML、源文件、HTML等等,可以说,它的出现就是...

悠悠然然
2014/06/18
2.2K
1

没有更多内容

加载失败,请刷新页面

加载更多

linux运维人员必会运维工具

linux运维人员必会开源运维工具体系 说明:不同的技术人员,不同的阶段确定知识边界非常重要,否则,就像马拉车,不知道终点在哪,累死也达不到目标。例如拿8K要学多少,拿15K要学多少。一个...

寰宇01
7分钟前
1
0
10大PHP比特币开源项目

如果你是一个Phper,如果你希望学习区块链,那么本文列出的 10个开源的Php比特币项目,将有助于你了解在自己的应用中 如何加入对比特币的支持。 如果你希望快速掌握使用Php对接比特币钱包的方...

汇智网教程
28分钟前
0
0
springclould feign客户端添加全局参数

用springclould feign作为调用服务的客户端,一般来说参数可以写在feignclient的方法参数里 有时需要所有feign请求都统一添加一些参数,例如token用于鉴权等,可以这样做: 添加一个配置类,...

canneljls
29分钟前
0
0
win32截屏并rgb24转yuv420

//最终f的内存布局为BGRA格式,需要保证buf长度足够(>w*h*4)void ScreenCap(void* buf, int w, int h){ HWND hDesk = GetDesktopWindow(); HDC hScreen = GetDC(hDesk); ......

styleman
今天
1
0
php输出mysql取出的中文为??的问题

解决方法: @ $db=new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_DB); $db->query("set names utf8");//添加此语句,可以解决问题...

Aomo
今天
1
2

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部