FreeMarker教程

FreeMarker教程

分类:JavaWeb2013-01-2511:164410人阅读评论(0)收藏举报

freemarkerFreeMarkerFreemarkerjavawebJavaWebjavaWebjspJspJSPmvcMVC显示层

(本文乃是原创,作者是Lubby,转载请说明来源,谢谢!)

一、什么是模板引擎,为什么要用模板引擎

在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面、风格、布局、效果等等可视元素;而程序员则忙于创建程式的商业流程,生成设计页面要显示的数据等等。

很多时候,要显示的资料在设计的时候并不存在,它们一般是在运行时由程式产生的,比如执行“价格不高于800NT的USBDisk”查询的返回结果。这种技术需求产生了JSP等Scriptlet,JSP十分强大,但是也常常被滥用,并导致一些不良的后果

将逻辑和表现混合在一起。

破坏了美工和程序员职责的正常分解。

使JSP页面难以阅读和维护。

模板引擎就是为了解决上面的问题而产生的。在设计HTML的时候,我们加入一些特定指令来指定要插入哪些数据,这些加了特殊指令的HTML或者其他文本,我们称为模板(Template)。而模板引擎会在输出页面时,用适当的数据替代这些代码。

模板和嵌入JSP的HTML是不同的,模板指令只有很有限的编程能力,可以避免混入商业逻辑。

二、FreeMarker与JSP、Velocity的对比

FreeMarker优点:

1.不能编写Java代码,可以实现严格的MVC分离

2.美工和技术的工作分离

3.页面是静态化的,这样方便搜索引擎的收录

4.模板可以存在数据库,可以实现cms定制功能

5.性能不错,页面显示的速度非常快,省去了JSP编译的过程

6.内置许多功能强大的标记、以及大量常用的函数

7.带有宏定义(macro)功能,类似于JSP自定义标签,但是更加简单方便

8.支持JSP标签

9.Struts2对其支持效果不错

10.不一定非要在Servlet中去实现

FreeMarker缺点:

1.性能没有Velocity高,学习起来没有Velocity简单

2.需要花费时间重新学习

3.FreeMarker中不能读取值为null的变量,会报错,必须要设置默认值或者判断

4.模板修改之后,如果没有更新模板生成的HTML,会看到过期的页面

5.MyEclipseIDE插件的效果不太好

三、一个简单的FreeMarkerDemo

1.导入Jar包:

FreeMarker需要freemarker-2.3.19.jar包,Struts2里面有这个Jar包。

2.编写模板文件

FreeMarker的模板文件的后缀名是ftl。这里是我写的一个Example.ftl,我把它放在WebRoot下的Template文件夹下。

[html]viewplaincopy

<html>

<head>

<title>Example</title>

</head>

<body>

<h1>大家好,我的名字叫${name},我家住在${address},我今年${age}岁了!</h1>

</body>

</html>

3.模板的解析

模板需要被解析之后才能生成最终的文件,FreeMarker的数据模型也是在模板中配置的。

ExampleResolution.java

[java]viewplaincopy

publicclassExampleResolution{

publicvoidresolution(){

Writerout=null;

/**

*创建Configuration对象

*设置模板文件的基路径

*设置读取模板的编码方式

*/

Configurationcfg=newConfiguration();

cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(),"TemplateFiles");

cfg.setDefaultEncoding("UTF-8");

/**

*创建FreeMarker的数据模型

*/

Maproot=newHashMap();

root.put("name","李鑫龙");

root.put("address","合肥市望江西路666号");

root.put("age",23);

/**

*设置生成的模板的位置

*合并数据模型与模板

*生成最终的html页面

*/

try{

Templatetemplate=cfg.getTemplate("Example.ftl");

Stringpath=ServletActionContext.getServletContext().getRealPath("/");

Filefile=newFile(path+"example.html");

out=newBufferedWriter(newOutputStreamWriter(newFileOutputStream(file)));

template.process(root,out);

}catch(IOExceptione){

e.printStackTrace();

}catch(TemplateExceptione){

e.printStackTrace();

}finally{

try{

out.flush();

out.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

}

4.Action配置

[java]viewplaincopy

publicclassServiceActionimplementsAction{

@Override

publicStringexecute()throwsException{

ExampleResolutioner=newExampleResolution();

er.resolution();

returnAction.SUCCESS;

}

}

5.struts.xml配置

[html]viewplaincopy

<packagenamepackagename="default"namespace="/"extends="struts-default,json-default">

<actionname="example"class="com.lubby.action.ServiceAction">

<resulttyperesulttype="redirect">/example.html</result>

</action>

</package>

6.效果显示

[html]viewplaincopy

</html>

<head>

<title>Example</title>

</head>

<body>

<h1>大家好,我的名字叫李鑫龙,我家住在合肥市望江西路666号,我今年23岁了!</h1>

</body>

</html>

四、FreeMarker的数据模型

数据模型是树型结构,可以任意复杂和深层次,如下面的例子:

[html]viewplaincopy

(root)

|

+-animals

||

|+-mouse

|||

||+-size="small"

|||

||+-price=50

||

|+-elephant

|||

||+-size="large"

|||

||+-price=5000

||

|+-python

||

|+-size="medium"

||

|+-price=4999

|

+-test="Itisatest"

|

+-whatnot

|

+-because="don'tknow"

类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字

类似于文件的变量称为scalars,保存单值

scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理)

对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price

另外一种变量是sequences,和hashes类似,只是不使用变量名字,而使用数字索引,如下面的例子:

[html]viewplaincopy

(root)

|

+-animals

||

|+-(1st)

|||

||+-name="mouse"

|||

||+-size="small"

|||

||+-price=50

||

|+-(2nd)

|||

||+-name="elephant"

|||

||+-size="large"

|||

||+-price=5000

||

|+-(3rd)

||

|+-name="python"

||

|+-size="medium"

||

|+-price=4999

|

+-whatnot

|

+-fruits

|

+-(1st)="orange"

|

+-(2nd)="banana"

这种对scalars的访问使用索引,如animals[0].name这种对scalars的访问使用索引,如animals[0].name

五、模板的常用指令

在FreeMarker模板中可以包括下面几个特定部分:

1.${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代。

1.1${name}可以取得root中key为name的value。

1.2${person.name}可以取得成员变量为person的name属性

2.<#…>:FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分

3.<@>:宏,自定义标签

4.注释:包含在<#--和-->(而不是<!--和-->)之间

六.常用的FTL标记:

1、if指令:用于判断的指令

<#if(2>3)>

二比三大

<#else>

三比二大

</#if>

2、list指令:用来遍历Map和List的

2.1遍历List的数据

<#listarrListasitem>

${item}

</#list>

2.2遍历Map的数据

<#listmyMap?keysasitem>

${item}-à${myMap[item]}

</#list>

2.3item_has_next:判断list是否还有值,

<#listarrListasitem>

<#ifitem_has_next>more,

<#else>end.

</#if>

</#list>

2.4<#break/>指令可以跳出循环

<#listarrListasitem>

<#if!item_has_nex>end.<#break/>

</#if>

more,

</#list>

3、include指令:用来引入另一个另一个ftl模板或者html页面

<#include“TemplateFiles/example.ftl”>

4、assign指令:用于为该模板页面创建或替换一个顶层变量

变量为String<#assignaddress=”上海”>

我家住在${address}

结果:我家住在上海

变量为map:<#assignperson={"name":"Tom","age":20,"address":"上海"}>

我的名字叫${person.name},我今年${person.age},我家住在${person.address}

结果:我的名字叫Tom,我今年20,我家住在上海

5、import指令:用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中。

<#import"/libs/mylib.ftl"asmy>

6.判断为空:FreeMarker默认是不允许值为空或者值不存在的,否则一定会报错。所以我们需要一些方法来判断是否为空或者是否存在

方法一:<h1>Welcome${user!"Anonymous"}!</h1>

当user为空或者不存在会默认为Anonymous.

${user!}这个当user不存在或为空时候,不会报错,也不会输出。

方法二:<#ifname??>nameisexist</#if>

这里会先判断,若name为空或不存在则不会执行if内部的,也不会报错

七、内建函数:

使用方法类似于访问散列的子变量,只是使用?代替.例如:${test?upper_case?html}常用的内建函数列举如下:

?html:html字符转义

?cap_first:字符串的第一个字母变为大写形式

?lower_case:字符串的小写形式

?upper_case:字符串的大写形式

?trim:去掉字符串首尾的空格

?substring:截字符串

?lenth:取长度

?size:序列中元素的个数

?int:数字的整数部分(比如-1.9?int就是-1)

?replace:字符串替换

一些示例:

${username?[0,10]}

${appHtml?replace('<@person.component/>',"AK47test")}

八、FreeMarkermacro(宏)的使用

1.example1.ftl设置宏

<#macroname>

我的名字叫做${name}!

</#macro>

2.example2.ftl调用example1.ftl的宏

<#inclue“example1.ftl”>

<#macroname=”王晓乐”></#macro>

最终可以在example2.ftl模板生成的页面中得到

我的名字叫做王晓乐!

3.关于关于嵌套指令<#nested>

<#macrogreet>

<#nested>

<#nested>

</#macro>

调用:<@greet>hello!</@greet>

结果:hello!

hello!

九、通过Struts2设置type来访问FreeMarker模板

1.WEB-INF/TemplateFiles/example.ftl模板文件

[html]viewplaincopy

<spanstyle="white-space:pre"></span><html>

<head>

<title>这是一个Example</title>

</head>

<body>

大家好,我的名字叫王媛媛!

</body>

</html>

2.action配置

[java]viewplaincopy

publicStringexample()throwsException{

System.out.println("exampleisrequested.....");

ActionContext.getContext().getSession().put("name","刘德华");

returnAction.SUCCESS;

}

3.struts.xml配置result的type要设置为freeMarker

[java]viewplaincopy

<actionname="*"class="com.lubby.action.ServiceAction"method="{1}">

<resulttype="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>

</action>

3.struts.xml配置result的type要设置为freeMarker

[java]viewplaincopy

<actionname="*"class="com.lubby.action.ServiceAction"method="{1}">

<resulttype="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>

</action>

<actionname="*"class="com.lubby.action.ServiceAction"method="{1}">

<resulttype="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>

</action>

4.效果显示(通过session把值传进去)

5.使用type=“freemarker”与第一个demo的区别:

第一个demo是先在action中调用解析方法生成一个html页面,然后跳转到这个生成的htm页面。那么以后访问的话只需要直接访问这个已经生成的html,无需解析,访问速度回非常快。而使用struts2自带的解析,每次访问action都重新生成一个html页面然后传回浏览器。

前者访问的速度非常快,适合数据刷新频率不高的地方。后者的访问速度略逊于前者,适合数据刷新频率高的地方。

十、利用macro简单封装的jqGrid的使用方法

1.macro名和参数的调用Demo

<@myjqgridurl="jqgridtest.action"colNameList=["来电号码","业务类型","编号"]colModelList=[["customer","string"],["bussiness","string"],["id","int"]]caption="jqgrid测试三"width="500"height="250"divid="jqgridOne"/>

2.参数的含义

url:请求的action的URL

colNameList:jqGrid表所需要显示的字段

colModelList:jqGrid中colModelList中的字段的英文名,和排序的类型

caption:表格的标题名

width:长度

height:高度

divId:div的id名

十一、利用macro简单封装的highcharts的使用方法

1.macro名和参数的调用Demo

<@highchartsdivid="container1"type="column"title="2012年气温变化表一"subtitle="合肥气象局提供"ytitle="温度(°C)"function="return'<b>'+this.series.name+'</b><br/>'+this.x+':'+this.y+'°C';"width="500"height="300"/>

2.参数的含义

divId:div的id名

type:图表的类型/line直线/pie饼状/bar横向条状/column柱状图

title:图表的标题

subtitle:图表的副标题

yTitle:纵坐标的标题

function:当鼠标移到节点时,返回的信息

width:宽度

height:高度

(本文乃是原创,作者是Lubby,转载请说明来源,谢谢!)

相关推荐