FreeMarker简易教程

最近项目用到FreeMarker,在网上学习一番,遂把它整理之!

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

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

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

  1. 将逻辑和表现混合在一起。
  2. 破坏了美工和程序员职责的正常分解。
  3. 使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] view plaincopy

  1. <html>
  2. <head>
  3. <title>Example</title>
  4. </head>
  5. <body >
  6. <h1>大家好,我的名字叫${name},我家住在${address},我今年${age}岁了!</h1>
  7. </body>
  8. </html>

3.模板的解析

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

ExampleResolution.java

[java] view plaincopy

  1. publicclass ExampleResolution {
  2. publicvoid resolution(){
  3. Writer out = null;
  4. /**
  5. *创建Configuration对象
  6. *设置模板文件的基路径
  7. *设置读取模板的编码方式
  8. */
  9. Configuration cfg = new Configuration();
  10. cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(),"TemplateFiles");
  11. cfg.setDefaultEncoding("UTF-8");
  12. /**
  13. *创建FreeMarker的数据模型
  14. */
  15. Map root = newHashMap();
  16. root.put("name","李鑫龙");
  17. root.put("address","合肥市望江西路666号");
  18. root.put("age", 23);
  19. /**
  20. *设置生成的模板的位置
  21. *合并数据模型与模板
  22. *生成最终的html页面
  23. */
  24. try {
  25. Template template = cfg.getTemplate("Example.ftl");
  26. String path = ServletActionContext.getServletContext().getRealPath("/");
  27. File file = new File(path +"example.html");
  28. out = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(file)));
  29. template.process(root, out);
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. } catch (TemplateException e) {
  33. e.printStackTrace();
  34. }finally{
  35. try {
  36. out.flush();
  37. out.close();
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  43. }

4.Action配置

[java] view plaincopy

  1. publicclass ServiceActionimplements Action {
  2. @Override
  3. public String execute()throws Exception {
  4. ExampleResolution er = new ExampleResolution();
  5. er.resolution();
  6. return Action.SUCCESS;
  7. }
  8. }

5.struts.xml配置

[html] view plaincopy

  1. <packagenamepackagename="default" namespace="/"extends="struts-default,json-default">
  2. <action name="example"class="com.lubby.action.ServiceAction">
  3. <resulttyperesulttype="redirect">/example.html</result>
  4. </action>
  5. </package>

6.效果显示

[html] view plaincopy

  1. </html>
  2. <head>
  3. <title>Example</title>
  4. </head>
  5. <body >
  6. <h1>大家好,我的名字叫李鑫龙,我家住在合肥市望江西路666号,我今年23岁了!</h1>
  7. </body>
  8. </html>

四、FreeMarker的数据模型

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

[html] view plaincopy

  1. (root)
  2. |
  3. +- animals
  4. |   |
  5. |   +- mouse
  6. |   |  |
  7. |   |   +-size = "small"
  8. |   |  |
  9. |   |   +-price = 50
  10. |   |
  11. |   +- elephant
  12. |   |  |
  13. |   |   +-size = "large"
  14. |   |  |
  15. |   |   +-price = 5000
  16. |   |
  17. |   +- python
  18. |       |
  19. |       +- size = "medium"
  20. |       |
  21. |       +- price = 4999
  22. |
  23. +- test ="It is a test"
  24. |
  25. +- whatnot
  26. |
  27. +-because = "don‘t know"

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

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

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

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

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

[html] view plaincopy

  1. (root)
  2. |
  3. +- animals
  4. |   |
  5. |   +- (1st)
  6. |   |   |
  7. |   |   +-name = "mouse"
  8. |   |   |
  9. |   |   +-size = "small"
  10. |   |   |
  11. |   |   +-price = 50
  12. |   |
  13. |   +- (2nd)
  14. |   |   |
  15. |   |   +-name = "elephant"
  16. |   |   |
  17. |   |   +-size = "large"
  18. |   |   |
  19. |   |   +-price = 5000
  20. |   |
  21. |   +- (3rd)
  22. |       |
  23. |       +- name = "python"
  24. |       |
  25. |       +- size = "medium"
  26. |       |
  27. |       +- price = 4999
  28. |
  29. +- whatnot
  30. |
  31. +- fruits
  32. |
  33. +- (1st)= "orange"
  34. |
  35. +- (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的数据

<#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模板文件

[html] view plaincopy

  1. <span style="white-space:pre">  </span><html>
  2. <head>
  3. <title>这是一个Example</title>
  4. </head>
  5. <body>
  6. 大家好,我的名字叫王媛媛!
  7. </body>
  8. </html>

2.action配置

[java] view plaincopy

  1. public String example() throws Exception {
  2. System.out.println("example is requested.....");
  3. ActionContext.getContext().getSession().put("name", "刘德华");
  4. return Action.SUCCESS;
  5. }

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

[java] view plaincopy

  1. <action name="*" class="com.lubby.action.ServiceAction" method="{1}">
  2. <result type="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>
  3. </action>

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

[java] view plaincopy

  1. <action name="*" class="com.lubby.action.ServiceAction" method="{1}">
  2. <result type="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>
  3. </action>
  4. <action name="*" class="com.lubby.action.ServiceAction" method="{1}">
  5. <result type="freemarker">/WEB-INF/TemplateFiles/{1}.ftl</result>
  6. </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名

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

十一、利用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:高度

时间: 2024-08-30 07:47:38

FreeMarker简易教程的相关文章

BIND简易教程(1):安装及基本配置

首先,为什么说是简易教程呢?因为BIND的功能实在太多,全写出来的话要连载好久,我觉得我没有那么多精力去写:而我了解的仅仅是有限的一点点,不敢造次.百度上的文章也是一抓一大把呐!所以,教点基本使用方法,有需求的同学可以再翻翻BIND管理员手册.那么,还是直接开始说正题吧.本次还是像PowerDNS一样是一个连载,写三篇. 目录:BIND简易教程(1):安装及基本配置(本篇)BIND简易教程(2):BIND视图配置(待续)BIND简易教程(3):DNSSec配置(待续) 首先说说安装.安装是非常简

Emacs简易教程

Emacs简易教程阅读: 命令: $emacs 进入之后,输入: C-h t 这里,C-h表示按住[Ctrl]键的同时按h ####### 20090620 *退出: 输入“C-x C-c” *撤销: 输入"C-x u" 或输入"C-_" 这里,"C-_"比较好输入一些(好像C--也行),但是有的键盘上面没有"_"就只能输入“C-x u”了,撤销动作能进行20次. *向上翻页: 输入"M-v" 这里,右手的

CCS2.2基于软件仿真简易教程(汇编)

CCS2.2基于软件仿真简易教程(汇编) Rev 1.0 Writer Nirvana Silence 配置目标芯片 打开此图标 导入配置,生成gel文件,导入点击close 然后关闭 保存changes 启动工程软件 新建工程.asm文件,添加到工程 新建文件 保存为汇编格式 添加到工程 编写程序,编译程序,load程序 在新建的ASM文件中输入以下程序,查看运行后(1030H).(1040H).*AR3,AR4的值 记得助记符前面至少要有一个空格 编译 没有问题,load .out文件 打开

getopts简易教程(Small getopts tutorial)译文(未完成)

getopts简易教程 当你想用一种专业的方式解析命令行参数时,getopts就是要选择的工具.和它的旧版本兄弟命令getopt不同(注意没有s!),getopts是shell内置命令.高级地方表现在 你不需要通过一个外部命令传递参数 getopts可以很容易的设置一些你能用于解析参数的变量(对于一个外部程序来说这是不可能的!) 你不必再处理过去一些使用getopt时的一些bug实现(空格, -) getopts已经在POSIX?定义 一些其他解析位置参数的其他方法(不用getopt(s))在这

Android实战简易教程-第四十枪(窃听风云之短信监听)

近期在做监听验证码短信自己主动填入的功能,无意间想到了一个短信监听的办法. 免责声明:短信监听本身是一种违法行为,这里仅仅是技术描写叙述.请大家学习技术就可以.(哈哈) 本实例是基于bmob提供的后台服务,将监听到的短信自己主动上传到bmob数据库中. 一.代码实现: 1.首先实现javabean对象. package com.example.messagecut; import cn.bmob.v3.BmobObject; public class MsgContent extends Bmo

移动开发之【微信小程序】的原理与权限问题以及相关的简易教程

这几天圈子里到处都在传播着这样一个东西,微信公众平台提供了一种新的开放能力,开发者可以快速开发一个小程序,取名曰:微信公众平台-小程序 据说取代移动开发安卓和苹果,那这个东东究竟是干吗用的?但很多人觉得是网页版应用. 有的人很鸡冻,但是--最后文章会提及具体的权限开放问题,所以,还是保持一颗冷静的?比较好. 那我们先来看看组件和API开放了哪些服务: 视图容器:视图(View).滚动视图.Swiper 基础内容:图标.文本.进度条 表单组件:按钮.表单等等 操作反馈 导航 媒体组建:音频.图片.

BIND简易教程(2):BIND视图配置

目录:BIND简易教程(1):安装及基本配置BIND简易教程(2):BIND视图配置(本篇)BIND简易教程(3):DNSSec配置 上文书说到,我们把aaa.apple.tree解析到192.168.4.100.那么世界上任何一个人在请求aaa.apple.tree的时候,解析到的都是这个IP地址,之后,再访问这个域名(当然这个IP地址只是实验的,而且我域名也没注册,除了我内网之外,世界上任何一个人都访问不到).那么问题来了,两个人一个在电信,一个在联通,都想访问这个域名的话,我的服务器要放在

BIND简易教程(3):DNSSec配置

目录:BIND简易教程(1):安装及基本配置BIND简易教程(2):BIND视图配置BIND简易教程(3):DNSSec配置 (本篇) DNSSec,有个半英半中的名字叫DNS安全扩展.说的好听一点,它是对域名进行签名认证,保证域名的完整性和正确性,不会被修改.DNSSec不能防御对DNS服务器的攻击,也不会对请求和应答的数据进行加密,甚至如果你不知道DNSSec这个东西的话,域名是不是完整正确的你也不知道. 实际上,给我的感觉就是,DNSSec是在花很大的力气去配置一个不怎么有用的东西.然并卵

BIND简易教程(0):在Ubuntu下源码安装BIND(其实跟前面的教程没太大关系)

之前介绍过BIND的基本使用啦.关于BIND的入门级使用方法见:http://www.cnblogs.com/anpengapple/p/5877661.html简易教程系列,本篇只讲BIND安装. 本来源码安装不想介绍了,但是最近重装的时候,还是爆出来好多问题.唉,apt方式装习惯了,生成配置文件的脚本都是按照apt的目录和用户来的,源码方式有些坑.所以,还是介绍一下吧(有些部分是直接照前面扒下来的). 首先,因为需要开启DNSSec,所以必须要安装openssl.如果不需要装,或者已经安装好