Beetl 0.6beta 发布,欢迎使用

Beetl模板语言使用指南

什么是Beetl

BeetlBee Template languageBee译为忙碌的人,意指忙碌中国的开发人员。目前版本0.6beta,大小约320K

Beetl是国人提供的一款开源免费得模板语言,作者有10余年Java开发经验,曾在国内外著名大公司工作过,根据自己实际使用模板语言的心得体会而编写的一款模板语言,它具有如下特性:

1 非常简单:它的语法是javascript一个子集,只有少量的大家熟悉的符号。任何了解java,或者javascript的人,都能快速学会。如果从未用过任何模板语言,用Beetl是非常很合适的

2 同时支持较为松散的MVC和严格的MVC,如果在模板语言里嵌入计算表达式,复杂条件表达式,以及函数调用有干涉业务逻辑嫌疑,你可以禁止使用这些语法。关于这一点,可以参考strictly enforces model-view separation

3 提供一系列其他模板语言没有提供的功能,如自定义占位符号,控制语句符号,虚拟属性,自定义函数,文本处理函数等,它们并不复杂,但有可能解决你在使用别的模板语言时候遇到的一些不便捷的问题

下载

 

 

Beetl能为你做些什么

作为模板语言,你可以用于任何适合在MVC的地方。如代码生成,或者web界面

因为Beetl是基于antlr实现语法解析的,因此如果你仅仅对antlr感兴趣,beetl仍然可以作为你的一个重要参考

关于Beetl性能:

目前实现了runtime版本,适合代码生成。暂时不适合作为web界面。它本生的是以易读的方式实现,并未经过优化。然而,即将推出预编译版本,可以保证有很好的性能

Beetl目前渲染一个7K文件,内含少量控制语句和占位符,所需要时间是1毫秒,这是在我一个四年前的老机器上跑得,作为代码生成,你完全无需担心性能。

 

beetl(runtime,0.52)

Beetl(runtime,0.6)

Freemarker(2.3.1.8)

Beetl(compiled)

Velocity

7K1000次)

4000毫秒

950毫秒

900毫秒

 估计约400毫秒

 

 

展望Beetl预编译实现出来后,性能将至少提高2-3倍以上,因此未来能超越Freemaker

 

关于功能:

http://freemarker.sourceforge.net/fmVsVel.html  是一篇freemakervelocity功能比较的文章,很幸运Beetl能以简单易学,更易扩展的方式支持所有功能

下表是以此文章为基础做的比较

功能点

Beetl

Freemarker

velocity

Number and date support

yes

yes

no

Internationalization:

Yes,但不支持中文变量名

yes

no

Loop handling:

Yesbetter

yes

no

Array handling on the template language level

yes

yes

no

Macros

Yes

Yes

no

Name-spaces:

No

yes

no

Java-independent string, list, and map manipulations with built-in functions/operators:

yes

yes

no

Expose typos and other mistakes in template

Yesbetter

yes

no

Advanced rendering control:

yes

yes

no

Literals:

yes

yes

no

Advanced white-space removal

No ,不明白为啥有此需求

yes

no

Integration with other technologies:

yes

yes

yes

Powerful XML transformation capabilities:

no

yes

no

Advanced template metaprogramming:

No,不明白为啥有此需求

yes

no

function

No,觉得模板不需要

yes

No

自定义控制语句

yes

no

no

自定义占位符号

yes

no

no

严格MVC控制

yes

no

no

虚拟属性

yes

no

no

文本处理函数

yes

no

no

自定以错误处理Hanlder

yes

no

no

 

基本用法

 

Hello Beetl

package org.bee.tl.samples;

import java.io.IOException;

import org.bee.tl.core.BeeTemplate;

public class HelloBeetl {

 

   public static void main(String[] args)throws IOException {

      Template template =new BeeTemplate("Hello,$name$");// 1

      template.set("name","Beetl");//2

      String result = template.getTextAsString();//3

      System.out.println(result);

   }

}

 

1用于BeeTemplate创建一个模板,此时使用的是一个字符串输入,输入也可以是java.io.File或者java.io.reader.对于beetl来说,如果输入是文件,那将会缓存中间的解析结果而大幅度提升性能

2定义变量,set方法允许字符串,对象作为参数,如果需要引用对象的属性,则用小数点,如$user.name$,如果属性是个List集合,可以用[索引],$user.friends[0]$,如果属性是Map集合,

 使用[key],key为任何对象,如$books[thinking in java].author$

3调用template.getTextAsString() 或者template.getText(OutputStream os)都可以获得模板渲染的结果

 

控制语句和占位符号

Beetl默认情况下,采用#:作为控制语句开始,回车作为控制语句结束

#:for(user in userList){

hello,$user.name$

#:}

默认情况下,占位符号使用$作为开始和结尾占位符号

$users[index]$

然而,Beetl支持自定义控制语句和占位符号,以适应不同类型模板文件

public static void main(String[] args) {

  String input = ”…..

      BeeTemplate template =new BeeTemplate(input);

      template.setStatementStart("<%");

      template.setStatementEnd("%>");

      template.setPlaceholderStart("~");

      template.setPlaceholderStart("~");

      template.getTextAsString();

}

 

此代码可以解析如下模板文件

 

<% var temp=lijz; %>

Hello ~temp~ !

 

建议:控制语句和占位符号最好不要影响原有文件,可以使用<!--:  -->作为XML模板文件控制语句,使用#:作为通常shell脚本,配置文件的控制语句

 

API接口

 Beetl 主要的接口Template 和 类 GroupTemplate.

 Template 实现类分为BeeTemplate CompiledBeeTemplate,前者用于解释执行模板,适合代码生成或者开发阶段使用,后者是预编译成class,适合web框架或者生产模式使用。

 

org.bee.tl.core.Template 常用API

public void set(String name, Object o)

 设置模板变量

public void getText(OutputStream os)

 渲染模板到os

public void getText(Writer w)

渲染模板到wirter

public String getTextAsString()

 渲染模板,结果作为String返回

public void makeStrict(boolean isTrict)

 是否使用严格MVC

org.bee.tl.core.Template 高级API (同org.bee.tl.core..GroupTemlate

public void setPlaceholderStart(String placeholderStart)

 设置占位符好开始标记,默认是$

public void setPlaceholderEnd(String placeholderEnd)

 设置占位符好结束标记,默认是$

public void setStatementStart(String statementStart)

设置控制语句开始标记,默认是#:

public void setStatementEnd(String statementEnd) ;

设置控制语句结束标记,默认是null,也就是文件回车换行符号

public void registerFunction(String name,Function fn);               

Beetl注册一个自定义函数,参考高级用法

public void registerFormat(String name,Format format);               

Beetl创建一个格式化函数,参考高级用法

public void registerTextProcess(String name,TextPorcessFunction process);

Beetl创建一个文本处理函数,参考高级用法

public void registerVirtualAttributeEval(VirtualAttributeEval e);

为某对象设置一个虚拟属性,参考高级用法

 

 Beetl 不推荐直接调用高级API,在一个真正的系统里,首先通过GroupTemlate设置好模板所有属性,然后调用 GroupTemlate.getTetmplate来获取Template,如下代码

package org.bee.tl.samples;

import org.bee.tl.core.GroupTemplate;

public class GroupTemplateUtil {

                static GroupTemplate group = new GroupTemplate();

                static {|

                                                group.setPlaceholderStart("$");

                                                group.setPlaceholderEnd("$");

                                                group.setStatementStart("#:");

                                                group.setStatementEnd(null);

                                                group.makeStrict(true);

                }

public static GroupTemplate getGroup (){

                return group;

}

               

 

org.bee.tl.core.GroupTemplate 常用API

public GroupTemplate()

 构造一个GroupTemplate

public GroupTemplate(File root)

 构造一个GroupTemplate,且制定模板文件跟目录,此目录下的模板文件都将编译成class,(前提是isProduct = true

public Template getStringTemplate(String input)

 得到一个BeeTemplate

public Template getReaderTemplate(Reader  reader)

 得到一个BeeTemplate,输入是Reader

public Template getFileTemplate(String child)

 如果isProudct=true,得到一个CompiledBeeTemplate模板,否则得到一个BeeTemplate

public void setProduct(boolean isProduct)

指示Beetl运行在开发模式还是生产模式

 

注意:要真正获得预编译支持以用于Web或者高性能项目, 只有通过GroupTemplate(File root) 构造的GroupTemplate ,且sProudct=true

然而,目前暂时不支持预编译版本

 

定义变量

Beetl允许定义变量,准确的说,允许定义临时变量,如下所示

#:var name=lijz,loopCount=100+other ,girlName;

关键字var是必须得,这点不同于javascript

Beelt中得变量同javascript一样,有自己的作用域,如下模板输出为”lucy

#:var name=lijz,i=1;

#:if(i>=1){

 #:var name=lucy;

 Hello,$name$

#:}

 

变量命名规则同javascript或者java,但不允许以俩个下划线开头"__",这是因为以此开头的多为Beetl内部的一些临时变量

算术表达式

Beetl支持类似javascript的算术表达式和条件表达式,如+ - * / % 以及(),如下例子

#:var a=1,b=2,c=3;

the result is $(a+b)*c-0.75$

逻辑表达式

Beetl支持类似Javascript,java的条件表达式 如><== !=>= , <= 以及 !,如下例子

#:var a=1,b=2,c=3;if((b-c)>=1){

Hello big!

#:}else{

:( ,small!

#:}

循环语句

Beetl 支持for in 循环格式,以及breakcontinuereturn (实际上可以出现在任何地方),如下例子

//java代码

tempalte.set("userList",userList);

//模板

总共 $userList.~size$

#:for(user in userList){

$user.~index$ . Welcome $user.name$!

#:}

 

如果循环中,需要引用当前索引和总数,可以分别使用虚拟属性index,size

条件语句

Beetl只支持同javascriptjava一样的if 语句,不支持switch. 如下例子

#:var isGirl = true;

#:if(isGir){

姑娘,你好

#:}else{

小伙子,你好

#:}

 

函数调用

Beetl内置了少量实用函数,可以在Beetl任何地方调用,一般情况是在占位符里调用。

如下例子是调用NVL函数,判断如果变量为不为null,则输出变量,如果为null,则输出默认值

//java代码

template.set("name",service.getName(id));

//模板

The name is $nvl(name,"defaultValue")$

 

如下例子casef,判断变量与哪个值匹配,便显示响应的值

//java代码

template.set("score",3);

//模板

The name is $casef(score,3,"Good",2 ,"so-so",1 ,"bad","error score")$

 

Beetl允许用户自定义函数以适合特定领域使用,请参考高级用法。也欢迎有人把他认为能公用的函数发给我,我将作为核心函数放入beetl

 

格式化

几乎所有的模板语言都支持格式化,Beetl也不列外,如下例子Beetl提供的内置日期格式

#:var date = now();

Today is $date,df="yyyy-MM-dd"$.

Today is $date,df$

如果没有为格式化函数输入参数,则使用默认值,df格式化函数默认值是local

Beetl允许用户自定义格式化函数以适合特定领域,请参考高级用户,也欢迎有人把他认为能公用的格式化函数发给我,我将作为核心函数放入beetl

 

错误处理

Beetl默认情况使用 org.bee.tl.core.DefaultErrorHandler  来处理语法解析错误和运行时刻的错误,默认情况下,会显示行号,错误原因,以及错误的关键字

如下所示

BeeTemplate t = new BeeTemplate("#:if(!isGirl){var c=1;}");
t.makeStrict(true);
t.set("isGirl", false);
t.getTextAsString() ;

会导致如下编译错误


STRICK_MVC 位于1行,符号 var
1|#:if(!isGirl){var c=1;}

 

 

其他琐碎功能

对齐: 我发现别的模板语言要是做到对齐,非常困难,Beetl你完全不用担心,比如veloctystringtemlatefreemarker例子都出现了不对齐的情况,影响了美观,Beetl完全无需担心输出对齐

包含其他模板文件:在Beetl中,这不是一个特殊的功能,通过调用函数includeFT,或者includeST都可以实现,前者是包含一个文件模板,后者是将一个string模板作为输入。详细使用请参考高级用法

Escape:可以使用/ escape符号,如hello,it's $money$/$, 或者Hello,it's $money+"/$"$

空值策略: 在输出一个变量的时候,如果为null,是应该抛出异常还是仅仅忽略,打印出默认值,Beetl相对于其他模板语言来说,控制的更为精细,如下代码

#:var NULL='N/A';var NULL_POLICY=1;

$u.name$

第一行指示空值情况下仅仅输出默认值,此时NULL_POLICY=1 表示不抛出异常,而仅仅输出默认值,0为默认情况,即抛出异常,停止渲染

你可以在Beetl中任何一处重新设置这些值以满足特定的需求。

文本处理函数:文本处理函数允许你将模板文件中的一段文件内容作为输入,经过函数操作,变成特定的输出,如下内置的replaceProperties

#:replacePropertiesip,port{

Server_ip= 127.0.0.1

Server_port= 8080

#:}

#:if(isProduct) { delNext(){

Debug_para1=.....

Debug_para2=......

#:}

如果在java代码中,tempalte.set("ip",targetIP),template.set("port",targetPort);

则模板文件里等于号后的字符串将被以此替换.

如果在java代码中,template.set("isProduct",true),则所有debug参数都将被删除。关于文本处理函数概念,请参考高级用法

 

 

 

高级用法

自定义函数

 Beetl允许提供自定义函数以适合特定业务需求,自定义函数需要实现org.bee.tl.core.Function。如下定义了一个now函数仅仅返回一个java.util.Date实例

public class DateFunction implements Function {

      public Object call(Object... paras) {

            return new Date();

      }    

      public  static void main(String[] args) throws IOException{

            GroupTemplate group = new GroupTemplate();

            group.registerFunction("now", new DateFunction());

            Template t = group.getStringTemplate("today is $now()$");

            System.out.println(t.getTextAsString());

      }

 

}

 

格式化函数

 Beetl允许提供自定义格式化函数,用于格式化输出。 格式化函数需要实现org.bee.tl.core.Format

public class DateFormat extends Format  {

      public Object format(Object data,String pattern){

            SimpleDateFormat sdf = null;

            if(pattern==null){

                 

                  sdf = new SimpleDateFormat();

            }else{

                  sdf = new SimpleDateFormat(pattern);

            }

           

            return sdf.format(data);

      }

      public static void main(String[] args)throws IOException {

            GroupTemplate group = new GroupTemplate();

            group.registerFunction("now", new DateFunction());

            group.registerFormat("df", new DateFormat());

            Template t = group.getStringTemplate("today is $now(),df=’yyyy-MM-dd’$");    

            System.out.println(t.getTextAsString());

      }

}

 

 

严格MVC控制

 如果设置了严格MVC,则以下语法将不在模板文件里允许,否则将报出STRICK_MVC 错误

l  定义变量,为变量赋值

l  算术表达式

l  除了只允许布尔以外,不允许逻辑表达式

l  方法调用

 

虚拟属性

无需为java对象定义额外的属性用于辅助显示,虚拟属性可以轻易做到,如Beetljava.util.Collection 定义的一个虚拟属性size,用于表示集合大小

group.registerVirtualAttributeEval(new VirtualAttributeEval(){

      public Object eval(Object o,String attributeName,Context ctx){

            if(attributeName.equals("size")){

                  return ((Collection)o).size();

            }else{

                  throw new IllegalArgumentException();

            }

                       

      }

      public boolean isSuppoert(Class c,String attributeName){

                         if(Collection.class.isAssignableFrom(c)&&attributeName.equals("size")){

                  return true;

           }else{

                  return false;

            }

      }

});

这样,所以Collection子类都有虚拟属性size$userList.~size$ 输出userList集合长度

实现虚拟属性,必须实现接口俩个方法,一个是isSupport,这让Beetl用于找到VirtualAttributeEvaleval方法用于计算虚拟属性

文本处理函数

所谓文本处理函数,即允许处理模板文件里的一块内容。如下{}的内容在beetl运行的时候将会被删除

#:del(){

This content will be deleted

#:}

 

自定义文本处理函数必须实现org.bee.tl.core.TextPorcessFunction,需要实现requriedInput,用于告诉Beetl,是否需要先渲染文本体。

getOutput 用于返回文本处理函数的结果

如下是Beetl提供的内置的del文本处理函数实现

public class DeleteFunction extends TextPorcessFunction{

      public String getOutput(){

            return "";

      }    

      @Override

      public  boolean requriedInput(){

            return false;

      }

 

 

}

 

可以通过父类属性args,获取输入参数,详细可以参考API

自定义错误处理

 

<!--EndFragment-->

你可能感兴趣的:(freemarker,velocity,模板,antlr)