freemarker中实现自定义标签(2.3.11版本以后的方式)

本文介绍如何使用Freemaker 2.3.11及更高版本中的TemplateDirectiveModel接口创建自定义指令,以实现将模板内容体中的字母转换为大写的功能。通过具体的Java代码示例,展示了自定义指令的实现细节,包括参数检查、循环变量处理以及内容体的转换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值