先借鉴javaeye Robbin的文章:FreeMarker三宗罪!
http://www.iteye.com/topic/17468
引用
FreeMarker是Quake Wang推荐我使用的。刚学FreeMarker的时候,发现freemarker真的很棒!简单易用,功能强大。但是用它做了几个项目以后开始不爽了。
一宗罪:freemarker的变量必须有值,没有被赋值的变量就会抛出异常,那个黄黄的freemarker出错页面,真是让人看了太难过了。
freemarker的FAQ上面冠冕堂皇的说,未赋值的变量强制抛错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误。但是实际的效果是:带来的是非常大的编程麻烦,程序里面几乎所有可能出现空值的变量统统需要加上${xxx?if_exists},有些循环条件还需要写if判断,这样不但没有杜绝应该杜绝的错误,反而极大增加了编程的麻烦。
二宗罪:freemarker的map限定key必须是string,其他数据类型竟然无法操作!这一点就不讲了,JavaEye上面已经有人抱怨过了。连Webwork的开发人员Pat Lightboy都在抱怨这一点。
三宗罪:freemarker为了编程方便把不可序列化的东西往session里面放!
freemarker支持在页面里面直接操作Session,request等,例如${Session[...]},方便确实很方便,但是一旦需要做群集,就会报错。
今天是b051问起我这个问题,他在做Tomcat群集的时候发现freemarker报错,HttpSessionHashModel不可序列化。他修改该类源代码,让他实现序列化接口,仍然报错。我一看,HttpSessionHashModel包含的属性:
private HttpSession session;
private final ObjectWrapper wrapper;
// These are required for lazy initializing session
private final FreemarkerServlet servlet;
private final HttpServletRequest request;
private final HttpServletResponse response;
登时晕倒,这样的东西还往Session里面放?bad smell!
严重警告应用需要往群集上面发布应用的同学们,千万别用freemarker!
不过瑕不掩瑜,freemarker也是有优点的:
1、易学易用
我是看了一天文档就用得挺熟练了,freemarker文档写得太好了,例子丰富,照做一遍全都会了。
2、功能强大
比Velocity强大多了,还支持JSP Tag。不过最有意义的是macro功能,可以自定义常用的macro,实现页面常规操作的可复用性。
3、报错信息友好
很多应用服务器的JSP报错信息是无法定位到源代码行的。不过freemarker报错定位很准确,丝毫不差,而且信息丰富,一看就知道怎么回事 (虽然那个黄黄的页面看起来让人难受)
看了很多关于freemarker的评论,自己也实际项目中使用了一下,总结了一些我需要注意的地方,记录下来:
1:freemarker 对于空值的判断。 freemarker接受的对象如果是空,会直接报错。这里不管它这样设计好坏,至少我觉得我的代码里面会有很多判断空值的语句。尤其是其上一层对象出现空的时候更要判断为空的情况,单纯字符串对象你可以使用
${obj!""}来判断obj是否为空,如果为空赋值为空字符串。使用
<#if obj??>判断obj是否为空。
2:freemarker接受的map对象key只能是string类型的。
3:freemarker的自定义函数。 这个自定义函数还是很有用的,可以在freemarker接受到后台请求自定义方法后再次进入到后台进行计算。
${methodModel('${tname}','${row}')} //methodModel 自定义的freemarker方法的类对象 在后台绑定
componentMap.put(EnumConstants.FREEMARKER_CUSTOMIZE_METHOD_METHODMODEL.toString(), new GridMethodModel());
常量就是methodModel 这个freemarker请求的类在后台通过map绑定的key-name.
让我们看看这个类里面怎么接受这2个参数和处理这个逻辑
public class GridMethodModel implements TemplateMethodModel {
@SuppressWarnings("unchecked")
@Override
public Object exec(List arg) throws TemplateModelException {
Row row = null ;
try {
row = RowDocument.Factory.parse(arg.get(1).toString().replaceAll("xml-fragment", "per:row")).getRow();
} catch (XmlException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String modelName = arg.get(0).toString();
Model[] models = row.getModelArray();
for(Model m : models)
{
if(modelName.equals(m.getName()))
return m.getValue();
}
return "";
}
}
4:freemarker几个判断类型的函数 和 简单的宏使用
引用
<#macro parse results>
<#if results?is_enumerable>
[<#list results as result><@parse results=result/><#if result_has_next>,</#if></#list>]
<#elseif results?is_hash_ex>
{<#list results?keys as key>"${key?j_string}":<@parse results=results[key]/><#if key_has_next>,</#if></#list>}
<#elseif results?is_date>"${results?string("yyyy-MM-dd")}"
<#elseif results?is_boolean>"${results?string}"
<#elseif results?is_number>"${results?c}"
<#elseif results?is_string>"${results?j_string}"
</#if>
</#macro>
<@compress single_line=true><@parse results=results/></@compress>
5:freemarker内建函数
引用
Sequence的内置函数
1. sequence?first 返回sequence的第一个值。
2. sequence?last 返回sequence的最后一个值。
3. sequence?reverse 将sequence的现有顺序反转,即倒序排序
4. sequence?size 返回sequence的大小
5. sequence?sort 将sequence中的对象转化为字符串后顺序排序
6. sequence?sort_by(value) 按sequence中对象的属性value进行排序
注意:Sequence不能为null。
Hash的内置函数
1. hash?keys 返回hash里的所有key,返回结果为sequence
2. hash?values 返回hash里的所有value,返回结果为sequence
操作布尔值
string 用于将布尔值转换为字符串输出
true转为“true”,false转换为“false”
foo?string(“yes”,”no”)如果布尔值是true,那么返回“yes”,否则返回no
操作数字
1.c 用于将数字转换为字符串
${123?c} à结果为123
2.string用于将数字转换为字符串
Freemarker中预订义了三种数字格式:number,currency(货币)和percent(百分比)其中number为默认的数字格式转换
例如:
<#assign tempNum=20>
${tempNum}
${tempNum?string.number}或${tempNum?string(“number”)} à结果为20
${tempNum?string.currency}或${tempNum?string(“currency”)} à结果为¥20.00
${tempNum?string. percent}或${tempNum?string(“percent”)} à结果为2,000%
freemarker 的内建函数 contains 的使用:
<#if employee.departments?contains(department)>checked="checked"</#if>
其中departments是一个集合,而department是departments集合里的一个元素。contains函数可以判断出,元素 department是否存在于集合departments里,最终返回一个Boolean
Sequence内置的分段器: chunk
用途:某些比较BT的排版需求
模板:
<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']>
<#list seq?chunk(4) as row>
<ul>
<li><#list row as cell>${cell} </#list></li>
</ul>
</#list>
<#list seq?chunk(4, '-') as row>
<tr>
<td><#list row as cell>${cell} </#list></td>
</tr>
</#list>
输出:
引用
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
</ul>
<ul>
<li>e</li>
<li>f</li>
<li>g</li>
<li>h</li>
</ul>
<ul>
<li>i</li>
<li>j</li>
</ul>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>e</td>
<td>f</td>
<td>g</td>
<td>h</td>
</tr>
<tr>
<td>i</td>
<td>j</td>
<td>-</td>
<td>-</td>
</tr>
以后有时间继续补充freemarker宏定义和使用以及freemarker调用java静态方法的好处和使用方法。
分享到:
相关推荐
freemarker 简单项目示例,生成静态html过程
Velocity 和 FreeMarker区别 对于大部分的应用来说,使用 FreeMarker 比 Velocity 更简单,因为 Velocity 还必须编写一些自定义的
FreeMarker概述、FreeMarker特性、FreeMarker应用指南
模板:velocity和freemarker的比较模板:velocity和freemarker的比较
FreeMarker,FreeMarker
SSH项目 有Freemarker模版 原本带的还有maven 但是被我简化掉了
在项目中难免和各种数据报表打交道,如导出XX申请表,登记表,推荐表之类。就可以通过现有信息导出Word文档。基于Java语言来导出Word文档的方式也有很多种,如Jacob,Apache POI,Freemarker,PageOffice,java2word...
安装freemarker插件(freemarker的eclipse插件) a) 首先下载 freemarker-ide-...这样在编辑混合有HTML和FreeMarker标记的文件时,可以选择右击文件 --> Open with HTML Editor 或者 Open with FreeMarker Editor
# 本项目主要介绍 1. itextpdf(CreatePdf) 不太推荐需要在代码内部编写PDF格式,如果要使用,建议写个基类,将同一版本 或者同一类型的公共方法写入,差异化的抽象,一个模板一个子类,子类使用@Component命名,...
一篇freemarker很不错的文章 reeMarker的模板文件并不...值得注意的是, /> 和指令之间不允许有空白字符. 2, 插值规则 FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}
FreeMarker
Freemarker SpringMVC Spring4 Hibernate4项目搭建测试
spring mvc、hibernate、freemarker开源项目源码下载
自己写的一个框架例子,公司也在用,框架是struts2+hibernate+freemarker
freemarker freemarker freemarker freemarker freemarker freemarker freemarker freemarker
Spring+Maven+freemarker+Ibatis项目结合
freemarker和sitemesh结合需要注意的地方,总体设计流程
Struts2 和freemarker实例 简单STRUTS2的使用,和freeMarker的使用
关于freemarker的jar包和代码例子
资料附有Java源代码和自己总结的使用说明及注意事项 大至预览如下: 1、用word编辑好模板 普通字符串替换为 ${string} 表格循环用标签 姓名:${user.userName} , 性别:${user.sex} 2、将word模板另存为xml...