众所周知,随着网站的访问量增加,如何给用户以良好的访问体验就显得尤为重要。提升网站性能便成为一些网站面临的一大难题,像hao123这样的导航网站要提升网站的性能只要部署的web服务器数量足够就可以承载超大规模的访问量,如果是一个动态的网站呢?例如像凤凰新闻、网易新闻这样的CMS系统,淘宝、京东这样的大型购物网站由于这些网站都使用到了数据库这也就很难做到单纯的通过增加web服务器数量的方式来有效的提升网站的性能,但是这些网站并没有出现或者说极少出现因为访问量过大而造成页面响应缓慢的问题。这其中有什么样的技术手段使得这些大型的动态网站能够有如此高的性能呢?目前提升网站性能的方法通常有HTML静态化、图片服务器分离、数据库集群、负载均衡、代码优化、压缩JS和CSS文件等等。其中HTML静态化的目的其实就是降低HTTP请求个数从而降低数据库的操作从而达到提高网站运行速度,这也是一个最有效的提升网站性能的方法之一。本文将通过具体案例讲解如何采用FreeMarker将动态网页静态化从而达到提升网站性能的目的。
一:FreeMarker简介
1,动态网页与静态网页的差距
2,FreeMarker的原理
3,FreeMarker特有表达式
4,FreeMarker常用的命令
1,动态网页和静态网页差异?
1)静态网页:
a、静态网页的内容稳定,页面加载速度快。
b、静态网页的没有数据库支持,在网站制作和维护方面的工作量较大。
c、静态网页的交互性差,有很大的局限性。
2)动态网页:
a、交互性好。
b、动态网页的信息都需要从数据库中读取,每打开一个一面就需要去获取一次数据库,如果访问人数很多,也就会对服务器增加很大的荷载,从而影响这个网站的运行速度。
通过上面的比较我们不难看出,要提升网站的性能,我们只要把动态网页做成静态网页就会在运行速度方面有显著的提升,但是问题出来了,如果将所有页面都做成静态页面显然是不切实际的。有什么办法能让我们的网站即能有动态网页的交互性,又有静态网页的加载速度呢?FreeMarker便能实现这样的需求:实现动态网页静态化。
2、FreeMarker原理
FreeMarker是一个基于Java的开发包和类库的一种将模板和数据进行整合并输出文本的通用工具,FreeMarker实现页面静态化的原理是:将页面中所需要的样式写入到FreeMarker模板文件中,然后将页面所需要的数据进行动态绑定并放入到Map中,然后通过FreeMarker的模板解析类process()方法完成静态页面的生成。其工作原理如下图所示。
3、FreeMarker表达式
表达式可以说是FreeMarker的核心功能,表达式放置在插值语法“${...}”之中时,表面需要输出表达式的值,表达式语法也可以与FreeMarker标签结合,用于控制输出。
1)直接指定值
例如:${“zhangsan”}
2)输出变量值
FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性,例如:${user.name}。
3)字符串操作
a、字符串的连接,字符串的连接可以直接使用云算符“+”来连接字符串也可以使用${..}(或#{..})在字符串常量部分插入表达式的值,从而完成字符串连接。
b、字符串的截取,${book[1..4]}
4)集合连接运算符,这里所说的集合连接运算是将两个集合连接成一个新的集合,连接集合的运算符是“+”,例如:
5)Map连接运算符,Map对象的连接运算也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+。如果两个Map对象具有相同的 key,则后加入Map里的key所对应的value替代原来key所对应的value
Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子:
{"语文":78, "数学":80}
Map对象的key和value都是表达式,但是key必须是字符串
6)算术运算符,FreeMarker表达式中完全支持算术运算。FreeMarker支持的算术运算符包括: +,-,*,/,%
7)比较运算符,FreeMarker表达式中支持的比较运算符有如下几个
a、=(或者==):判断两个值是否相等.
b、!=:判断两个值是否不相等
c、 >(或者gt):判断坐标值是否大于右边值
d、 >=(或者gte):判断坐标值是否大于等于右边值
e、 <(或者lt):判断左边值是否小于右边值
f、 <=(或者lte):判断左边值是否小于等于右边值
8)逻辑运算符,FreeMarker中的逻辑运算符有如下几个:
a、逻辑与:&&
b、逻辑或:||
c、逻辑非:!
9)内建函数
FreeMarker提供了一些内建函数用来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来转换输出变量,例如:${test?upper_case?html}这里就是将test字符串转换为大写并进行HTML编码。
html:对字符串进行HTML编码
cap_first:使字符串第一个字母大写
lower_case:将字符串转换成小写
upper_case:将字符串转换成大写
trim:去掉字符串前后的空白字符
下面是集合的常用内建函数
size:获取序列中元素的个数
下面是数字值的常用内建函数
int:取得数字的整数部分,结果带符号
例如:
<#assign test="Tom & Jerry">
${test?html}
${test?upper_case?html}
结果是:Tom & Jerry TOM & JERRY
10)空值处理运算符
FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,如果存在没有赋值的变量就会抛出异常,为了处理缺失变量FreeMarker提供了两个运算符:“!”和“??”,其中“!”用于指定缺失变量的默认值,“??”用来判断某个变量是否存在。
4、FreeMarker的常用指令
1)if指令
使用if指令可以有条件的跳过模板的一部分,和程序语言中的if相似,例如你想显示某个用户是否成年可以这样写:
2)switch、case、default、break指令
FreeMarker中使用switch、case、default、break指令和常用的程序设计语言中的一样。例如:
虽然FreeMarker提供了switch指令,但它并不推荐使用switch指令来控制也输出,而是推荐使用FreeMarker的if..elseif..else 指令来替代它。
3)list, break指令
list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:
<#list sequence as item>
...
</#list>
上面的语法格式中,sequence就是一个集合对象,也可以是一个表达式,但该表达式将返回一个集合对象,而item是一个任意的名字,就是被迭代输出的集合元素.此外,迭代集合对象时,还包含两个特殊的循环变量:
item_index:当前变量的索引值
item_has_next:是否存在下一个对象
也可以使用<#break>指令跳出迭代
当在HTML中需要用列表遍历集合的内容时,list就显得尤为重要,例如当我们需要遍历一个用户集合时可以这样写:
4)include 指令
include指令的作用类似于JSP的包含指令,用于包含指定页,include指令的语法格式如下:
<#include filename [options]>
在上面的语法格式中,两个参数的解释如下
a)filename:该参数指定被包含的模板文件
b)options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding指定包含页面时所使用的解码集,而parse指定被包含是否作为FTL文件来解析。如果省略了parse选项值,则该选项值默认是true。
5)assign指令
通过assign(赋值)指令可以创建一个变量,或替换一个已存在的变量,例如:
<#assign name=”zhangsan”>
三、FreeMarker实现网页静态化
上面我简单介绍了FreeMarker的基本用法,下面我将以具体例子采用Freemarker实现网页静态化的功能。
1)新建一个Maven项目,在pom.xml文件中新增FreeMarker的jar包,<version>2.3.20</version>
2)新建FreemarkerUtil工具类,其中包含了通过标准输出流输出模板的结果的方法和输出到文件中的方法。Freemarker是通过template.Configuration这个对象对模板进行加载的(它也处理创建和缓存预解析模板的工作),然后我们通过getTemplate方法获得你想要的模板,有一点要记住template.Configuration在你整个应用必须保证唯一实例。
3)新建User实体类,用户属性包含用户主键、用户年龄、邮箱,该实体类用于模拟从数据库中查询出数据。
4)新建模板文件01.ftl,通过上面的介绍知道FreeMarker是一种基于模板的、用来生成输出文本的通用工具,所以我们必须要定制符合自己业务的模板出来,然后将需要动态加载的数据通过FreeMarker的语法规范书写生成静态HTML的模板文件,具体的语法规范在上前面已经详细介绍。
6) 通过以上步骤便成功的完成了一个通过FreeMarker生成静态HTML文件,生成的HTML文件内容如图3-1所示。
通过以上步骤便成功的实现了对一个需要从数据库中查询数据的动态页面的静态化处理,当我们每次更新了数据库中的相应信息以后,我们便可以重新执行这个方法,将这个页面重新静态化,当我们每次访问这个网页的时候便不会每一次都去数据库中查询数据了,而是访问的一个已经一次性生成了的静态页面,这也就达到了提高网站运行速度的目标。
四.总结
一个大型的网站,比如门户网站,在提高网站性能时,基本的解决方案都是将HTML静态化、图片服务器分离、数据库集群、负载均衡等几个方案。其中HTML静态化便大大降低了大量的数据库访问请求,在提高用户访问速度方面有很明显的作用,大家都知道,效率最高、消耗最小的就是纯静态化的HTML页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的解决方法。但是对于大量内容并且更新频繁的网站,我们无法全部手动的去一个一个实现,于是便出现了像FreeMarker这样的一些技术,在所有采用网页静态化手段的网站中,FreeMarker使用的比例大大的超过了其他的一些技术,由此可见FreeMarker在这方面的一些显著优势。
对于一些门户和信息发布类型的网站在交互性方面要求很高,对于这些网站来说尽可能的实现网页静态化是提高性能的必要手段,将系统的首页、文章、社区帖子进行实时的静态化、有更新的时候再重新静态化也是大量使用的策略,像Mop大杂烩、网易新闻、凤凰新闻等大型网站也都使用了这样的策略。同时,HTML静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用FreeMarker将HTML静态化。比如一些网站的公用设置信息,这些信息基本都是可以通过后台来管理并存储在数据库中,这些信息其实会大量的被前台程序调用,每一次调用都会去查询一次数据库,但是这些信息的更新频率又会很小,因此也可以考虑将这部分内容进行后台更新的时候进行静态化,这样就避免了大量的数据库访问请求,从而也就提高了网站的性能。