freemarker中实现自定义标签(包含处理参数以及循环变量)

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot使用Freemarker可以非常方便地进行模板渲染,但是默认的列表循环标签可能不能完全满足我们的需求。这时我们可以自定义一个列表循环标签来满足我们的需求。 以下是一个简单的自定义列表循环标签示例: 首先我们创建一个类 extending `TemplateDirectiveModel`,并实现 `execute()` 方法。在该方法,我们解析参数,准备数据并调用模板引擎进行渲染。 ```java @Component public class CustomLoopTagDirective implements TemplateDirectiveModel { private static final String PARAM_NAME_FROM = "from"; private static final String PARAM_NAME_TO = "to"; private static final String PARAM_NAME_STEP = "step"; private static final String PARAM_NAME_VAR = "var"; @Autowired private Configuration configuration; @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { int from = Integer.parseInt(params.get(PARAM_NAME_FROM).toString()); int to = Integer.parseInt(params.get(PARAM_NAME_TO).toString()); int step = Integer.parseInt(params.get(PARAM_NAME_STEP).toString()); String var = params.get(PARAM_NAME_VAR).toString(); List<Integer> list = new ArrayList<>(); for (int i = from; i <= to; i += step) { list.add(i); } env.setVariable(var, configuration.getObjectWrapper().wrap(list)); if (body != null) { body.render(env.getOut()); } } } ``` 我们在这个类上使用 `@Component` 注解,将这个类注册为一个Spring Bean,这样我们就可以在模板使用这个标签了。 在 `execute()` 方法,我们首先解析 `from`、`to`、`step` 和 `var` 四个参数。然后我们根据这些参数计算出一个包含整数的列表,并将它作为一个变量存储在模板引擎的环境。 最后,我们调用 `body.render()` 方法进行渲染,将渲染结果输出到 `env.getOut()` 。 在模板使用自定义循环标签: ```html <@loop from=1 to=10 step=2 var="i"> ${i} </@loop> ``` 我们可以在模板使用这个标签。在这个例子,我们将会输出 `1, 3, 5, 7, 9` 这五个整数。 注意:在使用自定义标签时,需要在模板使用 `@` 符号来引用这个标签,比如 `@loop`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值