FreeMarker 2.3.11版本以后提供了新的自定义标签接口TemplateDirectiveModel 以替代TemplateTransformModel,
下面是一个转换自定义标签的内容体中字母为大写字母的例子:
- import java.io.IOException;
- import java.io.Writer;
- import java.util.Map;
- import freemarker.core.Environment;
- import freemarker.template.TemplateDirectiveBody;
- import freemarker.template.TemplateDirectiveModel;
- import freemarker.template.TemplateException;
- import freemarker.template.TemplateModel;
- import freemarker.template.TemplateModelException;
- /**
- * FreeMarker 自定义指令,用于转换指令内容体中的字母为大写字母。
- *
- */
- public class UpperDirective implements TemplateDirectiveModel {
- public void execute(Environment env, Map params, TemplateModel[] loopVars,
- TemplateDirectiveBody body) throws TemplateException, IOException {
- // 检查是否传递参数,此指令禁止传参!
- if (!params.isEmpty()) {
- throw new TemplateModelException(
- "This directive doesn't allow parameters.");
- }
- // 禁用循环变量
- /*
- * 循环变量
- 用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在${"<@…>"}开始标记的参数后面指定循环变量的名字
- 例子:
- <#macro repeat count>
- <#list 1..count as x>
- <#nested x, x/2, x==count>
- </#list>
- </#macro>
- <@repeat count=4 ; c, halfc, last>
- ${c}. ${halfc}<#if last> Last!</#if>
- </@repeat>
- */
- if (loopVars.length != 0) {
- throw new TemplateModelException(
- "This directive doesn't allow loop variables.");
- }
- // 指令内容体不为空
- if (body != null) {
- // Executes the nested body. Same as <#nested> in FTL, except
- // that we use our own writer instead of the current output writer.
- body.render(new UpperCaseFilterWriter(env.getOut()));
- } else {
- throw new RuntimeException("missing body");
- }
- }
- /**
- * 输出流的包装器(转换大写字母)
- */
- private static class UpperCaseFilterWriter extends Writer {
- private final Writer out;
- UpperCaseFilterWriter(Writer out) {
- this.out = out;
- }
- public void write(char[] cbuf, int off, int len) throws IOException {
- char[] transformedCbuf = new char[len];
- for (int i = 0; i < len; i++) {
- transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);
- }
- out.write(transformedCbuf);
- }
- public void flush() throws IOException {
- out.flush();
- }
- public void close() throws IOException {
- out.close();
- }
- }
- }
- 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 ClientTest {
- public static void main(String[] args) {
- Map<String,Object> root=new HashMap<String, Object>();
- root.put("upper", new UpperDirective());
- FreeMarkertUtil.processTemplate("src/templates","demo01.ftl", "UTF-8", root, new OutputStreamWriter(System.out));
- }
- }
模板文件demo01.ftl如下:
- <@upper>
- bar
- <#-- All kind of FTL is allowed here -->
- <#list ["red", "green", "blue"] as color>
- ${color}
- </#list>
- baaz
- </@upper>