网站性能提升之采用FreeMarker实现网页静态化

news/2024/5/9 6:10:46/文章来源:https://blog.csdn.net/dislike0428/article/details/101467449

摘要

众所周知,随着网站的访问量增加,如何给用户以良好的访问体验就显得尤为重要。提升网站性能便成为一些网站面临的一大难题,像hao123这样的导航网站要提升网站的性能只要部署的web服务器数量足够就可以承载超大规模的访问量,如果是一个动态的网站呢?例如像凤凰新闻、网易新闻这样的CMS系统,淘宝、京东这样的大型购物网站由于这些网站都使用到了数据库这也就很难做到单纯的通过增加web服务器数量的方式来有效的提升网站的性能,但是这些网站并没有出现或者说极少出现因为访问量过大而造成页面响应缓慢的问题。这其中有什么样的技术手段使得这些大型的动态网站能够有如此高的性能呢?目前提升网站性能的方法通常有HTML静态化、图片服务器分离、数据库集群、负载均衡、代码优化、压缩JSCSS文件等等。其中HTML静态化的目的其实就是降低HTTP请求个数从而降低数据库的操作从而达到提高网站运行速度,这也是一个最有效的提升网站性能的方法之一。本文将通过具体案例讲解如何采用FreeMarker将动态网页静态化从而达到提升网站性能的目的。

关键字:FreeMarker、高并发、静态化。

 

文章组织结构

一.FreeMarker简介

1.动态网页与静态网页差异

2.FreeMarker原理

3.FreeMarker表达式

4.FreeMarker常用指令

二.FreeMarker实现网页静态化

三.总结

 

一、FreeMarker简介

1、动态网页和静态网页差异

在进入主题之前我先介绍一下什么是动态网页,动态网页是指跟静态网页相对应的一种网页编程技术。静态网页,随着HTML代码的生成,页面的内容和显示效果就不会再发生变化(除非你修改页面代码)。而动态网页则不然,页面代码虽然没有发生变化,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生相应的变化。简而言之,动态网页是基本的HTML语法规范与javaVBVC等高级程序设计语言、数据库编程等多种技术的融合,以实现对网站内容和风格的高效、动态和交互式的管理。

通过前面的介绍我们可以得出动态网页和静态网页的优缺点(这里我们只考虑网站性能方面的相关问题,信息安全等多方面问题不做赘述):

1)静态网页:

a、静态网页的内容稳定,页面加载速度快。

b、静态网页的没有数据库支持,在网站制作和维护方面的工作量较大。

c、静态网页的交互性差,有很大的局限性。

2)动态网页:

a、交互性好。

b、动态网页的信息都需要从数据库中读取,每打开一个一面就需要去获取一次数据库,如果访问人数很多,也就会对服务器增加很大的荷载,从而影响这个网站的运行速度。

通过上面的比较我们不难看出,要提升网站的性能,我们只要把动态网页做成静态网页就会在运行速度方面有显著的提升,但是问题出来了,如果将所有页面都做成静态页面显然是不切实际的。有什么办法能让我们的网站即能有动态网页的交互性,又有静态网页的加载速度呢?FreeMarker便能实现这样的需求:实现动态网页静态化。

 

2FreeMarker原理

FreeMarker是一个基于Java的开发包和类库的一种将模板和数据进行整合并输出文本的通用工具,FreeMarker实现页面静态化的原理是:将页面中所需要的样式写入到FreeMarker模板文件中,然后将页面所需要的数据进行动态绑定并放入到Map中,然后通过FreeMarker的模板解析类process()方法完成静态页面的生成。其工作原理如图2-1所示。

                                                                                      

图2-1 FreeMarker工作原理图

 

3FreeMarker表达式

表达式可以说是FreeMarker的核心功能,表达式放置在插值语法“${...}”之中时,表面需要输出表达式的值,表达式语法也可以与FreeMarker标签结合,用于控制输出。

1)直接指定值

例如:${“zhangsan”}

2)输出变量值

FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性,例如:${user.name}。

3)字符串操作

a、字符串的连接,字符串的连接可以直接使用云算符“+”来连接字符串也可以使用${..}(#{..})在字符串常量部分插入表达式的值,从而完成字符串连接

b、字符串的截取,${book[1..4]}

4)集合连接运算符,这里所说的集合连接运算是将两个集合连接成一个新的集合,连接集合的运算符是“+”,例如:

<#list ["星期一"," 星期二","星期三"]+["星期四","星期五"] as x>
          ${x}
</#list>

 

5Map连接运算符,Map对象的连接运算也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+。如果两个Map对象具有相同的 key,则后加入Map里的key所对应的value替代原来key所对应的value

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编码。

10)空值处理运算符

FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,如果存在没有赋值的变量就会抛出异常,为了处理缺失变量FreeMarker提供了两个运算符:“!”和“??”,其中“!”用于指定缺失变量的默认值,“??”用来判断某个变量是否存在。

 

4FreeMarker的常用指令

1if指令

使用if指令可以有条件的跳过模板的一部分,和程序语言中的if相似,例如你想显示某个用户是否成年可以这样写:

<#if user.age lt 18>

${user.name}未成年

<#else>

${user.name}已成年

</if>

2switchcasedefaultbreak指令

FreeMarker中使用switchcasedefaultbreak指令和常用的程序设计语言中的一样。例如:
  <#switch value>
           <#case refValue>
              ...
              <#bread>
           <#case refValue>
              ...
              <#bread>
           <#default>
              ...
 </#switch>     

虽然FreeMarker提供了switch指令,但它并不推荐使用switch指令来控制也输出,而是推荐使用FreeMarker的if..elseif..else 指令来替代它。

3list指令

当在HTML中需要用列表遍历集合的内容时,list就显得尤为重要,例如当我们需要遍历一个用户集合时可以这样写:

<table>

<tr><th>姓名</th><th>年龄</th></tr>

<#list users as user>

<tr><td>${user.name}</td><td>${user.age}</td></tr>

</#list>

</table>

4include 指令
        include指令的作用类似于JSP的包含指令,用于包含指定页,include指令的语法格式如下:
         <#include filename [options]>
          在上面的语法格式中,两个参数的解释如下
          a)filename:该参数指定被包含的模板文件
          b)options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding指定包含页面时所使用的解码集,而parse指定被包含是否作为FTL文件来解析。如果省略了parse选项值,则该选项值默认是true。

5assign指令

通过assign指令可以创建一个变量,或替换一个已存在的变量,例如:

<#assign name=”zhangsan”>

 

三、FreeMarker实现网页静态化

上面我简单介绍了FreeMarker的基本用法,下面我将以具体例子采用Freemarker实现网页静态化的功能。

 

1)新建一个Maven项目,在pom.xml文件中新增FreeMarker的jar包,

 <!-- freemark -->
<dependency>
   <groupId>org.freemarker</groupId>
   <artifactId>freemarker</artifactId>
   <version>2.3.20</version>
</dependency>

2)新建FreemarkerUtil工具类,其中包含了通过标准输出流输出模板的结果的方法和输出到文件中的方法。Freemarker是通过template.Configuration这个对象对模板进行加载的(它也处理创建和缓存预解析模板的工作),然后我们通过getTemplate方法获得你想要的模板,有一点要记住template.Configuration在你整个应用必须保证唯一实例。

public class FreemarkerUtil {

private static FreemarkerUtil util;

private static Configuration cfg;

private FreemarkerUtil() {

}

 

public static FreemarkerUtil getInstance(String pname) {

if(util==null) {

//通过FreemarkerConfiguration读取响应的ftl

cfg = new Configuration();

//设定去哪里读取响应的ftl模板文件

cfg.setClassForTemplateLoading(FreemarkerUtil.class, pname);

cfg.setDefaultEncoding("utf-8");

util = new FreemarkerUtil();

}

return util;

}

 

/**

 * 根据模板文件名获取模板文件对象

 * @param fname 模板文件名

 * @return

 */

private Template getTemplate(String fname) {

try {

//在模板文件目录中找到名称为fname的模板文件

return cfg.getTemplate(fname);

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

 

/**

 

 * 通过标准输出流输出模板的结果

 

 * @param root 数据对象

 

 * @param fname 模板文件名

 

 */

 

public void sprint(Map<String,Object> root,String fname) {

 

try {

 

//通过Template可以将模板文件输出到相应的流中

 

Template template  = getTemplate(fname);

 

template.setEncoding("utf-8");

 

template.process(root, new PrintWriter(System.out));

 

} catch (TemplateException e) {

 

e.printStackTrace();

 

} catch (IOException e) {

 

e.printStackTrace();

 

}

 

}

 

/**

 

 * 基于文件的输出

 

 * @param root 数据对象

 

 * @param fname 模板文件名

 

 * @param outpath 输出文件路径

 

 */

 

public void fprint(Map<String,Object> root,String fname,String outpath) {

 

try {

 

Template template  = getTemplate(fname);

 

template.setEncoding("utf-8");

 

template.process(root, new FileWriter(outpath));

 

} catch (TemplateException e) {

 

e.printStackTrace();

 

} catch (IOException e) {

 

e.printStackTrace();

 

}

 

}

 

}

 

3)新建User实体类,用户属性包含用户主键、用户年龄、邮箱,该实体类用于

模拟从数据库中查询出数据。

public class User {

private int id;

private String name;

private String age;

private String email;

 

public User() {

super();

}

 

public User(int id, String name, String age, String email) {

super();

this.id = id;

this.name = name;

this.age = age;

this.email = email;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

 

······省略其他getset方法

}

4)新建模板文件01.ftl,通过上面的介绍知道FreeMarker是一种基于模板的、用来生成输出文本的通用工具,所以我们必须要定制符合自己业务的模板出来,然后将需要动态加载的数据通过FreeMarker的语法规范书写生成静态HTML的模板文件,具体的语法规范在上前面已经详细介绍。

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

</head>

<body>

<h1>${user.name}</h1>

<h1>${user.age}</h1>

<h1>${user.email}</h1>

</body>

</html>

5)新建Junit测试类TestFreemarker,用假数据模拟从数据库中查询数据并通过FreeMarker将模板文件和数据结合生成静态的HTML文件。

public class TestFreemarker {

@Test

public void test01(){

Map<String,Object> root = new HashMap<String,Object>();

root.put("user",new User(1, "ZhangSan", "24", "ZhangSan@aa.com"));

FreemarkerUtil ft = FreemarkerUtil.getInstance("/ftl");

ft.sprint(root, "01.ftl");

ft.fprint(root, "01.ftl","C:\\01.html");

}

}

6 通过以上步骤便成功的完成了一个通过FreeMarker生成静态HTML文件,生成的HTML文件内容如图3-1所示。

 

图3-1

通过以上步骤便成功的实现了对一个需要从数据库中查询数据的动态页面的静态化处理,当我们每次更新了数据库中的相应信息以后,我们便可以重新执行这个方法,将这个页面重新静态化,当我们每次访问这个网页的时候便不会每一次都去数据库中查询数据了,而是访问的一个已经一次性生成了的静态页面,这也就达到了提高网站运行速度的目标。

 

四.总结

一个大型的网站,比如门户网站,在提高网站性能时,基本的解决方案都是将HTML静态化、图片服务器分离、数据库集群、负载均衡等几个方案。其中HTML静态化便大大降低了大量的数据库访问请求,在提高用户访问速度方面有很明显的作用,大家都知道,效率最高、消耗最小的就是纯静态化的HTML页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的解决方法。但是对于大量内容并且更新频繁的网站,我们无法全部手动的去一个一个实现,于是便出现了像FreeMarker这样的一些技术,在所有采用网页静态化手段的网站中,FreeMarker使用的比例大大的超过了其他的一些技术,由此可见FreeMarker在这方面的一些显著优势。

对于一些门户和信息发布类型的网站在交互性方面要求很高,对于这些网站来说尽可能的实现网页静态化是提高性能的必要手段,将系统的首页、文章、社区帖子进行实时的静态化、有更新的时候再重新静态化也是大量使用的策略,像Mop大杂烩、网易新闻、凤凰新闻等大型网站也都使用了这样的策略。同时,HTML静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用FreeMarker将HTML静态化。比如一些网站的公用设置信息,这些信息基本都是可以通过后台来管理并存储在数据库中,这些信息其实会大量的被前台程序调用,每一次调用都会去查询一次数据库,但是这些信息的更新频率又会很小,因此也可以考虑将这部分内容进行后台更新的时候进行静态化,这样就避免了大量的数据库访问请求,从而也就提高了网站的性能。

 

 

个人简介:

刘小兵

软件开发工程师

任职于某大型IT外资企业,主要从事JavaEE开发。

转载于:https://www.cnblogs.com/liuxiaobing/articles/5707486.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_899444.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RHCE-Day18(2)-LNMP搭建网站

RHCE-Day18(2)-LNMP搭建网站 使用LNMP架构部署动态网站环 1.源码包程序 使用源码包来安装服务程序具有两个优势。 源码包的可移植性非常好&#xff0c;几乎可以在任何Linux系统中安装使用&#xff0c;而RPM软件包是针对特定系统和架构编写的指令集&#xff0c;必须严格地符合…

网站站长必备的六款网页负载、网速性能测试工具

转自&#xff1a;http://www.cnplugins.com/zhuanti/sixwebmastertestplugins.html 有大数据表明&#xff0c;一个网页打开的速度超过4秒&#xff0c;用户就会关掉页面&#xff0c;对于网站来说就是流失到一个潜在的客户。有什么一些开发者插件可以帮助我们站在来及时的检测自己…

大型网站技术架构

作者&#xff1a;xlzd 链接&#xff1a;https://www.zhihu.com/question/20657269/answer/101795180 来源&#xff1a;知乎 著作权归作者所有&#xff0c;转载请联系作者获得授权。 1. 初始阶段的网站架构 一般来讲&#xff0c;大型网站都是从小型网站发展而来&#xff0c;一开…

Java开发牛人十大必备网站

本文由 ImportNew - 张文太 翻译自 programcreek。如需转载本文&#xff0c;请先参见文章末尾处的转载要求。 ImportNew注&#xff1a;如果你也对Java技术翻译分享感兴趣&#xff0c;欢迎加入我们的 Java开发 小组。参与方式请查看小组简介。 以下是我收集的Java开发牛人必备…

Java开发牛人十大必备网站

本文由 ImportNew - 张文太 翻译自 programcreek。如需转载本文&#xff0c;请先参见文章末尾处的转载要求。 ImportNew注&#xff1a;如果你也对Java技术翻译分享感兴趣&#xff0c;欢迎加入我们的 Java开发 小组。参与方式请查看小组简介。 以下是我收集的Java开发牛人必…

Python Django windows 环境配置---(网站开发)

学习做网站纯属个人的兴趣&#xff0c;就选择了Python对网站的开发。 下载Python 可以在Python官方网站下载下载完成以后就可以进行环境配置。环境配置路径就不做详细介绍了&#xff0c;可以在网上搜索出来。安装Django 在配置完Python以后就可以在Django官网下载程序包了&a…

java网上商城 购物网站 在线商品销售系统设计与实现 项目源代码下载 javaweb jsp ssm ssh mysql

1 前端商城界面 1.1 商城首页 首页分为三个部分&#xff0c;分别显示热销推荐、特价促销、新品上架三个推荐类目的商品列表 以上这三类推荐商品可以分别在后台管理中设置 点击商品图片或商品标题可以进入商品详情页面 点击【加入购物车】按钮会将次商品加入购物车 1.2 商品…

java农场商城 生鲜超市 水果蔬菜电商网站平台系统设计与实现 项目源代码下载 javaweb jsp ssm mysql

1 前端商城界面 1.1 商城首页 首页导航上有五个按钮&#xff0c;分别显示产品分类、商城首页、今日推荐、热销排行、新品上市&#xff0c;五个推荐类目的商品列表 首页很长说明书中1和2页均是首页&#xff0c;分六个部分&#xff0c;分别是今日推荐、热销排行、生态果蔬、肉禽…

java服装商城 男装女装童装鞋帽超市 购物网站系统设计与实现 项目源代码下载 javaweb jsp ssm mysql

1 前端商城界面 1.1 商城首页 首页分为三个部分&#xff0c;分别显示女装、男装、童装三个推荐类目的商品列表&#xff0c;以上这三类推荐商品可以分别在后台管理中设置&#xff0c;点击商品图片或商品标题可以进入商品详情页面 1.2 搜索功能 鼠标进入导航条上方的红色文本框…

dedecms 实现两个网站调用一个数据库

近年来移动端的流量上升&#xff0c;让我们不得不把眼光放在移动端上&#xff0c;程序猿都知道dedecms的wap不中用&#xff0c;标签少的可怜&#xff0c;没有静态化的功能&#xff0c;想调点数据&#xff0c;自己写sql语句&#xff0c;这东东如果用。于是&#xff0c;半路出家的…

搭建一个大型网站架构的实验环境(Squid缓存服务器篇)

squid缓存服务器的配置 squid缓存服务器在这个实验环境中有两台&#xff08;192.168.10.30&#xff0c;192.168.10.31&#xff09;做成squid集群&#xff0c;我们首先安装一台&#xff0c;然后复制一台&#xff0c;再做配置&#xff0c;这样省事&#xff0c;哈&#xff01; squ…

12个顶级开发者社区网站帮助程序员走上人生巅峰

公元二十一世纪&#xff0c;世界迎来了大互联网时代&#xff0c;程序员这个行当已然成为了医生、律师等高端中产阶级职业之外的又一高薪职业。不过既然是技术职业&#xff0c;自然也 就会分三六九等&#xff0c;没理想的程序员只能写着自己擅长的代码&#xff0c;加着没玩没了的…

[转载]说说大型高并发高负载网站的系统架构

| 评论 # yueguoliang发表于2007-09-29 16:08:37IP: 211.94.149.* ju ti dian shuo ming fang an cai hao # fxbird发表于2007-09-29 16:19:19IP: 59.44.72.* 这才是高质量的文章。 # oldmoon发表于2007-09-29 17:36:43IP: 116.252.70.* 受益匪浅 # irplay发表于2007-09-30 09:…

互联网网站的反爬虫策略浅析(收藏)

关键字: crawler 因为搜索引擎的流行&#xff0c;网络爬虫已经成了很普及网络技术&#xff0c;除了专门做搜索的Google&#xff0c;Yahoo&#xff0c;微软&#xff0c;百度以外&#xff0c;几乎每个大型门户网站都有自己的搜索引擎&#xff0c;大大小小叫得出来名字得就几十种&…

LAMP网站架构方案分析

LAMP&#xff08;Linux-Apache-MySQL-PHP&#xff09;网站架构是目前国际流行的Web框架&#xff0c;该框架包括&#xff1a;Linux操作系统&#xff0c;Apache网络服务器&#xff0c;MySQL数据库&#xff0c;Perl、PHP或者Python编程语言&#xff0c;所有组成产品均是开源软件&a…

【转】使用 Nginx 提升网站访问速度【反向代理】

Nginx 简介 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的&#xff0c;它已经在该站点运行超过两年半了。 Igor 将源代码以类 …

HTML——简单的网站首页

学习记录帖&#xff08;一&#xff09; 简单的网站首页 这是我的一个记录帖&#xff0c;我是按照黑马程序员的视频学习的。 使用的是HBuilder&#xff0c;学习了html & css & js & jq & bootstrap。 成果 代码 <!DOCTYPE html> <html><head…

Web网站服务(Apache)

Apache网站服务基础 Apache HTTP server 是广泛应用的Web应用之一 Apache简介 Apache HTTP server 是开源软件项目的杰出代表&#xff0c;基于标准的HTTP网络协议提供网页浏览器&#xff0c;Apache服务器可以运行在Linux&#xff0c;UNIX&#xff0c;Windows等多种操作系统平…

使用 HttpWebRequest 向网站提交数据

转自&#xff1a;http://www.cnblogs.com/webman/archive/2006/11/17/564106.html HttpWebRequest 是 .net 基类库中的一个类&#xff0c;在命名空间 System.Net 下面&#xff0c;用来使用户通过 HTTP 协议和服务器交互。 HttpWebRequest 对 HTTP 协议进行了完整的封装&#x…

创建springboot项目时改为国内网站

总结 &#xff1a; 第一点&#xff1a;今天进行了蓝桥杯 的竞赛&#xff0c;说一说我的感悟&#xff0c;还是练得不够&#xff0c;其实有挺多熟悉的题&#xff0c;可是还是没做出来&#xff0c;还是征战明年的蓝桥杯吧&#xff0c;还有就是&#xff0c;电脑的问题&#xff0c;…