FreeMarker教程
一、什么是模板引擎,为什么要用模板引擎
在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面、风格、布局、效果等等可视元素;而程序员则忙于创建程式的商业流程,生成设计页面要显示的数据等等。
很多时候,要显示的资料在设计的时候并不存在,它们一般是在运行时由程式产生的,比如执行“价格不高于800NT的USB Disk”查询的返回结果。这种技术需求产生了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>
<head>
<title>Example</title>
</head>
<body >
<h1>大家好,我的名字叫${name},我家住在${address},我今年${age}岁了!</h1>
</body>
</html>
3.模板的解析
模板需要被解析之后才能生成最终的文件,FreeMarker的数据模型也是在模板中配置的。
ExampleResolution.java
publicclass ExampleResolution {
publicvoid resolution(){
Writer out = null;
/**
*创建Configuration对象
*设置模板文件的基路径
*设置读取模板的编码方式
*/
Configuration cfg = new Configuration();
cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(),"TemplateFiles");
cfg.setDefaultEncoding("UTF-8");
/**
*创建FreeMarker的数据模型
*/
Map root = newHashMap();
root.put("name","李鑫龙");
root.put("address","合肥市望江西路666号");
root.put("age", 23);
/**
*设置生成的模板的位置
*合并数据模型与模板
*生成最终的html页面
*/
try {
Template template = cfg.getTemplate("Example.ftl");
String path = ServletActionContext.getServletContext().getRealPath("/");
File file = new File(path +"example.html");
out = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(file)));
template.process(root, out);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}finally{
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.Action配置
publicclass ServiceActionimplements Action {
@Override
public String execute()throws Exception {
ExampleResolution er = new ExampleResolution();
er.resolution();
return Action.SUCCESS;
}
}
5.struts.xml配置
<packagename="default" namespace="/"extends="struts-default,json-default">
<action name="example"class="com.lubby.action.ServiceAction">
<resulttype="redirect">/example.html</result>
</action>
</package>
6.效果显示
</html>
<head>
<title>Example</title>
</head>
<body >
<h1>大家好,我的名字叫李鑫龙,我家住在合肥市望江西路666号,我今年23岁了!</h1>
</body>
</html>
四、FreeMarker的数据模型
数据模型是树型结构,可以任意复杂和深层次,如下面的例子:
(root)
|
+- animals
| |
| +- mouse
| | |
| | +-size = "small"
| | |
| | +-price = 50
| |
| +- elephant
| | |
| | +-size = "large"
| | |
| | +-price = 5000
| |
| +- python
| |
| +- size = "medium"
| |
| +- price = 4999
|
+- test ="It is a test"
|
+- whatnot
|
+-because = "don't know"
类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字
类似于文件的变量称为scalars,保存单值
scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理)
对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price
(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
另外一种变量是sequences,和hashes类似,只是不使用变量名字,而使用数字索引,如下面的例子:
五、模板的常用指令
在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的数据
<#list arrList as item> ${item} </#list>
2.2遍历Map的数据
<#listmyMap?keys as item> ${item}-${myMap[item]} </#list>
2.3 item_has_next:判断list是否还有值,
<#listarrList as item> <#if item_has_next>more, <#else>end. </#if> </#list>
2.4<#break />指令可以跳出循环
<#listarrList as item> <#if!item_has_nex>end. <#break /> </#if> more, </#list>
3、include指令:用来引入另一个另一个ftl模板或者html页面
<#include“TemplateFiles/example.ftl”>
4、assign指令:用于为该模板页面创建或替换一个顶层变量
变量为String <#assign address=”上海”> 我家住在${address} 结果: 我家住在上海 变量为map: <#assign person={"name":"Tom","age":20,"address":"上海"} > 我的名字叫${person.name},我今年${person.age},我家住在${person.address} 结果:我的名字叫Tom,我今年20,我家住在上海
5、import指令:用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中。
<#import "/libs/mylib.ftl"as my>
6.判断为空: FreeMarker默认是不允许值为空或者值不存在的,否则一定会报错。所以我们需要一些方法来判断是否为空或者是否存在
方法一:<h1>Welcome${user!"Anonymous"}!</h1>
当user为空或者不存在会默认为Anonymous.
${user!}这个当user不存在或为空时候,不会报错,也不会输出。
方法二:<#if name??>name is exist</#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")}
八、FreeMarker macro(宏)的使用
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模板文件
<span style="white-space:pre"> </span><html>
<head>
<title>这是一个Example</title>
</head>
<body>
大家好,我的名字叫王媛媛!
</body>
</html>
2.action配置
public String example() throws Exception {
System.out.println("example is requested.....");
ActionContext.getContext().getSession().put("name", "刘德华");
return Action.SUCCESS;
}
3.struts.xml配置 result的type要设置为freeMarker
<action name="*" class="com.lubby.action.ServiceAction" method="{1}">
<result type="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>
</action>
3.struts.xml配置 result的type要设置为freeMarker
<action name="*" class="com.lubby.action.ServiceAction" method="{1}">
<result type="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>
</action>
<action name="*" class="com.lubby.action.ServiceAction" method="{1}">
<result type="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
<@myjqgrid url="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
<@highcharts divId="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:高度
本文转自:http://blog.csdn.net/liu00614/article/details/8541193
FreeMarker教程的更多相关文章
- FreeMarker 教程整理
Freemarker新手教程 http://blog.csdn.net/qq_23994787/article/details/77506980 FreeMarker教程整理 http://blo ...
- 转:一篇很全面的freemarker教程
最近在使用freemarker,于是在网上找了一些教程学习,如下: 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组 ...
- [转]一篇很全面的freemarker教程
copy自http://demojava.iteye.com/blog/800204 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...
- 一篇很全面的freemarker教程
以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:1,文本:直接输出的部分2,注释:<#-- ... --& ...
- 【转】一篇很全面的freemarker教程---有空慢慢实践
FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:<#-- ... -->格式部分,不会输 ...
- 一篇非常全面的freemarker教程
copy自http://demojava.iteye.com/blog/800204 下面内容所有是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...
- 一篇很全面的freemarker教程 前端工程师必备
FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:<#-- ... -->格式部分,不会输 ...
- [转载] FreeMarker教程
转载自http://www.blogjava.net/freeman1984/archive/2010/11/04/337239.html FreeMarker是一个模板引擎,一个基于模板生成文本输出 ...
- Freemarker教程1(基本使用)
简介 FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是 ...
随机推荐
- 创建一个最简单的Linux随机启动服务
转自: http://xiaoxia.org/2011/11/15/create-a-simple-linux-daemon/
- calico for kubernetes
(这一篇中很多错误,勿参考!) The reference urls: https://github.com/kubernetes/kubernetes/blob/master/docs/gettin ...
- 【OpenStack】OpenStack系列5之Cinder详解
源码下载安装 git clone -b stable/icehouse https://github.com/openstack/cinder.git pip install -r requireme ...
- Search Range in Binary Search Tree
Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find all t ...
- Android app主线程UI更新间歇性崩溃的问题
对App进行开发测试时,偶尔出现app崩溃的问题.日志如下: 10-25 18:44:52.935 15290-15290/com.zzq.cnblogs E/AndroidRuntime﹕ FATA ...
- Java for LeetCode 057 Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- Greedy:Fence Repair(POJ 3252)
Fence Repair 问题大意:农夫约翰为了修理栅栏,要将一块很长的木块切割成N块,准备切成的木板的长度为L1,L2...LN,未切割前的木板的长度恰好为切割后木板的长度的总和,每次切断木板的时候 ...
- 【数据结构】Huffman树
参照书上写的Huffman树的代码 结构用的是线性存储的结构 不是二叉链表 里面要用到查找最小和第二小 理论上锦标赛法比较好 但是实现好麻烦啊 考虑到数据量不是很大 就直接用比较笨的先找最小 去掉最小 ...
- Binary Search--二分查找
Binary Search--二分查找 采用二分法查找时,数据需是排好序的. 基本思想:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功:若x小于当前位 ...
- GCM 发送接收消息 Message Client Server 服务器端,客户端
GCM 传递参数 最近用了很多时间做GCM,由于碰到很多问题,因此详细做一下记录,以方便各位网友,不用再走我的重复的路.不过我试了一下GCM在国内很不好用.假如开发国外的程序的话,用GCM倒是很不错的 ...