1. 模板文件 test05.ftl
<#assign x = 1>
<@repeat count=4>
Test ${x}
<#assign x++>
</@repeat>
<@repeat count=3 hr=true>
Test
</@repeat>
<@repeat count=3; loopv>
${loopv}. Test
</@repeat>
2. 自定义指令类(带参数)RepeatDirective.java
package com.freemarker.test05.Directives2;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.Map;
import freemarker.core.Environment;
import freemarker.template.SimpleNumber;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
/**
* FreeMarker 用户自定义指令来重复模板中的一部分,可选的是使用 <tt><hr></tt>来分隔输出内容中的重复部分。
* <p><b>指令内容</b></p>
* <p> 参数:
* <ul>
* <li><code>count</code>: 重复的次数。必须!
* 必须是一个非负的数字,如果它不是一个整数,那么小数部分就会被。
* <em>舍去</em>.
* <li><code>hr</code>: 用来辨别 HTML 的 "hr"元素是否在重复内容之
* 间被打印出来。布尔值。 可选, 默认是<code>false</code>。
* </ul>
* <p> 循环变量: 1, 可选的。它给定了当前重复内容的数量,从 1 开始。
* <p> 嵌套内容: 是
*/
public class RepeatDirective implements TemplateDirectiveModel {
private static final String PARAM_NAME_COUNT = "count";
private static final String PARAM_NAME_HR = "hr";
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
int countParam = 0;
boolean countParamSet = false;
boolean hrParam = false;
Iterator paramIter = params.entrySet().iterator();
while (paramIter.hasNext()) {
Map.Entry ent = (Map.Entry) paramIter.next();
String paramName = (String) ent.getKey();
TemplateModel paramValue = (TemplateModel) ent.getValue();
if (paramName.equals(PARAM_NAME_COUNT)) {
if (!(paramValue instanceof TemplateNumberModel)) {
throw new TemplateModelException("The \"" + PARAM_NAME_HR
+ "\" parameter " + "must be a number.");
}
countParam = ((TemplateNumberModel) paramValue).getAsNumber()
.intValue();
countParamSet = true;
if (countParam < 0) {
throw new TemplateModelException("The \"" + PARAM_NAME_HR
+ "\" parameter " + "can't be negative.");
}
} else if (paramName.equals(PARAM_NAME_HR)) {
if (!(paramValue instanceof TemplateBooleanModel)) {
throw new TemplateModelException("The \"" + PARAM_NAME_HR
+ "\" parameter " + "must be a boolean.");
}
hrParam = ((TemplateBooleanModel) paramValue).getAsBoolean();
} else {
throw new TemplateModelException("Unsupported parameter: "
+ paramName);
}
}
if (!countParamSet) {
throw new TemplateModelException("The required \""
+ PARAM_NAME_COUNT + "\" paramter" + "is missing.");
}
if (loopVars.length > 1) {
throw new TemplateModelException(
"At most one loop variable is allowed.");
}
Writer out = env.getOut();
if (body != null) {
for (int i = 0; i < countParam; i++) {
if (hrParam && i != 0) {
out.write("<hr>");
}
if (loopVars.length > 0) {
loopVars[0] = new SimpleNumber(i + 1);
}
body.render(env.getOut());
}
}
}
}
3. 测试类 Test.java
package com.freemarker.test05.Directives2;
import freemarker.template.*;
import java.util.*;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
cfg.setDirectoryForTemplateLoading(new File("templates"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
Map root = new HashMap();
root.put("repeat", new RepeatDirective());
Template temp = cfg.getTemplate("test05.ftl");
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();
out.close();
}
}
运行结果
Test 1
Test 2
Test 3
Test 4
Test
<hr> Test
<hr> Test
1. Test
2. Test
3. Test