作者:empty 出版社:empty |
Freemarker与Velocity
1Freemarker
1.1Freemarker简介
FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出,仅是利用模板加上数据生成文本页面,即是由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据,并可以在模板中使用JSP标签。
FreeMarker与Web容器无关,即在web运行时,它并不知道Servlet或Http; FreeMarker同样也可以用于非Web应用环境。FreeMarker不仅可以用作表现层的实现技术,用来生成HTML Web页面,而且还可以用于生成XML,JSP或Java等。Freemarker是免费的。
1.2Freemarker特性
具有一般通用的功能:
能够生成各种任意格式的文本,如HTML,XML,RTF(多文本格式),Java源代码等等;
易于嵌入到产品中,是轻量级的,不需要servlet环境,不依赖javax.servlet.classes;
可插入的模板读取器(插件式模板载入器),即可以从任意的源码读取任意的模板,如本地本件、数据库等等;
可以做任意你想生成的文本,存储为本地文件,可以用来发送Email或返回WEB浏览器;
强大的模板语言:
完整的指令,如include,if/elseif/else,loop;
在模板中创建和改变变量;
几乎在任何地方都可以是使用复杂表达式来指定值;
支持宏指令;
字符串操作,如concateration,sub-string,uppercase,capitalize,escaping,等等;
十进制数学运算;
读取数组和相关的数组元素;
可以自己添加特殊的计算方法;
命名的宏有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突;
命名的宏,可以具有位置参数和嵌套内容;
通用的数据模型:
FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示;
可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等),使模板开发者直接使用方法,不受细节的打扰;
为web准备:
在模板语言中内建处理典型web相关任务(如HTML转义)的结构;
能够集成到Model2 web应用框架中作为JSP的替代;
支持JSP标记库;
为MVC模式设计,即分离可视化设计和应用程序逻辑,分离页面设计员和程序员;
智能的国际化和本地化:
字符集智能化(内部使用UNICODE);
数字格式本地化敏感;
日期和时间格式本地化敏感;
非US字符集可以用作标识(如变量名);
多种不同语言的相同模板;
强大的XML处理能力:
#recurse> 和 #visit>指令(2.3版本)用于递归遍历XML树;
在模板中清楚和直接的访问XML对象模型;
2Velocity
2.1Velocity简介
Velocity是一个基于JAVA的模板引擎(template engine:模板引擎的作用就是取得数据并加以处理,最后显示出数据)。它允许任何人仅仅简单的使用模板语言来引用由java代码定义的对象。
Velocity主要应用于Web应用的开发;作为模板产生SQL,XML或代码等;作为其他系统的集成组件使用。
3两者的比较
Velocity相比较FreeMarker而言更加简单,轻量级,但它的功能却没有FreeMarker那么强大。依据评测的结论,freemarker稍快一些,差别在毫秒级别,对用户而言可以忽略不计,若超大流量,考虑负载时,较倾向后者freemarker。
Velocity出现得较早些,也有更多的受众,因此在考虑到人员配给上,略占优势。
对于大部分的应用来说,使用FreeMarker比Velocity更简单,因为Velocity还必须编写一些自定义的toolbox类以及一遍遍重复的编写一些比较通用的模板代码,会浪费一些时间。另外Velocity使用工具类和变通的方法在模板引擎中似乎不是有一个非常有效的做法。同时,Velocity的做法使得在Velocity的模板中大量的跟Java对象进行交互,违反了简单的原则。
Velocity一个优于FreeMarker的地方在于它很广泛的第三方支持以及一个非常庞大的用户社区,你可以通过这个社区获得到很多的帮助,相反FreeMarker在这方面要差的很多,虽然已经有越来越多的第三方软件开始在支持FreeMarker。
以下是一些FreeMarker能实现而Velocity实现不了的功能:
日期和数字的支持:
可以执行运算和比较,对任意数量的类型,包括任意精度类型,而不仅仅是整数;
可以比较和显示(格式化)日期/时间值;
国际化:
可以格式数字区域,各种各样的内置和自定义数字格式模式;
可以格式日期地区和时区,各种各样的内置和定制的日期格式模式;
标识符(变量名)可以包含非英语字母,阿拉伯字母,汉字等;
循环处理:
可以退出循环;
可以访问控制变量外循环机构的内部循环;
可以得知当前是否到了循环的结束位置;
模板级别的数组处理:
可以使用[i]的语法来访问数组元素,包括原始的和非原始的指数;
可以获取到数组的长度;
宏定义:
宏调用可以通过位置或名称进行参数传递;
宏的参数可以设定默认值,在调用宏时如果没有指定该参数,则使用默认值代替;
通过 @myMacro>body /@myMacro>可以支持宏的嵌套;
宏允许先使用再定义;
宏可以定义局部变量;
命名空间:
可以使用多个名称空间的变数,对建立”宏库”是非常 有用的,可以防止名称冲突与申请特定变量或其他宏变量的库;
内置与Java语言无关的字符串、列表、Map的操作方法;
能提示模板中的拼写错误以及其他错误:
当访问一个不存在的变量时,FreeMarker在执行该模板时会报错,通过配置,可以指定FreeMarker在碰到此类错误时停止执行,还是忽略该错误,同时FreeMarker会在日志中记录此问题,如果输入错误指令的名称,FreeMarker将抛出一个异常;
更高级的文本输出工具;
文本处理:
支持Java的特殊字符处理,例如 b, t, n, f, r, ”, `, 以及UNICODE的 xXXX,除了通常的字符串,数字,和布尔常量还可以定义列表和地图文字以及内部模板;
高级的空格清除:
FreeMarker将删除一些多余的空格、条格、换行等字符,从而消除一些明显多余的空格,FreeMarker也提供指令来删除多余的空格;
与其他技术的集成:
提供JSP标签库以便在JSP中嵌入FreeMarker模板;
可以直接和Python对象一起工作:
更强大的XML转换功能;
先进的模板元程序:
可以捕捉到输出的任意部分范本,背景变量;
可以任意解释的范围变量,就如同此元程序是一个模板定义。
Velocity是较早出现的用于代替JSP的模板语言,它的优点主要有以下几点:不能编写java代码,可以实现严格的mvc分离;
性能良好;
使用表达式语言。
缺点主要有:不是官方标准;
用户群体和第三方标签库没有Jsp多;
对Jsp标签支持不够好;
FreeMarker的优点主要有:
使用FreeMarker的优点之一,可以彻底的分离表现层和业务逻辑。使用JSP开发过程中在页面中大量的存在业务逻辑的代码,使得页面内容凌乱,在后期大量的修改维护过程中就变得非常困难。FreeMarker不支持Java脚本代码,它的原理就是:模板+数据模型=输出,其中模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的,用户最终看到的输出是模板和数据模型合并后创建的。
使用FreeMarker的优点之二,可以提高开发效率。在以往的开发中,使用的都是JSP页面展示数据,即所谓的表现层,但是JSP在第一次执行的时候需要转换成Servlet类,开发阶段进行功能调试时需要频繁的修改JSP,每次修改都编译和转换,就会浪费很多编译时间,相对于JSP来说,FreeMarker模板技术不存在编译和转换的问题,所以就不会存在以上问题。
使用FreeMarker的优点之三,使得开发过程中的人员分工更加明确。使用FreeMarker后,作为界面开发人员,只要专心创建HTML文件、图像以及Web页面的其他可视化方面,不用理会数据,而程序开发人员则专注于系统实现,负责为页面准备要显示的数据即可。
FreeMarker的缺点主要有:
使用FreeMarker的缺点之一,应用FreeMarker模板技术,在修改模板后,可能会看到已经过期的数据。如:生成静态的HTML页面后,如果一旦模板改变,而没有及时更新模板生成的HTML页面的话,用户看到就是过期的数据。
使用FreeMarker的缺点之二,FreeMarker模板技术在应用过程中,FreeMarker中的变量必须要赋值,如果不赋值,就会抛出异常。如果想避免错误则需要对每个应用if/elseif/else指令进行判断,会给变成带来麻烦。
使用FreeMarker的缺点之三,FreeMarker的map限定key必须是string,其他数据类型无法操作。
使用FreeMarker的缺点之四,FreeMarker不支持集群应用。为了编程的方便性,把序列化的东西都放到了Session中,如Session,request等,在开发的过程中比较方便,但是如果放到集群中,就会出现错误。
从以上比较可知在实际使用中基于以下原因更倾向于使用FreeMarker:
性能上,在复杂页面上(包含大量判断、日期金额格式化)的页面上,freemarker的性能比使用tag和el的jsp要好;
宏定义比jsp tag方便;
内置大量常用功能,比如Html过滤,日期金额格式化等等,使用非常方便;
支持JSP标签;
可以实现严格的mvc分离;
4velocity,freemarker与jsp比较
在java领域,表现层技术主要有三种:jsp、freemarker、velocity。
jsp是大家最熟悉的技术它的优点:
功能强大,可以写java代码;支持jsp标签(jsp tag)支持表达式语言;官方标准,用户群广,丰富的第三方jsp标签库;性能良好,jsp编译成class文件执行,有很好的性能表现。
缺点:由于可以编写java代码,如使用不当容易破坏mvc结构(也不算是缺点)。
Velocity是较早出现的拥有代替jsp的模板语言。优点:
不能编写java代码,可以实现严格的mvc分离;性能良好,据说比jsp性能还要好些;使用表达式语言。
缺点:
不是官方标准;用户群体和第三方标签库没有Jsp多;对Jsp标签库支持不够好。
freemarker优点:
不能编写java代码,可以实现严格的mvc分离;新能非常不错;对jsp标签支持良好;内置大量常用功能,使用非常方便;使用表达式语言。
缺点:
不是官方标准,用户群体和第三方标签库没有jsp多。
性能:velocity应该是最好的,其次是jsp,普通的页面freemarker性能最差,但是在复杂页面上(包含大量判断、日期金额格式化)的页面上,freemarker的性能比使用tag和el的jsp要好。
5FreeMarker示例
本文主要通过一个示例来演示FreeMarker原理,此示例有两种实现方式,一种是直接通过客户端的方式实现,另外一种是FreeMarker和Spring mvc框架进行集成的方式。
FreeMarker的原理主要是利用模板+数据模型得到输出文件,即是将页面中所需要的样式放入FreeMarker文件中,然后将页面所需要的数据动态绑定,并放入Map中,通过调用FreeMarker模板文件解析类process()方法完成静态页面的生成。如下图所示:
5.1FreeMarker的内置函数
在使用FreeMarker开发模板的过程中,经常会操作例如字符串,数字,集合等对象,因此介绍 一下FreeMarker的内置函数及用法。
Sequence的内置函数:
sequence?first 返回sequence的第一个值;
sequence?last 返回sequence的最后一个值;
sequence?size 返回sequence的大小;
sequence?reverse 将sequence的现有顺序发转,即倒序排序;
sequence?sort 将sequence中的对象转化为字符串后顺序排序;
sequence?sort_by(value) 按sequence中对象的属性value进行排序;
另外需要注意的是:sequence不能为null。
Hash的内置函数:
hash?keys 返回hash里的所有key,返回结果为sequence;
hash?values 返回hash里的所有value,返回结果为sequence;
操作字符串函数:
substring(start, end)从一个字符串中截取子串:
start:截取子串开始的索引,start必须大于等于0,小于等于end;
end:截取子串的长度,end必须大于等于0,小于等于字符串长度,如果省略该参数,默认为字符串长度;
cap_first将字符串中的第一个单词的首字母变为大写;
uncap_first将字符串中的第一个单词的首字母变为小写;
capitalize将字符串中的所有单词的首字母变为大写;
date,time,datetime将字符串转换为日期;
操作数字:
C用于将数字转换为字符串;
String用于将数字转换为字符串;
FreeMarker中预定义了三种数字格式:number,currency(货币)和percent(百分比)其中number为默认的数字格式转换。
操作布尔值:
String用于将布尔值转换为字符串输出,true转为”true”,false转换为”false”;
5.2模板开发
模板能够用后端控制器提供的数据动态地生产HTML页面,FreeMarker的模板主要由以下四个部分组成:
文本:在生成页面时会直接按原样输出;
Interpolation插值:这部分的输出会被计算的值来替换,即${}或#{}格式的部分,将使用数据模型中的部分替代输出;
FTL tags标签:FTL标签和HTML标签很相似,在名字前加#予以区分,但是它们却是给FreeMarker的指示而且不会打印在输出内容中;
Comments注释:此注释和HTML的注释也 很相似,但它们是由 #-- -->来组成的。注释会被FreeMarker所忽略,更不会在输出内容中显示;
如下所示是具体的模板结构示例, :
5.1.1FTL指令
上面的模板结构中提到了FTL指令,在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3中FTL标签,如下所示:
开始标签: #directivename parameter>
结束标签: /#directivename >
空标签: #directivename parameter />
实际上,使用标签时前面的符合#可可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号。
以上是自定义的宏指令的使用。
以上是assign指令的使用
5.1.2插值
FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{format}。
通用插值有分为四种情况:
(1)FreeMarker插值结果为字符串值:直接输出表达式结果,如${user.name}输出为字符串”xieling”
(2)FreeMarker插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出,可以使用内建的字符串函数格式化单个插值,如下所示:
以上插值对应的输出结果如下所示:
(3)FreeMarker插值结果为日期值:根据默认格式(#setting指令设置)将表达式结果转换成文本输出,可以使用内建的字符串函数格式化单个插值,可参考上面的示例。
(4)FreeMarker的插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出,可以使用内建的字符串函数格式化单个插值,如下所示:
FreeMarker的数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:
mX:小数部分最小X位
MX:小数部分最大X位
5.3程序开发
FreeMarker中的程序开发主要是为模板文件中的变量动态地提供数据,主要包括配置实例的创建,模型数据的创建,获取模板以及将模板和数据模型进行合并生成最后的输出文件。
创建配置实例是指创建一个freemarker.template.Configuration实例,模型数据创建是指创建模板中所需要展示的数据,最后是获取模板文件将模板和数据模型结合生成最后的文件。
5.4Freemarker客户端实现
FreeMarker的客户端实现demo是直接通过客户端调用实现,不需要任何配置文件即可完成。客户端实现也需要模板文件和后端程序两部分。
模板文件的部分源码如上图所示:
以上代码是模板文件解析器类,主要创建Configuration示例,通过Configuration示例加载指定的模板文件,设置编码,然后将获取的模板文件和模型数据进行结合生成组后的文件。
以上是客户端测试类,主要设置模型数据,并指定要加载的模板文件路径及输出文件,最后调用模板解析器类,实现生成代码功能。
上图是最终生成的文件。
5.5Freemarker与Spring集成
FreeMarker与Spring的集成主要是通过配置文件来实现的。首先是模板文件的实现和客户端方式的模板文件是相似的。
模板文件的部分源码如上图所示:
其次是配置文件的实现,在spring-mvc.xml配置文件中主要配置了要使用的configuration类,要加载的模板文件的路径,FreeMarker最终生成的视图解析器配置,其源码如下图所示:
再次是数据模型类的实现,在此类中主要设置了页面要展示的数据,以及最终生成的视图类型,如下源码所示:
最后生成的视图代码展示的结果如下图所示: