场景

在做一个CMS网站时,要列出网站栏目,比如有新闻,科技,体育,财经等栏目。栏目内容存放在数据库中。

调用语法

//没有循环变量
<@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN/>

//有循环变量
<@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN ;lv1, lv2, ..., lvN/>

自定义指令使用

cms_chanel_list指令的作用是按传入的参数count找出指定数量的栏目,并且过滤掉名字为“体育”的栏目。

<@cms_chanel_list count=5 exclude="体育">
<#list chllist as c>
<dt>
<a href="#" target="_self"><span>${c.name}</span></a>
</dt>
</#list>
</@cms_chanel_list>

自定定义指令

首先要实现TemplateDirectiveModel接口。

public class ChanelListDirective implements TemplateDirectiveModel {
@Inject
private ChanelDao chanelDao;
/*
* @param 传入的参数,params类型为Map<String,
* TemplateModel>,由于历史原因没用泛型。比如传入参数“count=5”,String为count,TemplateModel为5
*
* @loopVars 循环变量
*
* @see freemarker.template.TemplateDirectiveModel#execute(freemarker.core.
* Environment, java.util.Map, freemarker.template.TemplateModel[],
* freemarker.template.TemplateDirectiveBody)
*/
public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
// TODO Auto-generated method stub
if (params == null || params.size() == 0) {
throw new TemplateException("params can not be empty", env);
}
int count = 0;
String excludeStr = null;
// 处理传入的参数
for (Object key : params.keySet()) {
String name = (String) key;
if (name.equalsIgnoreCase("count")) {
if (params.get(key) instanceof TemplateNumberModel)
count = ((TemplateNumberModel) params.get(key)).getAsNumber().intValue();
else
throw new TemplateException("count param must be number", env);
}
if (name.equalsIgnoreCase("exclude")) {
if (params.get(key) instanceof TemplateScalarModel)
excludeStr = ((TemplateScalarModel) params.get(key)).getAsString();
else
throw new TemplateException("execlude param must be string", env);
}
}
List<Chanel> chanleList = chanelDao.loadAll();
List<Chanel> list = new ArrayList<>();
for (int i = 0; i < count && i < chanleList.size(); i++) {
if (chanleList.get(i).getName().equals(excludeStr))
continue;
list.add(chanleList.get(i));
}
env.setVariable("chllist", ObjectWrapper.DEFAULT_WRAPPER.wrap(list));
if (body != null) {
body.render(env.getOut());
}
}
}

在freemarker中配置

需要绑定该指令为cms_chanel_list

...
<bean id="chanelListDirective" class="com.ydoing.web.directives.ChanelListDirective"/>
<!-- 配置freeMarker的模板路径 -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/t/cms/www/default/" />
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerVariables">
<map>
<entry key="cms_chanel_list" value-ref="chanelListDirective"/>
</map>
</property>
...