前言
OneBlog中使用到了springboot + freemarker的技术,同时项目里多个controller中都需要查询一个公有的数据集合,一般做法是直接在每个controller的方法中通过
model.addAttribute("xx",xx);的方式手动设置,但这样就有个明显的问题:重复代码。同一个实现需要在不同的controller方法中设置,除了重复代码外,还会给后期维护造成不必要的麻烦。在以往的jsp项目中,可以通过taglib实现自定义标签,那么,在freemarker中是否也可以实现这种功能呢?今天就尝试一下在freemarker中如何使用自定义标签。
TemplateDirectiveModel
在freemarker中实现自定义的标签,主要就是靠 TemplateDirectiveModel类。如字面意思:模板指令模型,主要就是用来扩展自定义的指令(和freemarker的宏类似,自定义标签也属于这个范畴)
1 public interface TemplateDirectiveModel extends TemplateModel { 2 void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException; 3 }
TemplateDirectiveModel是一个接口,类中只有一个execute方法供使用者实现,而我们要做的就是通过实现execute方法,实现自定义标签的功能。当页面模板中使用自定义标签时,会自动调用该方法。
先来看一下execute方法的参数含义
env : 表示模板处理期间的运行时环境。该对象会存储模板创建的临时变量集、模板设置的值、对数据模型根的引用等等,通常用它来输出相关内容,如Writer out = env.getOut()。
params : 传递给自定义标签的参数(如果有的话)。其中map的key是自定义标签的参数名,value值是TemplateModel实例【1】。
loopVars : 循环替代变量 (未发现有什么用,希望知道的朋友能指教一二)
body : 表示自定义标签中嵌套的内容。说简单点就是自定义标签内的内容体。如果指令调用没有嵌套内容(例如,就像<@myDirective />或者<@myDirective>),那么这个参数就会为空。
【1】:TemplateModel是一个接口类型,代表FreeMarker模板语言(FTL)数据类型的接口的公共超接口,即所有的数据类型都会被freemarker转成对应的TemplateModel。通常我们都使用TemplateScalarModel接口来替代它获取一个String 值,如TemplateScalarModel.getAsString();当然还有其它常用的替代接口,如TemplateNumberModel获取number等
| 类型 | FreeMarker接口 | FreeMarker实现 |
|---|---|---|
| 字符串 | TemplateScalarModel | SimpleScalar |
| 数值 | TemplateNumberModel | SimpleNumber |
| 日期 | TemplateDateModel | SimpleDate |
| 布尔 | TemplateBooleanModel | TemplateBooleanModel.TRUE |
| 哈希 | TemplateHashModel | SimpleHash |
| 序列 | TemplateSequenceModel | SimpleSequence |
| 集合 | TemplateCollectionModel | SimpleCollection |
| 节点 | TemplateNodeModel | NodeModel |
实现自定义标签
前面了解了 TemplateDirectiveModel的基本含义和用法,那么,接下来我们就以OneBlog中的例子来简单解释下如何实现自定义标签。
ps:为了方便阅读,本例只摘出了一部分关键代码,详细内容,请参考我的开源博客:https://gitee.com/yadong.zhang/DBlog
一、创建类实现TemplateDirectiveModel接口
1 @Component 2 public class CustomTagDirective

