Beetl学习笔记
Beetl
一、什么是Beetl
1.1 概念
Beetl是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,它功能强大,性能良好,超过当前流行的模板引擎。而且还易学易用。
1.2 优缺点
1.2.1 优点:
易整合、性能强
1.2.2 缺点:
文档蛋疼、用例少、与html标签结合略显混乱
二、Beetl语法
三、第一个例子:与SpringBoot集成
3.1 创建Spring boot项目(1.5.3.RELEASE)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/>
</parent>
3.2 添加启动器依赖
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl-framework-starter</artifactId>
<version>1.1.60.RELEASE</version>
</dependency>
3.3 关于启动器的说明
starter 自动处理以btl结尾的视图,模板根目录是Spring Boot默认的templates目录。
3.4 使用默认配置
- 创建HelloController(return "/hello.btl";)
- 在templates下创建 hello.btl
3.5 启动运行效果
Hello,This is a BTL file, The time is 2018-09-05 10:09:12
四、探究Beetl模板资源加载器
4.1 字符串模板加载器
在创建GroupTemplate过程中,如果传入的是StringTemplateResourceLoader,则允许通过调用gt.getTemplate(String template)来获取模板实例对象
4.2 文件资源模板加载器
更通常情况下,模板资源是以文件形式管理的,集中放在某一个文件目录下(如webapp的模板根目录就可能是WEB-INF/template里),因此,可以使用FileResourceLoader来加载模板实例,如下代码:
String root = System.getProperty("user.dir")+File.separator+"template";
FileResourceLoader resourceLoader = new FileResourceLoader(root,"utf-8");
Configuration cfg = Configuration.defaultConfiguration();
GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
Template t = gt.getTemplate("/s01/hello.txt");
String str = t.render();
System.out.println(str);
4.3 Classpath资源模板加载器
还有种常情况下,模板资源是打包到jar文件或者同Class放在一起,因此,可以使用ClasspathResourceLoader来加载模板实例
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("org/beetl/sample/s01/");
Configuration cfg = Configuration.defaultConfiguration();
GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
Template t = gt.getTemplate("/hello.txt");
String str = t.render();
System.out.println(str);
第1行代码指定了模板根目录,即搜索模板的时候从根目录开始,如果new ClasspathResourceLoader("template/"),则表示搜索template下的模板。此处用空构造函数,表示搜索路径是根路径,且字符集默认字符集UTF-8.
4.4 WebApp资源模板加载器
WebAppResourceLoader 是用于web应用的资源模板加载器,默认根路径是WebRoot目录。也可以通过制定root属性来设置相对于WebRoot的的模板根路径,从安全角考虑,建议放到WEB-INF目录下
4.5 自定义资源模板加载器
有时候模板可能来自文件系统不同目录,或者模板一部分来自某个文件系统,另外一部分来自数据库,还有的情况模板可能是加密混淆的模板,此时需要自定义资源加载,继承ResouceLoader才能实现模板功能
五、Beetl的高级用法
5.1 模板配置文件
常用的配置其实就只有几个,其他的几乎不用改动
#取值开始符号
DELIMITER_PLACEHOLDER_START=${
#取值结束符号
DELIMITER_PLACEHOLDER_END=}
#beetl代码开始符号
DELIMITER_STATEMENT_START=<%
#beetl代码结束符号
DELIMITER_STATEMENT_END=%>
5.2 自定义视图名与模板位置
在application.properties中配置模版路径,beetl解析的视图名以及spring mvc的视图后缀,不建议使用Spring mvc视图前缀,直接通过模板名称与spring mvc视图后缀组合定位具体模板
#配置模板的位置为templates下的views文件夹
beetl.templatesPath=templates/views
#配置beetl的默认解析的视图名为html
beetl.suffix=html
#配置spring mvc的后缀为.html
spring.mvc.view.suffix=.html
通过以上配置,在HelloController中 return "hello"; 则表示为渲染的视图文件为 classpath:templates/views/hello.html
5.3 启动器定制GroupTemplate
新建一个java类,并将BeetlTemplateCustomize注解,注意:不要将类名称命名为BeetlConfig 别问我怎么知道的。
@Configuration
public class MyConfig{
@Bean
//配置自定义GroupTemplate
public BeetlTemplateCustomize beetlTemplateCustomize(){
return new BeetlTemplateCustomize(){
public void customize(GroupTemplate groupTemplate){
/*开始你的表演*/
}
};
}
}
5.4 注册全局共享变量
全局共享变量可以在任何一个模板的任何一个位置使用,比如可以将后台或前台路径的path注册为全局共享变量
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", "GouDan Li");
groupTemplate.setSharedVars(map);
5.5 配置BeetlGroupUtilConfiguration和BeetlSpringViewResolver
使用Starter来配置已经够用,如果你想自己配置模板引擎, 通过java config来配置beetl需要的BeetlGroupUtilConfiguration,和 BeetlSpringViewResolver,参考代码如下
@Configuration
public class BeetlConf {
//模板根目录 ,比如 "templates"
@Value("${beetl.templatesPath}") String templatesPath;
@Bean(name = "beetlConfig")
public BeetlGroupUtilConfiguration getBeetlGroupUtilConfiguration() {
BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();
//获取Spring Boot 的ClassLoader
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if(loader==null){
loader = BeetlConf.class.getClassLoader();
}
//额外的配置,可以覆盖默认配置,一般不需要
beetlGroupUtilConfiguration.setConfigProperties(extProperties);
ClasspathResourceLoader cploder = new ClasspathResourceLoader(loader,templatesPath);
beetlGroupUtilConfiguration.setResourceLoader(cploder);
beetlGroupUtilConfiguration.init();
//如果使用了优化编译器,涉及到字节码操作,需要添加ClassLoader
beetlGroupUtilConfiguration.getGroupTemplate().setClassLoader(loader);
return beetlGroupUtilConfiguration;
}
@Bean(name = "beetlViewResolver")
public BeetlSpringViewResolver getBeetlSpringViewResolver(@Qualifier("beetlConfig") BeetlGroupUtilConfiguration beetlGroupUtilConfiguration) {
BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver();
beetlSpringViewResolver.setContentType("text/html;charset=UTF-8");
beetlSpringViewResolver.setOrder(0);
beetlSpringViewResolver.setConfig(beetlGroupUtilConfiguration);
return beetlSpringViewResolver;
}
}
5.6 自定义方法
新建类实现Fucntion接口,覆盖call方法,由于call方法返回的类型为Object,所以可以实现任何返回值的方法。
public class MyMethod implements Function{
@Override
public Object call(Object[] paras, Context ctx) {
//此处仅演示输出固定的String
return "Called My Method";
}
}
将该方法注册的方式分为两种,一种是在beetl.properties中通过FN(Function) 配置
#配置自定义函数,myFn为你注册的方法名,后面是它所在的Class位置
FN.myFn = com.xyx.demo.fn.MyFn
另外一种是在自定义GroupTemplate 时将该方法注册
groupTemplate.registerFunction("myFn", new MyFn());
在页面中直接使用“你注册的方法名”调用
${myFn()}
5.7 导入静态工具类
普通的java类中的方法亦可以被模板调用,该方法需声明为 public static,页面中调用需要把包名写上: ${@com.xyx.demo.utils.MyUtils.myUtilMethod()}
不想写包名?可以在beetl.properties中通过IMPORT_PACKAGE 配置,可以导入多个包
#导入自定义静态方法类
IMPORT_PACKAGE= com.xyx.demo.utils.;\
com.xyx.demo.anotherutils.;
页面中调用,直接 类名.方法名
${@MyUtils.myUtilMethod()}
${@MyAnotherUtils.myAnotherUtilMethod()}
5.8 注册方法包
有时候,我们想把某个工具类中的所有方法在页面中直接调用,也是可以的,首先需要创建一个普通的java类,里面定义好所有的方法。
public class MyFnPac {
public String MyFnPacTest() {
return "Called MyFuntionPackageTest Method";
}
public String MyFnPacTest2() {
return "Called MyFuntionPackageTest2 Method";
}
}
注册方式同样有两种,第一种是在beetl.properties中通过FNP(Function Package)配置
#自定义的功能包
FNP.myFnPac = com.xyx.demo.fnpackage.MyFnPac
第二种是将该类在GroupTemplate中注册
//注册方法包
groupTemplate.registerFunctionPackage("myFnPac", new MyFnPac());
页面中调用采用“注册的包名”.“方法名”
//调用方式采用“注册的包名”.“方法名”
${myFnPac.MyFnPacTest()}
${myFnPac.MyFnPacTest2()}
5.9 模板文件作为方法
一个html文件,也可以作为方法,比如在分页时很有用。
默认情况下,需要将模板文件放到Root的functions目录下,且扩展名为.html(可以配置文件属性来修改这俩个默认值) 方法参数分别是para0,para1…..
新建一个functions目录下的模板文件page.html
<%
//para0,para1 由函数调用传入
var current = para0,total = para1;
%>
当前页面 ${current},总共${total}
模板中调用
<%
page(1,10);
%>
允许使用return 表达式返回一个变量给调用者,如now.html,方法名为now
<%
return date();
%>
5.10 自定义格式化函数
新建类实现Format接口,覆盖format方法,由于format方法返回的类型为Object,所以可以实现任何返回值的方法。
public class MyFormat implements Format{
@Override
public Object format(Object data, String pattern) {
/*安排的妥妥的*/
return data;
}
}
5.11 自定义标签
标签形式有俩种,一种是标签函数,第二种是html tag。第二种实际上在语法解析的时候会转化成第一种,其实现是HTMLTagSupportWrapper,此类将会寻找root/htmltag目录下同名的标签文件作为模板来执行。
自定义标签的位置默认在root下的htmltag文件夹内,并以.tag为结尾,可修改。
定义: 在htmltag目录下创建mytag.tag文件
使用: 模板中<#mytag />
5.12 布局示例
在root下创建include文件夹,创建需要引入的页面
在root下创建layout文件夹,创建需要引入的页面
//引入头部页面
<% include('/include/header.html'){} %>
//引入左侧页面
<% include('/include/left.html'){} %>
//引入主页面(layoutContent 是默认变量)
<div class = "content">${layoutContent}</div>
//引入脚部页面
<% include('/include/footer.html'){} %>
在主页面使用layout方法采用此布局
<% layout("/layout/layout.html"){ %>
//开始你的表演
<% } %>