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
分享到:
相关推荐
这个类将定义你的自定义标签的行为,包括如何处理输入参数,如何处理模板模型数据,以及如何生成输出。 2. 注册自定义指令:在你的应用程序中,你需要将自定义指令类注册到FreeMarker配置中。这通常是通过`...
在提供的"TestFreemarkerDiy"示例中,可能包含了一个简单的自定义标签实现以及一个演示如何使用该标签的Freemarker模板文件。通过分析这个示例,我们可以学习如何在实际项目中应用自定义标签,以提高模板的可维护性...
通过上述内容,我们了解了Freemarker自定义标签的基本概念、创建与使用方法,以及如何在实际项目中发挥作用。自定义标签极大地增强了Freemarker的灵活性,使得模板语言可以更好地适应各种应用场景。在阅读...
Freemarker是一个强大的模板...通过这些文档的学习,你将能够熟练地运用Freemarker来编写模板,以及在Jeecms中利用其自定义标签来构建高效、灵活的网站内容管理。不断实践和探索,将使你在Web开发领域更加游刃有余。
例如,`<#if>`用于条件判断,`<#foreach>`用于循环,`<#assign>`用于变量赋值,`<#function>`定义自定义函数。这些元素使得开发者可以在模板中灵活地控制输出内容。 2. **数据模型与变量**: 在Freemarker中,数据...
4. **指令**:Freemarker支持一系列指令,如`<#assign>`分配变量,`<#include>`包含其他模板,`<#nested>`处理子模板等,它们扩展了模板的功能。 5. **模板继承与布局**:`<#macro>`定义宏,实现代码复用;`...
- **Spring MVC**:在Spring MVC中,Freemarker作为视图解析器,处理Controller返回的模型数据。 - **配置设置**:通过`freemarkerConfigurer` bean,可以在Spring中配置Freemarker的属性。 7. **错误处理和调试*...
通过这份"freemarker中文手册",读者可以系统地学习Freemarker的各个方面,包括基本语法、进阶特性以及在实际项目中的应用技巧。文档中的示例部分尤其重要,因为实践是理解和掌握任何技术的关键。在阅读和学习的过程...
`MacroWrapper` 可能用于包装和管理宏的定义,包括宏的参数处理、调用和输出。 6. **模板继承和导入** 在 Freemarker 中,`<#import>` 和 `<#extends>` 指令是实现模板复用的重要方式。`<#import>` 用于导入其他...
标签的详解涵盖了Freemarker的所有内置标签和自定义标签的使用方式,包括它们的参数、返回值以及在不同场景下的最佳实践。例如,`<#assign>`用于声明变量,`<#function>`用于定义函数,`<#tobool>`用于转换值为布尔...
- **指令参考文档**:详细介绍了FreeMarker中所有的指令,包括条件控制指令、循环控制指令、变量操作指令、指令引用和自定义指令等。 FreeMarker中文手册还提供了大量的实例代码和清晰的描述,帮助开发者掌握...
5. **自定义标签库**:Struts2支持自定义标签,结合Freemarker的模板,可以创建出易于理解和维护的视图层代码。 6. **错误和异常处理**:Struts2提供了一套完善的异常处理机制,可以在发生错误时跳转到特定的错误...
模板是纯文本文件,其中包含控制结构(如条件语句和循环)以及对数据模型的引用。FreeMarker 的优点在于它与任何特定的编程语言解耦,使得模板设计者和程序员可以独立工作。在Java项目中,FreeMarker 可以用来生成...
3. **控制结构**: Freemarker提供了类似编程语言的条件语句(如#if、#else、#elseif)、循环语句(如#foreach)以及异常处理(如#try、#catch)。这些结构使得模板能够根据数据进行条件渲染和迭代操作。 4. **指令*...
- **FreeMarker**的模板语法简洁灵活,支持各种控制结构(如条件语句、循环语句)、内置函数以及自定义指令等。 - **FreeMarker**模板的基本结构通常包括: - **静态文本**:直接显示在最终输出中的内容。 - **...
- **变量管理**:允许在模板中创建和修改变量,增强数据处理能力。 - **表达式支持**:几乎可以在模板中的任何位置使用复杂表达式来计算或指定值。 - **宏定义**:支持定义命名的宏,可用于函数调用,提升模板复用性...
4. **自定义标签支持**:除了内置的对象外,FreeMarker还允许用户自定义标签,从而扩展模板语言的功能。这为高级用户提供了一种非常灵活的方式来扩展FreeMarker的功能。 5. **多语言支持**:除了提供中文版本的手册...
FreeMarker的核心功能包括了对数值和类型的操作,其中类型包括了Java中的各种基本类型、容器类型以及用户自定义的类型。模板的总体结构涉及到指令的使用,这些指令控制了模板处理流程,例如条件判断、循环等逻辑结构...