`

freemarker中实现自定义标签(包含处理参数以及循环变量)(2.3.11版本以后的方式)

阅读更多

 

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));
		
	}
}

 

 模板文件repeat.ftl如下:

 

<#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>  

 

 输出结果:

一个参数:
  Test 1
  Test 2
  Test 3
  Test 4

二个参数:
  Test
<hr>  Test
<hr>  Test

循环变量:
  1. Test
  2. Test
  3. Test

 

分享到:
评论
2 楼 qiuq86 2013-04-08  
你好,请教一下,这个自定义标签的话,每次调用需要在类里添加FreeMarkertUtil.processTemplate("src/templates","repeat.ftl", "UTF-8", root, new OutputStreamWriter(System.out));来指定需要处理哪一个ftl吗,如果是这样的话,那么自定义标签不是不能通用了?
1 楼 mengfei86 2011-12-07  
 

相关推荐

    freemarker 自定义freeMarker标签

    这个类将定义你的自定义标签的行为,包括如何处理输入参数,如何处理模板模型数据,以及如何生成输出。 2. 注册自定义指令:在你的应用程序中,你需要将自定义指令类注册到FreeMarker配置中。这通常是通过`...

    Freemarker 自定义标签 简单案例

    在提供的"TestFreemarkerDiy"示例中,可能包含了一个简单的自定义标签实现以及一个演示如何使用该标签的Freemarker模板文件。通过分析这个示例,我们可以学习如何在实际项目中应用自定义标签,以提高模板的可维护性...

    spring mvc freemarker 自定义标签

    这个项目可能还包括了如何设置Spring MVC配置以支持自定义标签的步骤,以及如何在实际应用中调用这些自定义标签的示例。 自定义标签的灵活性非常高,你可以为任何复杂的业务逻辑或UI组件创建自定义标签。例如,你...

    实现通过jfinal框架自动扫描freemarker的自定义标签.zip

    本资源包的核心内容是教你如何在JFinal项目中实现FreeMarker自定义标签的自动扫描和注册,从而提升模板引擎的功能和灵活性。 首先,我们需要理解自定义标签的概念。在FreeMarker中,自定义标签允许开发者扩展其内置...

    freemark 自定义标签 总结

    通过上述内容,我们了解了Freemarker自定义标签的基本概念、创建与使用方法,以及如何在实际项目中发挥作用。自定义标签极大地增强了Freemarker的灵活性,使得模板语言可以更好地适应各种应用场景。在阅读...

    freemarker自定义分页标签宏

    总结起来,FreeMarker自定义分页标签宏的实现涉及到前端模板的宏定义与调用,以及后端的数据处理和链接生成。通过这种方式,我们可以创建出灵活且可复用的分页组件,方便地应用于各种项目中。理解并熟练掌握宏的使用...

    Struts2、Spring、Freemarker自定义标签

    Freemarker支持条件判断、循环结构、内置函数,以及自定义标签,增强了模板的灵活性。与JSP相比,Freemarker通常被认为更简洁、易读且更易于维护。 将这三个框架结合使用,可以构建出高效、灵活的Java Web应用。...

    freemarker及jeecms标签使用学习文档

    Freemarker是一个强大的模板...通过这些文档的学习,你将能够熟练地运用Freemarker来编写模板,以及在Jeecms中利用其自定义标签来构建高效、灵活的网站内容管理。不断实践和探索,将使你在Web开发领域更加游刃有余。

    使用freemarker扩展struts标签

    5. `说明.txt`: 这个文件可能包含了关于如何使用这些自定义标签的详细说明,包括如何在FreeMarker模板中引用它们以及它们的功能。 要扩展Struts2的FreeMarker标签库,你需要遵循以下步骤: 1. **创建模型类**: 定义...

    非常好用的自定义分页标签

    在JSP(JavaServer Pages)中,自定义标签是通过TLD(Tag Library Descriptor)文件来定义的,它描述了标签的行为、属性、变量等信息。TLD文件通常以`.tld`为扩展名,是XML格式的,用于告诉JSP引擎如何处理特定的...

    Freemarker简介及标签详解大全

    5. 通用数据模型:FreeMarker 不是直接反射到 Java 对象,Java 对象通过插件式对象封装,以变量方式在模板中显示。 6. 为 Web 准备:在模板语言中内建处理典型 Web 相关任务(如 HTML 转义)的结构。 7. 智能的国际...

    freemarker自定义的通用分页指令(标签)源码和使用示例

    一个用FTL定义的非常通用数据分页指令,有源码,有使用示例。使用效果图可以参看本人博客中的相关文章:http://blog.csdn.net/qjyong/archive/2009/10/18/4693142.aspx

    freemarker替换变量实例

    freemarker替换变量实例

    freemarker模板导出word循环图片表格源码和详细教程

    在本教程中,我们将探讨如何利用Freemarker模板来导出Word文档,并实现循环插入图片和表格的功能。这对于需要批量生成定制化报告或者文档的应用场景非常有用。 首先,我们需要了解Freemarker的基本语法。在...

    自定义分页标签源代码

    综上所述,这个自定义分页标签源代码提供了一种便捷的分页解决方案,通过自定义标签的方式简化了页面逻辑,使得开发者可以更专注于业务逻辑的实现,而不是分页的细节。理解并掌握这些知识点对于提升Java Web开发能力...

    freemarker实现一行两列算法

    ### Freemarker实现一行两列布局算法 在Web开发中,数据展示经常需要按照特定的格式进行排列,例如常见的列表项按行对齐显示等。Freemarker作为一种强大的模板引擎,可以方便地处理这类布局需求。本文将详细介绍...

    freemarker中文文档与包

    例如,`&lt;#if&gt;`用于条件判断,`&lt;#foreach&gt;`用于循环,`&lt;#assign&gt;`用于变量赋值,`&lt;#function&gt;`定义自定义函数。这些元素使得开发者可以在模板中灵活地控制输出内容。 2. **数据模型与变量**: 在Freemarker中,数据...

    freemarker格式化缩进文本或include指令

    在自定义指令中,你可以根据需要处理模板输出的文本,添加适当的空格、换行符,甚至可以实现更复杂的格式规则,如基于特定的代码风格指南进行格式化。 2. **模板包含(include指令)**: FreeMarker的`&lt;#include&gt;`...

Global site tag (gtag.js) - Google Analytics