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


本来是没有自己写一个模板引擎的计划的,因为按我的理解,一直认识这种“语言”级的引擎,难度是非常大的。总感觉自己的水平不够,因此不敢有这个念头。直到大量使用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[}] ]  显示内容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)

注释:

##单行注释

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

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

#[[
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()}

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

下面看看实际演练:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

<!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>

下面是渲染结果:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

<!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行。

下面是程序代码:

?


1

2

3

4

5

6

7

8

    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的但是实在等不到,因此只好自己动手升级了。

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

时间: 2024-10-31 04:59:09

TinyTemplate(Velocity Plus版)即将火热推出~~~的相关文章

Verizon版iPhone的推出将使得每季度出货量增加800万部

一名分析师周四称,iPad 2将成为苹果第一款采用双核ARM处理器的移动产品.不管这一消息是否准确,苹果iPad最终将会跨入双核的行列,以同即将上市的摩托罗拉平板和RIM Playbook竞争,这两款平板均采用双核处理器.美国投行Rodman & Renshaw分析师阿肖克·库马尔(Ashok Kumar)周四在一份研究报告中表示,"苹果正在准备于明年3月更新iPad产品线,随后的夏末更新iPhone产品.这些平台升级的一个重要部分将是一款1GHz ARM Cortex A9双核处理器.

“小米1S电信版和联通版即将上市”的配图使用魅族MX图片

凡客再次现乌龙,凡客http://www.aliyun.com/zixun/aggregation/2934.html">资讯中心文章"小米1S电信版和联通版即将上市"的配图使用魅族MX图片.百度识图的对比结果. TechWeb把凡客资讯中心的配图上传到"百度识图"进行对比之后,百度识图给出的结果为:魅族MX. 此图一出,激起微博热议,再次讨论"小米手机在抄袭魅族".@河蟹新闻:抄魅族抄得连图片都分不清了.网友批评说到,小米一直在

嘉实基金即将独家推出一项定制服

新京报讯 (记者苏曼丽)阿里巴巴纽交所上市在即,记者昨天从嘉实基金公司获悉,嘉实基金即将独家推出一项定制服务,专门服务于打新阿里美股.记者了解到,该服务的门槛仅为1000元.此外,华夏基金等基金公司也都正在酝酿相关产品,云集阿里IPO打新. 据了解,此次针对阿里IPO的团购打新服务,将通过其定制账户实现.最快下周就可以通过嘉实定制账户的官网或APP申请.2012年12月17日,嘉实基金在业内首推定制账户,起初以开放式基金为投资标的,每个投资者的定制账户相对独立,由投资者授权嘉实代为管理.此外,华

SolidFire公司CEO谈即将秘密推出的超融合型系统

NetApp公司联合创始人Dave Hitz与SolidFire公司总经理Dve Wright可能正在酝酿一份超融合型基础设施设备大礼包 SolidFire公司掌门人Dave Wright在日前的采访当中讨论了其即将推出且基于自家节点的超融合型系统. Wright此前曾任SolidFire公司CEO,并于2015年年末NetApp对其展开收购后成为后者旗下的副总裁兼SolidFire总经理. 尽管作出询问,但Wright仍然拒绝透露任何与产品相关的具体详情或者上市时间表. 他确认称,该产品将继续

微软官方预告:Win10创意者更新正式版即将发布

3月15日消息 今天微软推送了最新的Win10一周年更新正式版累积更新14393.953,不过在升级系统重启后我们在更新状态页面可以看到,微软已经向正式版用户预告Win10创意者更新正式版即将发布.根据此前消息,Win10创意者更新RTM将在3月签署,预计3月底或4月初推送正式版. Windows10一周年更新正式版用户升级到Build 14393.953后,在Windows更新状态就会看到微软提醒:"好消息!Win10创意者更新即将发布.是否想要成为第一个获取更新的用户?" 后面还有

阿里小微即将再推出第二期的理财产品―――定期宝

摘要: 一则普通的任命,再一次将暂时沉寂的阿里巴巴IPO推向前台.上周,香港财政司司长曾俊华宣布委任马雪征担任证监会非执行董事,任期两年.该委任被资本界解读为,继 香港交易所 一则普通的任命,再一次将暂时沉寂的阿里巴巴IPO推向前台.上周,香港财政司司长曾俊华宣布委任马雪征担任证监会非执行董事,任期两年.该委任被资本界解读为,继 香港交易所 总裁李小加后,又一有内地背景的人士出任香港金融机构的职位. 不过,引人关注的是马雪征兼任的私募股权基金博裕资本主席身份.2012年,通过一项阿里集团的普通股

Linux Mint 18.1&quot;Serena&quot;将于12月发布 公测版即将推出

今天公布的月度简报上,Linux Mint负责人Clement Lefebvre重申强调了关于即将到来Linux Mint 18.1 "Serena"操作系统的相关信息.该发行版本目前仍在开发进程中,将会搭载最近发布的Cinnamon 3.2桌面环境和MATE 1.16.Beta版本已经准备好进行公测,但目前还有部分BUG需要调整和修复. Clement Lefebvre说道:"我们刚刚完成了对MDM部分问题的修复,目前我们正着手修复影响Cinnamon screensave

Tiny框架2.0版火热推出

方法论 方法论决定了可以达到的高度 方法论,就是人们认识世界.改造世界的根本方法. 它是人们用什么样的方式.方法来观察事物和处理问题.概括地说,世界观主要解决世界"是什么"的问题,方法论主要解决"怎么办"的问题.  方法论是一种以解决问题为目标的体系或系统,通常涉及对问题阶段.任务.工具.方法技巧的论述.方法论会对一系列具体的方法进行分析研究.系统总结并最终提出较为一般性的原则.  方法论也是一个哲学概念.人们关于"世界是什么.怎么样"的根本观点

久游网即将要推出交友网站

中介交易 SEO诊断 淘宝客 云主机 技术大厅 据消息人士透露,久游网即将推出基于游戏的交友网站--久友网,目前正在测试阶段;另据可靠消息,QQ也正在研发SNS产品,推出校园平台等产品,把Qzone等业务结合到一起;搜狐也在看到这个市场,重整ChinaRen校友录模式.百度还正在想把旗下业务整合好的模式,如果想通了,相信也会迅速挺进的. 近年来,随着Facebook概念在中国的火热.中国出现了众多SNS的交友网站,如51.校内.360圈,爱情公寓.但是几家欢乐多家愁,从模式上来讲,各家网站大同小