最近用freemarker做一个代码生成工具,以减少工作量,因为我们项目中开发已经格式化了、固定化了,为什么还要完全自己写呢。fm用起来尽管有不方便的地方,但功能确实挺强大的,下面分享一下我在使用中遇到的问题。
1.先说说常用的函数吧
html : 将特殊html标记进行转换,如<转换成<
cap_first : 首字母大写
lower_case : 转换成小写
upper_case :转换成大写
trim : 剪掉前后空白
size :得到序列、数组的元素个数
int :获得小数的整数部分
substring (from, toExclusive):取子串
contains :和java同
ends_with : 以…结尾 吗
starts_with : 以…开头吗
last_index_of : 最后的索引所在位置
length : 字符串长度
matches :是否 匹配 一个正则
replace : 替换
${"this is a car acarus"?replace("car", "bulldozer")}----------->
this is a bulldozer abulldozerus
fm的函数调用语法是变量名后面跟一个问号,再写上方法名,如:${test?upper_case}
如果要调用2个以上的内置方法,则连续写,如:${test?upper_case?html}
2.自定义方法
有时候内置的方法无法满足你的特殊需求,怎么办?实现TemplateMethodModelEx接口,使用方法 Object exec(List list),下面是一个取模板里变量类名的方法:
public class GetClsNameTMM implements TemplateMethodModelEx{
private final static Log log= LogFactory.getLog(GetClsNameTMM.class);
public Object exec(List list) throws TemplateModelException {
if (list.size()!=1){
return new TemplateModelException("wrong param number, must be 1!");
}
String name = list.get(0).class.toString();
log.debug("class name of '"+list.get(0)+"' is '"+name+"'");
return name;
}
}
在java中定义参数map的时候:
root.put("nameOfClass", new GetClsNameTMM());
然后在模板里如下调用:
nameOfClass(${someVar})
3.如何取得变量类名
如果是javabean,可以通过“变量.class.simpleName”或“变量.class.name”,但对于String这样的内置java类则得不到,原因是变量在模板中并不是原始的类型,fm会为每种类型选择一个合适的包装器,如果你想任意类型的变量都能取到类名,做进一步的判断,唯一的选择是2中提供的方法--定义一个方法,实现TemplateMethodModelEx
4.删除连续多个变量之间的换行符
设想这样一个应用场景,你想生成一个java方法的代码,方法的参数是多个的,你一定不希望它是一行一个参数吧,那你就需要使用<#t>标签了,它的意思是去掉当前行首尾的空白,注意,换行也当成空白,当初看文档的时候不知道这一点,所以忽略了,好一顿google才找到答案。比如下面的例子:
1 <#t>
2<#t>
3<#lt>
4
5<#rt>
6
执行后的结果是:
4
5 6
<#t>在行里的位置无所谓,类似还有<#lt><#rt>,意思是去掉左侧和右侧的空白。
5.如何判断变量是否存在或对象的属性是否为null
用??进行判断,如下:
<#if user??><h1>Welcome ${user}!</h1></#if>
存在或有值则为true
6.如何输出${xxx} 这样的字符串
jsp el的语法和fm很像,都支持${}这样来输出变量内容,当然jsp本身其实也是一种模板技术,二者本质是一样的,你如果想生成jsp el的代码就会遇到这个问题,不能直接写,否则fm会把它当成fm的东西来解析成它变量了,这时候需要使用<#noparse>标签。
<#noparse>${ccc}</#noparse>
这样fm就不会把它当成变量来解析而是直接输出 ${ccc} 了
还有其它很多功能就不说了,很容易在文档中找到,以上只是一些比较重要而且不容易找到答案的地方。