2011年发布Beetl 0.5的时候,新闻是在Iteye上发布的,老资格程序员可能预料Iteye上会发生什么了,我收到的最多的不是鼓励和喝彩,而是吐槽,”又是一个轮子“是里面最大的声音。尽管4年前的版本还只是个雏形,但实际上已经开始有了与众不同创新点。我将在本文介绍一下Beetl的创新点和创新思路,希望有志从事开源开发的人能借鉴
freemarker 当初为什么能从模板引擎中脱颖而出,其实与当时XML流行无不关系。程序员习惯了用XML来处理问题,配置也好,流程说明也好,交互接口也好,无处不有XML,像我一样的大多数程序员,自然就接收了freemaker, 当我在确定Beetl的风格的时候,首先就排除了XML,因为2010后,XML已经不流行了,程序员更加务实了。我打开记事本,写了几种风格的模板语法,最后还是确定了类似JS风格
var a = 1; var b= a+2; for(item in items){ print(item.name); }
尽管语法上没有创新,但将脚本风格的语法应用在模板上还是创新的,独此一家。这是因为:
模板语言是嵌入在模板里的,所有涉及到定界符号和站位符号,其他模板语言定界符号都是固定的,如JSP总是用<%%> ,php 用的是<? ?>,veclociy 是采用# 和回车换号符号。Beetl 则完全能自定义定界符和占位符号,适用于各种应用场景,比如可以定义#和回车作为定界符号
#for(item in items){ <td>${item.name}</td> #}
也可以定义注释符号作为定界符
<!--: for(item in items){ --> <td>${item.name}</td> <!--:}-->
正如Beetl能自定义定界符和站位符号,Beetl也许是唯一一个能用beetl模板生成beetl模板的模板引擎,而其他模板引擎则太费劲才能完成这个任务
Beetl在线体验里,有beetl语法体验,可以输入beetl代码,运行,获得期望输出,如果用户输入while(true), 这将对服务器造成伤害,大部分后来跟随Beetl的在线体验模板引擎,比如freemarker,rythmn,tinytemplate 都对此无能为力,或者通过kill thread方式来避免用户乱搞。但Beetl不是,Beetl定制了While循环处理节点,循环超过5次就结束循环。
还有在我主导的另外一个开源Beetl SQL里,也有类似需要,如下SQL模板,
select * from user where 1=1 -- if(user.name!=null) and name = ${user.name} --}
(注,--是定界符,伪装成注释,这样容易在sql客户端调试)当执行模板的时候,${user.name} 并不是需要输出其属性值,而是需要输出?,并记录其值以便随后操作
select * from user where 1=1 and name = ?只需要定制Beetl模板引擎,修改 PlaceholderST 节点,改成如下代码即可
public final void execute(Context ctx) { Object value = expression.evaluate(ctx); ctx.byteWriter.writeString("?"); List list = (List)ctx.getGlobal("_paras"); list.add(value); }
定制模板引擎作为高级特性,已经有数个项目被应用到,这在其他模板引擎里不可想象的
在Beetl推出Ajax标记之前,前端开发者都认为模板引擎和Ajax水火不容,Beet改变了这个现状,通过推出Ajax标志支持,完美结合了模板引擎渲染和无刷新的Ajax。消除了各自的缺点
<div id="table-container" > <% //ajax片段开始 #ajax userTable: { %> <table> <tr><td width=100>id</td><td width=100>姓名</td></tr> <%for(user in users){%> <tr><td>${user.id}</td><td>${user.name}</td></tr> <%}%> </table> 当前页面<span id="current">${page!1}</span><span style="width:20px"></span> <a href="#"><span class="page">next</span></a> <a href="#" ><span class="page">pre</span></a> <% //ajax片段结尾 } %>
如上代码所示,如果渲染整个页面,如render("user.html").则ajax标记忽略,模板正常渲染,如果后台仅仅渲染render("user.html#userTable"); 则模板引擎会找到userTable 的标记,仅仅渲染这一部分。
正如在我的文章里提到过,单纯用js来实现ajax,会有一些问题,如
用了Beetl Ajax标记,能完美解决这些问题,其他模板引擎,无论是老资格Freemaker,还是新出现的tinytemplate,都不具备这个功能。我觉得这些模板引擎应该顺应web技术发展新方向,像Beetl那样推出ajax局部渲染技术
尽管所有模板引擎支持MVC分层开发,但实际上在Beetl之前,谁能正正提供分层呢?所谓分层开发,不但是可以单独开发,而且还需要单独测试而无需其他层(M和V)。也只有Beetl才能做到这真正做到一点,关于如何实现,可以参考官网,或者我的一个开源项目BingoUI,没有用任何后台代码实现的一个UI标签库,一套前端代码同时支持pc和mobile
Beetl虽然引用在模板领域,但实际上本质上时个脚本语言,为了模板输出定制的语言,因此他有许多创新语法,着在其他模板引擎里很少有,或者他们都是借鉴Beetl的
除此之外,还有很多实用功能,,比如
Beetl是个功能强大模板引擎,是除了jsp以外,唯一同时兼顾了脚本和标签的模板语言,本文仅仅列出了Beetl创新部分,回击那些轮子党的轮子言论(尽管轮子党人数庞大,但他们只有一个言论,这很搞笑),让有志从事开源的开发者们借鉴我的开源思路。 同时本文也展示了模板引擎的生命力仍然可以持续和古老的模板引擎技术仍然发扬光大,顺应时代潮流和现代程序审美观。