FreeMarker (使用方法)


FreeMarker FreeMarker FreeMarker FreeMarker 概述和特性 FreeMarkerFreeMarkerFreeMarker FreeMarker 概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写 FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序 虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker 生成页面,通过模板显示准备的数据(如下图) FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件 FreeMarker与容器无关,因为它并不知道 HTTP或Servlet;FreeMarker同样可以应用于非 Web应用程序环境 FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用 JSP 标记库 FreeMarker是免费的 111 1 、通用目标 能够生成各种文本:HTML、XML 、RTF、Java源代码等等 易于嵌入到你的产品中:轻量级;不需要Servlet环境 插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等 你可以按你所需生成文本:保存到本地文件;作为Email发送;从Web应用程序发送它返回 给Web浏览器 222 2 、强大的模板语言 所有常用的指令:include、if/elseif/else、循环结构 在模板中创建和改变变量 几乎在任何地方都可以使用复杂表达式来指定值 命名的宏,可以具有位置参数和嵌套内容 名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心 名字冲突 输出转换块:在嵌套模板片段生成输出时,转换 HTML转义、压缩、语法高亮等等; 你可以定义自己的换 333 3 、通用数据模型 FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在 模板中显示 你可以使用抽象(接口)方式表示对象(JavaBean、XML 文档、SQL查询结果集等等 ), 告诉模板开发者使用方法,使其不受技术细节的打扰 444 4 、为WebWebWeb Web 准备 在模板语言中内建处理典型Web相关任务(如HTML转义)的结构 能够集成到Model2 Web应用框架中作为JSP的替代 支持JSP标记库 为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员 555 5 、智能的国际化和本地化 字符集智能化(内部使用UNICODE) 数字格式本地化敏感 日期和时间格式本地化敏感 非US字符集可以用作标识(如变量名) 多种不同语言的相同模板 666 6 、强大的XMLXMLXML XML 处理能力 <#recurse> 和<#visit>指令(2.3版本)用于递归遍历XML 树 在模板中清楚和直觉的访问XML 对象模型 Eclipse下编辑 FreeMarker的插件 FreeMarker(http://freemarker.sourceforge.net/) 是一个非常优秀的模板引擎,一个用来根据模 板生成文本输出的通用工具,我们可以用它来生成例如HTML这样的文本,FreeMarker本身 提供了一个Eclipse的插件用于编写FreeMarker模板文件,这个插件主要是提供了语法高亮、 语法错误提示以及模板文件的概要信息,下图是该插件工作的截图: 接下来把安装过程大略的介绍一下:( Eclipse 3.x ) 打开菜单项 HelpHelpHelp Help -> SoftwareSoftwareSoftware Software updatesupdatesupdates updates -> FindFindFind Find andandand and install...install...install... install... . 选择单选项 "Search for new features to install". 点击 AddAddAdd Add UpdateUpdateUpdate Update Site...Site...Site... Site... , 输入 "FreeMarker""FreeMarker""FreeMarker" "FreeMarker" 作为名字以及 "http://www.freemarker.org/eclipse/update""http://www.freemarker.org/eclipse/update""http://www.freemarker.org/eclipse/update" "http://www.freemarker.org/eclipse/update" 作为更新的地址 选中复选框 "FreeMarker" 点击下一步或完成按钮根据提示完成插件的安装 安装完毕后该插件自动关联*.ftl文件,你也可以在下面对话框中进行自行设置 网址: FreeMarker的官方主页: http://freemarker.sourceforge.net/ 下载地址:http://sourceforge.net/projects/freemarker 使用FreeMarker生成Html静态文件(实例) 以下是我在生成新闻的静态文件时用到的代码.仅供参考.请根据实际情况修改. 模板::: : 查看文章: ${newsitem.title}
${newsitem.title} ( ${newsitem.addtime} ) 返回         

${newsitem.showContent}

代码::: : importimportimport import java.io.*; importimportimport import java.util.HashMap; importimportimport import java.util.Map; importimportimport import org.apache.commons.logging.Log; importimportimport import org.apache.commons.logging.LogFactory; importimportimport import freemarker.template.*; /* * Created on 2005-4-7 * */ /** * 测试FreeMarker. * *@author@author@author @author scud * */ publicpublicpublic public classclassclass class FreeMarkerTest { privateprivateprivate private finalfinalfinal final Log logger = LogFactory.getLog(getClass()); privateprivateprivate private Configuration freemarker_cfg = nullnullnull null ; publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { //@todo@todo@todo @todo 自己的一个类 NewsItem aItem = nullnullnull null ; //@todo@todo@todo @todo 装入新闻 //NewsItem = loadNewsItem(1); FreeMarkerTest test = newnewnew new FreeMarkerTest(); Map root = newnewnew new HashMap(); root.put("newsitem", aItem); String sGeneFilePath = "/tpxw/"; String sFileName = "1.htm"; booleanbooleanboolean boolean bOK = test.geneHtmlFile("/tpxw/view.ftl",root, sGeneFilePath,sFileName); } /** * 获取freemarker 的配置. freemarker 本身支持classpath, 目录和从 ServletContext获取. */ protectedprotectedprotected protected Configuration getFreeMarkerCFG() { ififif if (nullnullnull null == freemarker_cfg) { // Initialize the FreeMarker configuration; //- Create a configuration instance freemarker_cfg = newnewnew new Configuration(); //- FreeMarker支持多种模板装载方式,可以查看API文档,都很简单:路径, 根据Servlet上下文,classpath等等 //htmlskin是放在classpath下的一个目录 freemarker_cfg.setClassForTemplateLoading(thisthisthis this .getClass(), "/htmlskin"); } returnreturnreturn return freemarker_cfg; } /** * 生成静态文件. * *@param@param@param @param templateFileName 模板文件名,相对htmlskin 路径,例如 "/tpxw/view.ftl" *@param@param@param @param propMap 用于处理模板的属性Object映射 *@param@param@param @param htmlFilePath 要生成的静态文件的路径 ,相对设置中的根路径 ,例如 "/tpxw/1/2005/4/" *@param@param@param @param htmlFileName 要生成的文件名,例如 "1.htm" */ publicpublicpublic public booleanbooleanboolean boolean geneHtmlFile(String templateFileName,Map propMap, String htmlFilePath,String htmlFileName ) { //@todo@todo@todo @todo 从配置中取得要静态文件存放的根路径 :需要改为自己的属性类调 用 String sRootDir = "e:/webtest/htmlfile" ; trytrytry try { Template t = getFreeMarkerCFG().getTemplate(templateFileName); //如果根路径存在,则递归创建子目录 creatDirs(sRootDir,htmlFilePath); File afile = newnewnew new File(sRootDir +"/" +htmlFilePath + "/" + htmlFileName); Writer out = newnewnew new BufferedWriter(newnewnew new OutputStreamWriter(newnewnew new FileOutputStream(afile))); t.process(propMap, out); } catchcatchcatch catch (TemplateException e) { logger.error("Error while processing FreeMarker template " + templateFileName,e); returnreturnreturn return falsefalsefalse false ; } catchcatchcatch catch (IOException e) { logger.error("Error while generate Static Html File " + htmlFileName,e); returnreturnreturn return falsefalsefalse false ; } returnreturnreturn return truetruetrue true ; } /** * 创建多级目录 * *@param@param@param @param aParentDir String *@param@param@param @param aSubDir 以 / 开头 *@return@return@return @return boolean 是否成功 */ publicpublicpublic public staticstaticstatic static booleanbooleanboolean boolean creatDirs(String aParentDir, String aSubDir) { File aFile = newnewnew new File(aParentDir); ififif if (aFile.exists()) { File aSubFile = newnewnew new File(aParentDir + aSubDir); ififif if (!aSubFile.exists()) { returnreturnreturn return aSubFile.mkdirs(); } elseelseelse else { returnreturnreturn return truetruetrue true ; } } elseelseelse else { returnreturnreturn return falsefalsefalse false ; } } } 学习FreeMarker FreeMarker是一个用Java编写的模板引擎,主要用来生成HTML Web页面,特别是基于MVC 模式的应用程序。虽然FreeMarker具有一些编程的能力,但不像PHP,通常由Java程序准备 要显示的数据,由FreeMarker模板生成页面。 FreeMarker可以作为Web应用框架一个组件, 但它与容器无关,在非Web应用程序环境也能工作的很好。 FreeMarker适合作为MVC的视 图组件,还能在模板中使用JSP标记库。 Welcome!

Welcome ${user}!

Our latest product: ${latestProduct.name}! 上面的例子中,在简单的HTML中加入了一些由${…}包围的特定FreeMarker的指令,这个文 件就称为模板了。而user、latestProduct.url和latestProduct.name来自于数据模型,由Java程序 提供,模板设计者就不用关心数据从哪来的。 FreeMarker模板中可以包括下面四种特定部分: 一.) 文本:直接输出 二.)FTLFTLFTL FTL 标记(FreeMarker模板语言标记):类似于HTML标记,名字前加#(有些以@开始,用 户自定义标记)予以区分,不会输出。 字符串- 使用单引号或双引号限定;如果包含特殊字符需要转义符: ${"It's \"quoted\" andthis is a backslash: \\"} 有一类特殊的字符串:${r"C:\f oo\bar"},输出结构为:C:\foo\bar,在引号前面加r被认为是纯 文本。 数字-直接输入,不需要引号。${08}, ${+8}, ${8.00} and ${8} 都是相同的 布尔值-true和false,不使用引号 Sequences(Sequences(Sequences( Sequences( 序列))) ) -由逗号分隔的变量列表,由方括号限定,类似java中的一维数组: <#list ["winter", "spring", "summer", "autumn"] as x> ${x} 输出结果: winter spring summer autumn 例二:[2 + 2, [1, 2, 3, 4], "whatnot"] 例三:2..5,等同于[2, 3, 4, 5];5..2,等同于[5,4,3,2]。注意方括号是不需要的。 Hashes(Hashes(Hashes( Hashes( 散列))) ) -由逗号分隔的键 -值列表,由大括号限定,键和值之间用冒号分隔: {"name":"green mouse", "price":150},键和值都是表达式,但是键必须是字符串。 获取变量-${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数 字开头。下列表达式是等价的: book.author.name book["author"].name book.author.["name"] book["author"]["name"] 获取Sequence(序列)片断-使用 [startindex..endindex] ,例如: seq中存储了 "a", "b", "c", "d","e",那么seq[1..2]包含了b和c两个值。 可以使用.variablename语法访问FreeMarker内置变量。 字符串操作 {"Hello ${user}!"} <==> ${"Hello " + user + "!"} ${"${user}${user}${user}${user}"} <==> ${user + user + user + user} ${…}只能在文本中使用,下面是错误的代码: <#if ${isBig}>Wow! <#if "${isBig}">Wow! //此处的代码也是错误的,因为if指令需要的是boolean,实际的 却是个字符串 子字符串的操作,假设user的值为"Big Joe": ${user[0]}${user[4]} <==> BJ ${user[1..4]} <==> ig J Sequences(Sequences(Sequences( Sequences( 序列))) ) 操作 <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user> - ${user} 结果: - Joe - Fred - Julia - Kate Hashes(Hashes(Hashes( Hashes( 散列))) ) 操作 <#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}> - Joe is ${ages.Joe} - Fred is ${ages.Fred} - Julia is ${ages.Julia} 结果: - Joe is 30 - Fred is 25 - Julia is 18 算术运算 <#-- x的值设定为5 --> ${x * x - 100} ${x / 2} ${12 % 10} 结果: -75 2.5 2 注意: 操作符两边必须是数字;使用"+"时,如果一边是数字,一边是字符串,就会自动将 数字转换为字符串。 使用内建的指令int获得整数部分: ${(x/2)?int} ${1.1?int} ${1.999?int} ${-1.1?int} ${-1.999?int} 结果: 2 1 1 -1 -1 比较操作符-<#if expression>... 1.)使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等 2.)=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误 3.)Freemarker是精确比较,所以"x"、"x "和"X"是不相等的 4.)对数字和日期可以使用<、<=、>和>=,但不能用于字符串 5.)由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免 这种情况,例如<#if (x > y)>,另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、> 和>= 逻辑操作符-&&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误 <#if x < 12 && color = "green"> We have less than 12 things, and they are green. <#if !hot> <#-- here hot must be a boolean --> It's not hot. 内置函数-用法类似访问hash(散列)的子变量,只是使用"?"替代".",例如 :user?upper_case 下面列出常用的一些函数: 对于字符串 html-对字符串进行HTML编码 cap_first-使字符串第一个字母大写 lower_case-将字符串转换成小写 trim-去掉字符串前后的空白字符 对于Sequences(序列) size-获得序列中元素的数目 对于数字 int-取得数字的整数部分(如-1.9?int的结果是-1) 例一: <#-- test的值为Tom & Jerry --> ${test?html} ${test?upper_case?html} 结果: Tom & Jerry TOM& JERRY 例二: <#-- seasons的值为"winter", "spring", "summer", "autumn" --> ${seasons?size} ${seasons[1]?cap_first} <#-- left side can by any expression --> ${"horse"?cap_first} 结果: 4 Spring Horse 方法的调用 ${repeat("What", 3)} ${repeat(repeat("x", 2), 3) + repeat("What", 4)?upper_case} 结果: WhatWhatWhat xxxxxxWHATWHATWHATWHAT 操作符优先顺序 后缀 [subvarName] [subStringRange] .(methodParams) 一元 +expr、-expr、! 内建 ? 乘法 *、/、% 加法 +、- 关系 <、>、<=、>=(lt、lte、gt、gte) 相等 =、!= 逻辑 && 逻辑 || 数字范围 .. 三.) InterpolationInterpolationInterpolation Interpolation :由${...}或#{...}两种类型,输出计算值,可以定义输出的格式 例一: <#setting number_format="currency"/> <#assign answer=42/> ${answer} ${answer?string} <#-- the same as ${answer} --> ${answer?string.number} ${answer?string.currency} ${answer?string.percent} 结果: $42.00 $42.00 42 $42.00 4,200% 例二: ${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")} ${lastUpdated?string("EEE, MMM d, ''yy")} ${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")} 结果: 2003-04-08 21:24:44 Pacific Daylight Time Tue, Apr 8, '03 Tuesday, April 08, 2003, 09:24:44 PM(PDT) 例三: <#assign foo=true/> ${foo?string("yes", "no")} 结果: yes 例四: <#-- x is 2.582 and y is 4 --> #{x; M2} <#-- 2.58 --> #{y; M2} <#-- 4 --> #{x; m1} <#-- 2.6 --> #{y; m1} <#-- 4.0 --> #{x; m1M2} <#-- 2.58 --> #{y; m1M2} <#-- 4.0 --> 说明:mX-小数部分最小X位;MX-小数部分最大X位。 四.) 注释:<#--和--> 下面是一个常用的模板例子:

We have these animals:

NamePrice <#list animals as being>
<#if being.size = "large"> ${being.name} <#if being.size="large"> ${being.price} Euros
<#include "/copyright_footer.html"> 注意点: 1.) FreeMarker是区分大小写的; 2.) FTL标记不能位于另一个FTL标记内部,例如:<#if <#include 'foo'>='bar'>...; 3.) ${…}只能在文本中使用; 4.) 多余的空白字符会在模板输出时去除; 5.) 如果使用的指令不存在,会产生一个错误消息。 webwork+freemarker webwork+freemarker webwork+freemarker webwork+freemarker 轻松实现 Rss,AtomRss,AtomRss,Atom Rss,Atom Rss,Atom,已经是Web2.0的基本特征,今天终于有时间决定实现一下。对于动态的Rss, Atom其实就是选取最新的内容,迭迨一下生成一个固定格式的xml文件就可以了。其实也很 简单。 我用webwork2,用freemarker做模版,在网上找了一个标准的Rss2.0格式就生成我的 模版文件rss.ftl http://www.86oo.com <![CDATA[我的小站]]> http://leaf.jdk.cn/ 86oo精彩教程 zh-cn 86oo精彩教程 PaoPao v4.0 我的小站 http://leaf.jdk.cn/logo.gif www.86oo.com http://leaf.jdk.cn 莫多泡泡2006 <#list blogs as blog> http://www.86oo.com http://leaf.jdk.cn/entry.action?entryId=${blog.id} <![CDATA[${blog.title}]]> 86oo.com提供各类教程 ${blog.authorMail}(${blog.author}) ${blog.pubDate} 86oo.com提供各类教程 http://leaf.jdk.cn/entry.action?id=${blog.id} 86oo精彩教程 我在rss.action里面去取blogs就可以了。 public String execute() throws Exception { http://www.86oo.com PaginationSupport ps = blogManager.getBlogsByPage(0); blogs = new ArrayList(); for(Iterator ite = ps.getItems().iterator(); ite.hasNext();){ Blog blog = (Blog)ite.next(); 86oo.com欢迎你 WrapRssBlog wrapBlog = new WrapRssBlog(); wrapBlog.setId(blog.getId()); wrapBlog.setAuthor(blog.getAuthor().getNickname()); wrapBlog.setAuthorMail(blog.getAuthor().getMail()); wrapBlog.setTitle(blog.getTitle()); wrapBlog.setContent(StringUtil.extractText(blog.getContent())); wrapBlog.setPubDate(DateUtil.formatRssDate(blog.getPostTime())); 您所浏览的文章来自86oo.com StringBuffer sb = new StringBuffer(); for(Iterator ite2 = blog.getCategories().iterator(); ite2.hasNext();){ Category cate = (Category) ite2.next(); sb.append(" ") www.86oo.com .append(cate.getName()); } wrapBlog.setCategories(sb.toString()); blogs.add(wrapBlog); } return super.execute(); } 这里把blog包装了一下,主要是处理了一下日期,内容,还有把分类拼成字符串。关于日期 的处理,参考了飞云小侠写的rss日期的研究。实现代码如下。 public static String formatRssDate(Date date){ 86oo精彩教程 SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z",Locale.US); //TODO TimeZone SimpleTimeZone zone = new SimpleTimeZone(8,"GMT"); 您所浏览的文章来自86oo.com sdf.setTimeZone(zone); return sdf.format(date); } 这样就得到了这样的日期 Thu, 6 Apr 2006 16:01:36 GMT 做好了这些,配置一下action www.86oo.com /WEB- INF/pages/rss.ftl 不过像这样配置的话,你访问http://xxx.xxx.com/rss.action看到的不是一个xml 因为返回结果的contentType是text/html.而不是xml ,这样是不行的。看了一下webwork源码 。 原来可以这样简单的解决。改成这样配置就可以了。 86oo.com 86oo精彩教程 /WEB-INF/pages/rss.ftl application/xml 86oo精彩教程 简单吧。其实你还可以把这个contentType改成其他类型的。比如excle的。这样用户执行就 可以得到一个xls文件。哈哈。
还剩18页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

xxcdh

贡献于2012-08-20

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf