3.2. 自定义方法

3.2.1. 实现Function
  1. public class Print implements Function{
  2. public String call(Object[] paras, Context ctx){
  3. Object o = paras[0];
  4. if (o != null){
  5. try{
  6. ctx.byteWriter.write(o.toString());
  7. }catch (IOException e){
  8. throw new RuntimeException(e);
  9. }
  10. }
  11. return "";
  12. }
  13. }

call方法有俩个参数,第一个是数组,这是由模板传入的,对应着模板的参数,第二个是Context,包含了模板的上下文,主要提供了如下属性

  • byteWriter 输出流
  • template 模板本身
  • gt GroupTemplate
  • globalVar 该模板对应的全局变量
  • byteOutputMode 模板的输出模式,是字节还是字符
  • safeOutput 模板当前是否处于安全输出模式
  • 其他属性建议不熟悉的开发人员不要乱动
  1. call方法要求返回一个Object,如果无返回,返回null即可
  2. 为了便于类型判断,call方法最好返回一个具体的类,如date函数返回的就是java.util.Date
  3. call方法里的任何异常应该抛出成Runtime异常
3.2.2. 使用普通的java类

尽管实现Function对于模板引擎来说,是效率最高的方式,但考虑到很多系统只有util类,这些类里的方法仍然可以注册为模板函数。其规则很简单,就是该类的所有public方法。如果还需要Context 变量,则需要在方法最后一个参数加上Context即可,如

  1. public class util{
  2. public String print(Object a, Context ctx){
  3. //balabala...
  4. }
  5. }

注意

  1. 从beetl效率角度来讲,采用普通类效率不如实现Function调用
  2. 采用的普通java类尽量少同名方法。这样效率更低。beetl调用到第一个适合的同名方法。而不像java那样找到最匹配的
  3. 方法名支持可变数组作为参数
  4. 方法名最后一个参数如果是Context,则beetl会传入这个参数。
3.2.3. 使用模板文件作为方法

可以不用写java代码,模板文件也能作为一个方法。默认情况下,需要将模板文件放到Root的functions目录下,且扩展名为.html(可以配置文件属性来修改这俩个默认值) 方法参数分别是para0,para1…..

如下root/functions/page.fn

  1. <%
  2. //para0,para1 由函数调用传入
  3. var current = para0,total = para1,style=para2!'simple'
  4. %>
  5. 当前页面 ${current},总共${total}

则在模板中

  1. <%
  2. page(current,total);
  3. %>

允许使用return 表达式返回一个变量给调用者,如模板文件functions\now.html

  1. <%
  2. return date();
  3. %>

在任何模板里都可以调用:

  1. hello time is ${now(),'yyyy-MM-dd'}

也可以在functions建立子目录,这样function则具有namespace,其值就是文件夹名