1.在自己的代码中创建包 com.jfinal.template.stat.ast;
2.创建类 For,具体代码如下:
package com.jfinal.template.stat.ast;
import com.jfinal.template.Env;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ForCtrl;
import com.jfinal.template.expr.ast.Logic;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Ctrl;
import com.jfinal.template.stat.Scope;
import java.util.Iterator;
public class For extends Stat {
private ForCtrl forCtrl;
private Stat stat;
private Stat _else;
public For(ForCtrl forCtrl, StatList statList, Stat _else) {
this.forCtrl = forCtrl;
this.stat = statList.getActualStat();
this._else = _else;
}
public void exec(Env env, Scope scope, Writer writer) {
scope = new Scope(scope);
// 将forCtrl往group中传递
scope.setLocal("forCtrl",this.forCtrl);
if (this.forCtrl.isIterator()) {
this.forIterator(env, scope, writer);
} else {
this.forLoop(env, scope, writer);
}
}
private void forIterator(Env env, Scope scope, Writer writer) {
Ctrl ctrl = scope.getCtrl();
Object outer = scope.get("for");
ctrl.setLocalAssignment();
ForIteratorStatus forIteratorStatus = new ForIteratorStatus(outer, this.forCtrl.getExpr().eval(scope), this.location);
ctrl.setWisdomAssignment();
scope.setLocal("for", forIteratorStatus);
Iterator<?> it = forIteratorStatus.getIterator();
String itemName = this.forCtrl.getId();
while(it.hasNext()) {
// 将it往group中传递
scope.setLocal("forIterator",it);
scope.setLocal(itemName, it.next());
this.stat.exec(env, scope, writer);
forIteratorStatus.nextState();
if (ctrl.isJump()) {
if (ctrl.isBreak()) {
ctrl.setJumpNone();
break;
}
if (!ctrl.isContinue()) {
return;
}
ctrl.setJumpNone();
}
}
if (this._else != null && forIteratorStatus.getIndex() == 0) {
this._else.exec(env, scope, writer);
}
}
private void forLoop(Env env, Scope scope, Writer writer) {
Ctrl ctrl = scope.getCtrl();
Object outer = scope.get("for");
ForLoopStatus forLoopStatus = new ForLoopStatus(outer);
scope.setLocal("for", forLoopStatus);
Expr init = this.forCtrl.getInit();
Expr cond = this.forCtrl.getCond();
Expr update = this.forCtrl.getUpdate();
ctrl.setLocalAssignment();
init.eval(scope);
for(; cond == null || Logic.isTrue(cond.eval(scope)); update.eval(scope)) {
ctrl.setWisdomAssignment();
this.stat.exec(env, scope, writer);
ctrl.setLocalAssignment();
forLoopStatus.nextState();
if (ctrl.isJump()) {
if (ctrl.isBreak()) {
ctrl.setJumpNone();
break;
}
if (!ctrl.isContinue()) {
ctrl.setWisdomAssignment();
return;
}
ctrl.setJumpNone();
}
}
ctrl.setWisdomAssignment();
if (this._else != null && forLoopStatus.getIndex() == 0) {
this._else.exec(env, scope, writer);
}
}
}3.编写分组标签GroupDirective代码:
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.expr.ast.ForCtrl;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Scope;
import com.jfinal.template.stat.ast.ForIteratorStatus;
import java.util.Iterator;
/**
* 分组标签
*/
public class GroupDirective extends Directive {
private Expr groupNumExpr;
public GroupDirective() {
}
@Override
public void exec(Env env, Scope scope, Writer writer) {
if (groupNumExpr == null) {
stat.exec(env, scope, writer);
} else {
Object groupNumObj = this.groupNumExpr.eval(scope);
if (!(groupNumObj instanceof Integer groupNum)) {
throw new TemplateException("group的第一个参数必须为int类型", this.location);
}
Object outer = scope.get("for");
if (outer instanceof ForIteratorStatus) {
forIterator(env, scope, writer, groupNum, 0);
} else {
forLoop(env, scope, writer, groupNum);
}
}
}
private void forIterator(Env env, Scope scope, Writer writer, Integer groupNum, Integer flag) {
this.stat.exec(env, scope, writer);
ForIteratorStatus outer = (ForIteratorStatus) scope.get("for");
if (flag < groupNum - 1) {
Iterator<?> it = (Iterator<?>) scope.get("forIterator");
if (it.hasNext()) {
ForCtrl forCtrl = (ForCtrl) scope.get("forCtrl");
scope.setLocal(forCtrl.getId(), it.next());
scope.set("forIterator", it);
scope.setLocal("for", outer);
flag++;
forIterator(env, scope, writer, groupNum, flag);
}
}
}
private void forLoop(Env env, Scope scope, Writer writer, Integer groupNum) {
this.stat.exec(env, scope, writer);
}
// ExprList 代表指令参数表达式列表
public void setExprList(ExprList exprList) {
int paraNum = exprList.length();
if (paraNum == 0) {
this.groupNumExpr = null;
} else {
this.groupNumExpr = exprList.getExpr(0);
}
}
public boolean hasEnd() {
return true;
}
}4.配置类中扩展#group指令
addDirective("group", GroupDirective.class);5.编写模版代码举例:
#set(test=[1,2,3,4,5,6,7,8,9]) #for(item : test) <div style="width:100%"> #group(4) <span style="padding-right:10px">#(item)</span> #end </div> #end
6.最终渲染结果如下:

这个需求如果没有扩展确实还不太好实现