### 高级功能
#### 配置GroupTemplate
Beetl建议通过配置文件配置GroupTemplate,主要考虑到IDE插件未来可能会支持Beetl模板,模板的属性,和函数等如果能通过配置文件获取,将有助于IDE插件识别。 配置GroupTemplate有俩种方法
- 配置文件: 默认配置在/org/beetl/core/beetl-default.properties 里,Beetl首先加载此配置文件,然后再加载classpath里的beetl.properties,并用后者覆盖前者。配置文件通过Configuration类加载,因此加载完成后,也可以通过此类API来修改配置信息
- 通过调用GroupTemplate提供的方法来注册函数,格式化函数,标签函数等
配置文件分为三部分,第一部分是基本配置,在第一节讲到过。第二部分是资源类配置,可以在指定资源加载类,以及资源加载器的属性(这个配置在spring框架里,通过spring或者springboot的配置机制实现覆盖,并未起作用),如下
```properties
RESOURCE_LOADER=org.beetl.core.resource.ClasspathResourceLoader
#资源配置,resource后的属性只限于特定ResourceLoader
#classpath 根路径
RESOURCE.root= /
#是否检测文件变化
RESOURCE.autoCheck= true
```
第1行指定了模板加载器类,在beetl与其他框架集成的时候,**模板加载器不一定根据这个配置**,比如spring,它的RESOURCE_LOADER以spring的配置为准
第4行指定了模板根目录的路径,此处/ 表示位于classpath 根路径下,同loader一样,依赖使用的框架
第6行是否自动检测模板变化,默认为true,开发环境下自动检测模板是否更改。关于如何自定义ResouceLoader,请参考下一章
配置文件第三部分是扩展部分,如方法,格式化函数等
```properties
##### 扩展 ##############
## 内置的方法
FN.date = org.beetl.ext.fn.DateFunction
FN.nvl = org.beetl.ext.fn.NVLFunction
.................
##内置的功能包
FNP.strutil = org.beetl.ext.fn.StringUtil
##内置的格式化函数
FT.dateFormat = org.beetl.ext.format.DateFormat
FT.numberFormat = org.beetl.ext.format.NumberFormat
.................
##内置的默认格式化函数
FTC.java.util.Date = org.beetl.ext.format.DateFormat
FTC.java.sql.Date = org.beetl.ext.format.DateFormat
## 标签类
TAG.include= org.beetl.ext.tag.IncludeTag
TAG.includeFileTemplate= org.beetl.ext.tag.IncludeTag
TAG.layout= org.beetl.ext.tag.LayoutTag
TAG.htmltag= org.beetl.ext.tag.HTMLTagSupportWrapper
```
FN前缀表示Function,FNP前缀表示FunctionPackage,FT表示format函数,FTC表示类的默认Format函数,TAG表示标签类。Beetl强烈建议通过配置文件加载扩展。以便随后IDE插件能识别这些注册函数
#### 自定义方法
##### 实现Function
```java
public class Print implements Function{
public String call(Object[] paras, Context ctx){
Object o = paras[0];
if (o != null){
try{
ctx.byteWriter.write(o.toString());
}catch (IOException e){
throw new RuntimeException(e);
}
}
return "";
}
}
```
call方法有俩个参数,第一个是数组,这是由模板传入的,对应着模板的参数,第二个是Context,包含了模板的上下文,主要提供了如下属性
- byteWriter 输出流
- template 模板本身
- gt GroupTemplate
- globalVar 该模板对应的全局变量
- byteOutputMode 模板的输出模式,是字节还是字符
- safeOutput 模板当前是否处于安全输出模式
- 其他属性建议不熟悉的开发人员不要乱动
> 1. call方法要求返回一个Object,如果无返回,返回null即可
> 2. 为了便于类型判断,call方法最好返回一个具体的类,如date函数返回的就是java.util.Date
> 3. call方法里的任何异常应该抛出成Runtime异常
##### 使用普通的java类
尽管实现Function对于模板引擎来说,是效率最高的方式,但考虑到很多系统只有util类,这些类里的方法仍然可以注册为模板函数。其规则很简单,就是该类的所有public方法。如果还需要Context 变量,则需要在方法最后一个参数加上Context即可,如
```java
public class util{
public String print(Object a, Context ctx){
//balabala...
}
}
```
注意
> 1. 从beetl效率角度来讲,采用普通类效率不如实现Function调用
> 2. 采用的普通java类尽量少同名方法。这样效率更低。beetl调用到第一个适合的同名方法。而不像java那样找到最匹配的
> 3. 方法名支持可变数组作为参数
> 4. 方法名最后一个参数如果是Context,则beetl会传入这个参数。
##### 使用模板文件作为方法
可以不用写java代码,模板文件也能作为一个方法。默认情况下,需要将模板文件放到Root的functions目录下,且扩展名为.html(可以配置文件属性来修改这俩个默认值) 方法参数分别是para0,para1…..
如下root/functions/page.fn
```javascript
//para0,para1 由函数调用传入
var current = para0,total = para1,style=para2!'simple'
%>
当前页面 ${current},总共${total}
```
则在模板中
```javascript
page(current,total);
%>
```
允许使用return 表达式返回一个变量给调用者,如模板文件functions\now.html
```javascript
return date();
%>
```
在任何模板里都可以调用:
```javascript
hello time is ${now(),'yyyy-MM-dd'}
```
也可以在functions建立子目录,这样function则具有namespace,其值就是文件夹名
#### 自定义格式化函数
需要实现Format接口
```java
public class DateFormat implements Format{
public Object for