多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 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