freemarker中实现自定义标签(包含处理参数以及循环变量) 博客分类: Freemarker freemarkerJava
程序员文章站
2024-03-07 23:39:39
...
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 自定义标签实现重复输出内容体。 * * * 参数: * count: 重复的次数,必须的且非负整数。 * hr: 设置是否输出HTML标签 "hr" 元素. Boolean. 可选的默认为fals. * * * 循环变量: 只有一个,可选的. 从1开始。 * * */ 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."); } // Yeah, it was long and boring... // --------------------------------------------------------------------- // 真正开始处理输出内容 Writer out = env.getOut(); if (body != null) { for (int i = 0; i < countParam; i++) { // 输出 <hr> 如果 参数hr 设置为true if (hrParam && i != 0) { out.write("<hr>"); } // 设置循环变量 if (loopVars.length > 0) { loopVars[0] = new SimpleNumber(i + 1); } // 执行标签内容(same as <#nested> in FTL). body.render(env.getOut()); } } } }
import java.io.File; import java.io.IOException; import java.io.Writer; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; /** * * 模板工具类 */ public class FreeMarkertUtil { /** * @param templatePath 模板文件存放目录 * @param templateName 模板文件名称 * @param root 数据模型根对象 * @param templateEncoding 模板文件的编码方式 * @param out 输出流 */ public static void processTemplate(String templatePath, String templateName, String templateEncoding, Map<?,?> root, Writer out){ try { Configuration config=new Configuration(); File file=new File(templatePath); //设置要解析的模板所在的目录,并加载模板文件 config.setDirectoryForTemplateLoading(file); //设置包装器,并将对象包装为数据模型 config.setObjectWrapper(new DefaultObjectWrapper()); //获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致 Template template=config.getTemplate(templateName,templateEncoding); //合并数据模型与模板 template.process(root, out); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); }catch (TemplateException e) { e.printStackTrace(); } } }
import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.Map; /** * * 客户端测试模板输入类 */ public class RepeatTest { public static void main(String[] args) { Map<String,Object> root=new HashMap<String, Object>(); root.put("repeat", new RepeatDirective()); FreeMarkertUtil.processTemplate("src/templates","repeat.ftl", "UTF-8", root, new OutputStreamWriter(System.out)); } } import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.Map; /** * * 客户端测试模板输入类 */ public class RepeatTest { public static void main(String[] args) { Map<String,Object> root=new HashMap<String, Object>(); root.put("repeat", new RepeatDirective()); FreeMarkertUtil.processTemplate("src/templates","repeat.ftl", "UTF-8", root, new OutputStreamWriter(System.out)); } } 模板文件repeat.ftl如下: Java代码 <#assign x = 1> 一个参数: <@repeat count=4> Test ${x} <#assign x = x + 1> </@repeat> 二个参数: <@repeat count=3 hr=true> Test </@repeat> 循环变量: <@repeat count=3; cnt> ${cnt}. Test </@repeat>
输出结果:
Java代码
一个参数:
Test 1
Test 2
Test 3
Test 4
二个参数:
Test
<hr> Test
<hr> Test
循环变量:
1. Test
2. Test
3. Test