## 2.15 定制模板引擎
Beetl在线体验([http://ibeetl.com/beetlonline/](http://ibeetl.com/beetlonline/))面临一个挑战,允许用户输入任何脚本做练习或者分享代码。但又需要防止用户输入恶意的代码,如
```javascript
<%
while(true){
//其他代码
}
%>
```
此时,需要定制模板引擎,遇到while循环的时候,应该限制循环次数,譬如,在线体验限制最多循环5次,这是通过定义扩展模板引擎来实现的,以jar包自带的实例代码OnlineTemplateEngine来说明
```java
public class OnlineTemplateEngine extends DefaultTemplateEngine {
public static int MAX = 5;
public static String ERROR = "错误:在线引擎不允许循环次数超过 " + MAX;
@Override
protected GrammarCreator getGrammerCreator(GroupTemplate gt) {
GrammarCreator grammar = new OnlineGrammarCreator();
return grammar;
}
}
```
扩展DefaultTemplateEngine,重载getGrammerCreator方法,返回一个我们自己的语法定义类OnlineGrammarCreator
OnlineGrammarCreator继承了默认的
```java
static class OnlineGrammarCreator extends GrammarCreator {
@Override
public WhileStatement createWhile(Expression exp, Statement whileBody, GrammarToken token) {
WhileStatement whileStat = new RestrictWhileStatement(exp, whileBody, token);
return whileStat;
}
}
```
需要对for循环重新定义,使用新的 RestrictWhileStatement,定义如下
~~~java
static class RestrictWhileStatement extends WhileStatement {
public RestrictWhileStatement(Expression exp, Statement whileBody, GrammarToken token) {
super(exp, whileBody, token);
}
@Override
public void execute(Context ctx) {
int i = 0;
while (i < OnlineTemplateEngine.MAX) {
Object result = exp.evaluate(ctx);
if (result instanceof Boolean) {
if ((Boolean) result) {
whileBody.execute(ctx);
} else {
break;
}
} else {
BeetlException be = new BeetlException(BeetlException.BOOLEAN_EXPECTED_ERROR);
be.token = exp.token;
throw be;
}
i++;
}
if (i >= OnlineTemplateEngine.MAX) {
try {
ctx.byteWriter.writeString(ERROR);
} catch (IOException e) {
// ignore
}
}
}
}
~~~
完成这些代码后,在配置文件中申明使用新的引擎
```properties
ENGINE=org.beetl.core.engine.OnlineTemplateEngine
```
这样就完成了模板引擎定制。
> BeetlSQL 正是支持定制,所以才把## 占位符输出"?",而不是字面值,${} 负责输出字面值,可以查看BeetlSQL的org.beetl.sql.core.engine.SQLTemplateEngine
- Beetl 3 中文文档
- 第一部分 基础用法
- 1.1 安装
- 1.2 快速开始
- 1.3 模板基础配置
- 1.4 模板加载器
- 1.5 定界符与占位符
- 1.6 注释
- 1.7 变量定义
- 1.8 属性
- 1.9 数学表达式
- 1.10 循环语句
- 1.11 条件语句
- 1.12 异常捕获
- 1.13 虚拟属性
- 1.14 函数调用
- 1.15 安全输出(重要)
- 1.16 输出格式化
- 1.17 标签
- 1.18 调用Java方法与属性
- 1.19 严格MVC控制
- 1.20 指令
- 1.21 错误处理
- 1.22 Beetl小工具
- 1.23 Escape
- 第二部分 高级用法
- 2.1 配置GroupTemplate
- 2.2 自定义方法
- 2.3 自定义格式化函数
- 2.4 自定义标签
- 2.5 自定义虚拟属性
- 2.6 使用额外的资源加载器
- 2.7 自定义资源加载器
- 2.8 使用CompositeResourceLoader
- 2.9 自定义错误处理器
- 2.10 自定义安全管理器
- 2.11 注册全局共享变量
- 2.12 自定义布局
- 2.13 性能优化
- 2.14 定制输出
- 2.15 定制模板引擎
- 2.16 直接运行Beetl脚本
- 2.17 模板校验
- 第三部分 Web 集成
- 3.1 Web提供的全局变量
- 3.2 集成技术开发指南
- 3.3 Servlet集成
- 3.4 SpringMVC集成
- 3.5 Spring Boot集成
- 3.6 Jodd集成
- 3.7 JFinal4 集成方案
- 3.8 Nutz集成
- 3.9 Struts2集成
- 3.10 整合ajax的局部渲染技术
- 3.11 在页面输出错误提示信息
- 附录
- 4.1 内置方法
- 4.2 Spring相关函数
- 4.3 Spring security
- 4.4 shiro
- 4.5 内置格式化方法
- 4.6 内置标签函数
- 4.7 内置html标签
- 4.8 性能优化
- 4.9 Eclipse 插件
- 4.10 性能测试对比