1 import java.io.IOException; 2 import java.io.Writer; 3 import java.util.Iterator; 4 import java.util.Map; 5 6 import freemarker.core.Environment; 7 import freemarker.template.SimpleNumber; 8 import freemarker.template.TemplateBooleanModel; 9 import freemarker.template.TemplateDirectiveBody; 10 import freemarker.template.TemplateDirectiveModel; 11 import freemarker.template.TemplateException; 12 import freemarker.template.TemplateModel; 13 import freemarker.template.TemplateModelException; 14 import freemarker.template.TemplateNumberModel; 15 16 /** 17 * FreeMarker 自定义标签实现重复输出内容体。 18 * 19 * 20 * 参数: 21 * count: 重复的次数,必须的且非负整数。 22 * hr: 设置是否输出HTML标签 "hr" 元素. Boolean. 可选的默认为fals. 23 * 24 * 25 * 循环变量: 只有一个,可选的. 从1开始。 26 * 27 * 28 */ 29 public class RepeatDirective implements TemplateDirectiveModel { 30 31 private static final String PARAM_NAME_COUNT = "count"; 32 private static final String PARAM_NAME_HR = "hr"; 33 34 public void execute(Environment env, Map params, TemplateModel[] loopVars, 35 TemplateDirectiveBody body) throws TemplateException, IOException { 36 37 // --------------------------------------------------------------------- 38 // 处理参数 39 40 int countParam = 0; 41 boolean countParamSet = false; 42 boolean hrParam = false; 43 44 Iterator paramIter = params.entrySet().iterator(); 45 while (paramIter.hasNext()) { 46 Map.Entry ent = (Map.Entry) paramIter.next(); 47 48 String paramName = (String) ent.getKey(); 49 TemplateModel paramValue = (TemplateModel) ent.getValue(); 50 51 if (paramName.equals(PARAM_NAME_COUNT)) { 52 if (!(paramValue instanceof TemplateNumberModel)) { 53 throw new TemplateModelException("The \"" + PARAM_NAME_HR 54 + "\" parameter " + "must be a number."); 55 } 56 countParam = ((TemplateNumberModel) paramValue).getAsNumber() 57 .intValue(); 58 countParamSet = true; 59 if (countParam < 0) { 60 throw new TemplateModelException("The \"" + PARAM_NAME_HR 61 + "\" parameter " + "can't be negative."); 62 } 63 } else if (paramName.equals(PARAM_NAME_HR)) { 64 if (!(paramValue instanceof TemplateBooleanModel)) { 65 throw new TemplateModelException("The \"" + PARAM_NAME_HR 66 + "\" parameter " + "must be a boolean."); 67 } 68 hrParam = ((TemplateBooleanModel) paramValue).getAsBoolean(); 69 } else { 70 throw new TemplateModelException("Unsupported parameter: " 71 + paramName); 72 } 73 } 74 if (!countParamSet) { 75 throw new TemplateModelException("The required \"" 76 + PARAM_NAME_COUNT + "\" paramter" + "is missing."); 77 } 78 79 if (loopVars.length > 1) { 80 throw new TemplateModelException( 81 "At most one loop variable is allowed."); 82 } 83 84 // Yeah, it was long and boring... 85 86 // --------------------------------------------------------------------- 87 // 真正开始处理输出内容 88 89 Writer out = env.getOut(); 90 if (body != null) { 91 for (int i = 0; i < countParam; i++) { 92 // 输出 <hr> 如果 参数hr 设置为true 93 if (hrParam && i != 0) { 94 out.write("<hr>"); 95 } 96 97 // 设置循环变量 98 if (loopVars.length > 0) { 99 loopVars[0] = new SimpleNumber(i + 1); 100 } 101 102 // 执行标签内容(same as <#nested> in FTL). 103 body.render(env.getOut()); 104 } 105 } 106 } 107 108 }
1 import java.io.File; 2 import java.io.IOException; 3 import java.io.Writer; 4 import java.util.Map; 5 6 import freemarker.template.Configuration; 7 import freemarker.template.DefaultObjectWrapper; 8 import freemarker.template.Template; 9 import freemarker.template.TemplateException; 10 11 /** 12 * 13 * 模板工具类 14 */ 15 public class FreeMarkertUtil { 16 /** 17 * @param templatePath 模板文件存放目录 18 * @param templateName 模板文件名称 19 * @param root 数据模型根对象 20 * @param templateEncoding 模板文件的编码方式 21 * @param out 输出流 22 */ 23 public static void processTemplate(String templatePath, String templateName, String templateEncoding, Map<?,?> root, Writer out){ 24 try { 25 Configuration config=new Configuration(); 26 File file=new File(templatePath); 27 //设置要解析的模板所在的目录,并加载模板文件 28 config.setDirectoryForTemplateLoading(file); 29 //设置包装器,并将对象包装为数据模型 30 config.setObjectWrapper(new DefaultObjectWrapper()); 31 32 //获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致 33 Template template=config.getTemplate(templateName,templateEncoding); 34 //合并数据模型与模板 35 36 template.process(root, out); 37 out.flush(); 38 out.close(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 }catch (TemplateException e) { 42 e.printStackTrace(); 43 } 44 45 } 46 }
1 import java.io.OutputStreamWriter; 2 import java.util.HashMap; 3 import java.util.Map; 4 5 /** 6 * 7 * 客户端测试模板输入类 8 */ 9 public class RepeatTest { 10 public static void main(String[] args) { 11 Map<String,Object> root=new HashMap<String, Object>(); 12 13 root.put("repeat", new RepeatDirective()); 14 15 FreeMarkertUtil.processTemplate("src/templates","repeat.ftl", "UTF-8", root, new OutputStreamWriter(System.out)); 16 17 } 18 }
1 模板文件repeat.ftl如下: 2 3 4 5 <#assign x = 1> 6 7 一个参数: 8 <@repeat count=4> 9 Test ${x} 10 <#assign x = x + 1> 11 </@repeat> 12 13 二个参数: 14 <@repeat count=3 hr=true> 15 Test 16 </@repeat> 17 18 循环变量: 19 <@repeat count=3; cnt> 20 ${cnt}. Test
输出结果:
- 一个参数:
- Test 1
- Test 2
- Test 3
- Test 4
- 二个参数:
- Test
- <hr> Test
- <hr> Test
- 循环变量:
- 1. Test
- 2. Test
- 3. Test
浙公网安备 33010602011771号