网页静态化 & Freemarker的基本指令

Freemarker入门

一. Freemarker概述

1. 为什么要使用网页静态化技术

​ 网页静态化解决方案在实际开发中运用比较多,例如新闻网站,门户网站中的新闻频道或者是文章类的频道。

​ 对于电商网站的商品详细页来说,至少几百万个商品,每个商品又有大量的信息,这样的情况同样也适用于使用网页静态化来解决。

​ 网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于 SEO。

​ 另外我们如果将网页以纯静态化的形式展现,就可以使用 Nginx 这样的高性能的 web 服务器来部署。Nginx 可以承载 5 万的并发,而 Tomcat 只有几百。关于 Nginx 我们在后续的课程中会详细讲解。

今天我们就研究网页静态化技术----Freemarker。

2. 什么是 Freemarker

​ FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。 FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。

二. Freemarker入门

第一步,创建一个maven工程,并加入静态模板引擎的依赖坐标

<!--静态模板引擎依赖坐标  -->
	<dependencies>
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.23</version>
		</dependency>
	</dependencies>

第二步,创建模板文件.ftl(test.ftl)

注意:要把该文件编码格式改为UTF-8

<html>
<head>
	<meta charset="UTF-8">
	<title>入门Сdemo</title>
</head>
<body>
	<#--这是一个注释-->
	${name},你好,${message}
</body>
</html>

  1. 模板文件中四种元素
    1、 文本,直接输出的部分
    2、 注释,即<#–…-->格式不会输出
    3、 插值(Interpolation):即${…}部分,将使用数据模型中的部分替代输出
    4、 FTL 指令:FreeMarker 指令,和 HTML 标记类似,名字前加#予以区分,不会输出。

第三步,生成html文件的后台代码

注意:创建输出流的时候,不可以直接使用new FileWriter(),因为这样会乱码,

要使用OutPutStreamWriter流

/*
 * freemarker测试类
 */
public class FreeMarkerDemo {

	public static void main(String[] args) throws IOException, TemplateException {
		//1.创建配置类
		Configuration configuration=new Configuration(Configuration.getVersion());
		//2.设置ftl所在的包路径地址
		configuration.setDirectoryForTemplateLoading(
					new File("D:\\eclipseWorkspace\\freemarker_demo\\src\\main\\resources\\"));
		//3.设置字符集
		configuration.setDefaultEncoding("utf-8");
		//4.加载模板
		Template template = configuration.getTemplate("test.ftl");
		//5.创建模型,注意,前台有几个插值,这里就要封装几个数据
		Map dataMap=new HashMap<>();
		dataMap.put("name", "张三");
		dataMap.put("message", "欢迎来到静态模板引擎的世界");
		//6.创建输出流,设置输出地址
		Writer out =new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream("D:\\pingyougouSetup\\freemarkerDemo\\test.html"), "UTF-8"));
		//7.输出操作
		template.process(dataMap, out);
		//8.关闭流
		out.close();
	}

}

第四步,执行后,在D:\pingyougouSetup\freemarkerDemo目录即可看到生成的test.html ,

注意:如果改变了test.ftl里的内容,需要重新执行生成html的后台代码,方可看到效果

三. Freemarker指令

1. assign 指令

此指令是用来在页面上定义一个变量的指令

1.定义简单类型

assign指令-简单类型<br>
<#assign linkman="周先生">	
联系人:${linkman}

2.定义对象类型

assign指令-对象类型<br>
<#assign info={"name":"李先生","age":12}>	
姓名:${info.name} 年龄:${info.age}

2. include 指令

此指令用于模板文件的嵌套

创建一个head.ftl

<h1>黑马信息网</h1>

在test.ftl中引入head.ftl

include引入指令<br>
<#include "head.ftl">

显示效果

3. if 指令

<#if success=true> 
你已通过实名认证 
<#else>   
你未通过实名认证 
</#if> 

在代码中对 success变量赋值

dataMap.put("success", false);

在 freemarker的判断中,可以使用= 也可以使用==

4. list 指令

需求,实现商品价格表,如下图:

(1)代码中对变量 goodsList赋值

List goodsList=new ArrayList(); 
 	 	Map goods1=new HashMap(); 
 	 	goods1.put("name", "苹果"); 
 	 	goods1.put("price", 5.8);  	 	
 	 	Map goods2=new HashMap(); 
 	 	goods2.put("name", "香蕉"); 
 	 	goods2.put("price", 2.5);  	 	
 	 	Map goods3=new HashMap(); 
 	 	goods3.put("name", "橘子"); 
 	 	goods3.put("price", 3.2); 
 	 	goodsList.add(goods1); 
 	 	goodsList.add(goods2); 
 	 	goodsList.add(goods3);  	 	
 	 	dataMap.put("goodsList", goodsList); 


(2)在模板文件上添加

list指令<br>
	<#list goodsList as goods>
		${goods_index+1} 商品名称:${goods.name} 商品价格:${goods.price}<br>
	</#list>

如果想在循环中得到索引,使用循环变量+_index就可以得到。

四. Freemarker内建函数

内建函数语法格式: 变量?函数名称

1. 获取集合大小

我们使用size 函数来实现,代码如下:

共${goodsList?size}条记录

2. JSON 字符串转换

我们通常需要将 json 字符串转换为对象,那如何处理呢?看代码

JSON字符串转对象<br>
<#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> 
<#assign data=text?eval /> 
 开户行:${data.bank}  账号:${data.account} 

3. 日期格式化

代码中对变量赋值:

dataMap.put("today", new Date());

在模板文件中加入

当前日期:${today?date} <br> 
当前时间:${today?time} <br>    
当前日期+时间:${today?datetime} <br>         
日期格式化:  ${today?string("yyyy年MM月")} 

4. 数字转换为字符串

代码中对变量赋值:

map.put("point", 102920122); 

修改模板:

累计积分:${point} 

页面显示:

我们会发现数字会以每三位一个分隔符显示,有些时候我们不需要这个分隔符,就需要将数字转换为字符串,使用内建函数 c

累计积分:${point?c} 

页面显示效果如下:

五. 空值处理

如果你在模板中使用了变量但是在代码中没有对变量赋值,那么运行生成时会抛出异常。但是有些时候,有的变量确实是 null,怎么解决这个问题呢?

1. 判断是否存在:??

用法为:variable??,如果该变量存在,返回 true,否则返回 false

<#if  aa??>  
	我不存在
	<#else>
	我存在
</#if>

2. 指定默认值: bbb!转换值

我们除了可以判断是否为空值,也可以使用!对 null 值做转换处理

在模板文件中加入

${bbb!'ccc'}

在代码中不对 aaa 赋值,也不会报错了,当 bbb 为null 则返回!后边的内容ccc

六. 运算符

1. 算数运算符

FreeMarker 表达式中完全支持算术运算,FreeMarker 支持的算术运算符包括:+, - , * , / , %

2. 逻辑运算符

逻辑运算符有如下几个:

逻辑与:&& 逻辑或:||

逻辑非:!

逻辑运算符只能作用于布尔值,否则将产生错误

3. 比较运算符

表达式中支持的比较运算符有如下几个:

1 =或者==:判断两个值是否相等.

2 !=:判断两个值是否不等.

3 >或者 gt:判断左边值是否大于右边值

4 >=或者 gte:判断左边值是否大于等于右边值

5 <或者 lt:判断左边值是否小于右边值

6 <=或者 lte:判断左边值是否小于等于右边值

注意: =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值, 否则会产生错误,而且 FreeMarker 是精确比较,“x”,"x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果, 因为 FreeMarker 会把>解释成 FTL 标签的结束字符,当然,也可以使用括号来避免这种情况, 如:<#if (x>y)>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:<#-- ... -->格式部分,不会输出 3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出 4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出 下面是一个FreeMarker模板的例子,包含了以上所说的4个部分 <html><br> <head><br> <title>Welcome!</title><br> </head><br> <body><br> <#-- 注释部分 --><br> <#-- 下面使用插值 --> <h1>Welcome ${user} !</h1><br> <p>We have these animals:<br> <u1><br> <#-- 使用FTL指令 --> <#list animals as being><br> <li>${being.name} for ${being.price} Euros<br> <#list><br> <u1><br> </body><br> </html> 1, FTL指令规则 在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的. 1,开始标签:<#directivename parameter> 2,结束标签:</#directivename> 3,空标签:<#directivename parameter/> 实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号. 用户指令用@ 使用FTL标签时, 应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是< , /> 和指令之间不允许有空白字符. 2, 插值规则 FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式插值:#{expr}或#{expr;format} 2.1 通用插值 对于通用插值,又可以分为以下4种情况: 1,插值结果为字符串值:直接输出表达式结果 2,插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式单个插值,如下面的例子: <#settion number_format="currency"/> <#assign answer=42/> ${answer} ${answer?string} <#-- the same as ${answer} --> ${answer?string.number} ${answer?string.currency} ${answer?string.percent} ${answer} 输出结果是: $42.00 $42.00 42 $42.00 4,200% 3,插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式单个插值,如下面的例子: ${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')'")} 输出结果是: 2008-04-08 08:08:08 Pacific Daylight Time Tue, Apr 8, '03 Tuesday, April 08, 2003, 08:08:08 PM (PDT) 4,插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式单个插值,如下面的例子: <#assign foo=true/> ${foo?string("yes", "no")} 输出结果是: yes 2.2 数字格式插值 数字格式插值可采用#{expr;format}形式来格式数字,其中format可以是: mX:小数部分最小X位 MX:小数部分最大X位 如下面的例子: <#assign x=2.582/> <#assign y=4/> #{x; M2} <#-- 输出2.58 --> #{y; M2} <#-- 输出4 --> #{x; m1} <#-- 输出2.6 --> #{y; m1} <#-- 输出4.0 --> #{x; m1M2} <#-- 输出2.58 --> #{x; m1M2} <#-- 输出4.0 --> 3, 表达式 表达式是FreeMarker模板的核心功能,表达式放置在插值语法${}之中时,表明需要输出表达式的值;表达式语法也可与FreeMarker 标签结合,用于控制输出.实际上FreeMarker的表达式功能非常强大,它不仅支持直接指定值,输出变量值,也支持字符串格式输出和集合访问等功能. 3.1 直接指定值 使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象. 1,字符串 直接指定字符串值使用单引号或双引号限定,如果字符串值中包含特殊字符需要转义,看下面的例子: ${"我的文件保存在C:\\盘"} ${'我名字是\"annlee\"'} 输出结果是: 我的文件保存在C:\盘 我名字是"annlee" FreeMarker支持如下转义字符: \";双引号(u0022) \';单引号(u0027) \\;反斜杠(u005C) \n;换行(u000A) \r;回车(u000D) \t;Tab(u0009) \b;退格键(u0008) \f;Form feed(u000C) \l;< \g;> \a;& \{;{ \xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符. 如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码: ${r"${foo}"} ${r"C:\foo\bar"} 输出结果是: ${foo} C:\foo\bar 2,数值 表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker目前还不支持科学计数法,所以"1E3"是错误的.在FreeMarker表达式中使用数值需要注意以下几点: 1,数值不能省略小数点前面的0,所以".5"是错误的写法 2,数值8 , +8 , 8.00都是相同的 3,布尔值 直接使用true和false,不使用引号. 4,集合 集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子: <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x> ${x} </#list> 输出结果是: 星期一 星期二 星期三 星期四 星期五 星期六 星期天 除此之外,集合元素也可以是表达式,例子如下: [2 + 2, [1, 2, 3, 4], "whatnot"] 还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..2 5,Map对象 Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子: {"语文":78, "数学":80} Map对象的key和value都是表达式,但是key必须是字符串 3.2 输出变量值 FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况 1,顶层变量 所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型: Map root = new HashMap(); //创建数据模型 root.put("name","annlee"); //name是一个顶层变量 对于顶层变量,直接使用${variableName}来输出变量值,变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法: ${name} 2,输出集合元素 如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引: ["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法: ${week[2]} //输出第三个集合元素 此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法: week[3..5] //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素 3,输出Map元素 这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型: Map root = new HashMap(); Book book = new Book(); Author author = new Author(); author.setName("annlee"); author.setAddress("gz"); book.setName("struts2"); book.setAuthor(author); root.put("info","struts"); root.put("book", book); 书有作者, 为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法: book.author.name //全部使用点语法 book["author"].name book.author["name"] //混合使用点语法和方括号语法 book["author"]["name"] //全部使用方括号语法 使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果. Map?keys这个map当中所有的key的列表 Map?values这个map当中所有的value的列表 3.3, 字符串操作 FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等. 字符串连接有两种语法: 1,使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接. 2,直接使用连接运算符+来连接字符串 例如有如下数据模型: Map root = new HashMap(); root.put("user","annlee"); 下面将user变量和常量连接起来: ${"hello, ${user}!"} //使用第一种语法来连接 ${"hello, " + user + "!"} //使用+号来连接 上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样. 值得注意的是,${..}只能用于文本部分,不能用于表达式,下面的代码是错误的: <#if ${isBig}>Wow!</#if> <#if "${isBig}">Wow!</#if> 应该写成:<#if isBig>Wow!</#if> 截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型: Map root = new HashMap(); root.put("book","struts2,freemarker"); 可以通过如下语法来截取子串: ${book[0]}${book[4]} //结果是su ${book[1..4]} //结果是tru

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值