freemarker页面静态化介绍
FreeMarker原理
FreeMarker是一个基 于Java的开发包和类库的一种将模板和数据进行整合并输出文本的通用工具,FreeMarker实现页面静态化的原理是:将页面中所需要的样式写入到 FreeMarker模板文件中,然后将页面所需要的数据进行动态绑定并放入到Map中,然后通过FreeMarker的模板解析类process()方 法完成静态页面的生成
为啥要网页静态化
网页静态化解决方案在实际开发中运用比较多,例如新闻网站,门户网站中的新闻频道或者是文章类的频道。
对于电商网站的商品详细页来说,至少几百万个商品,每个商品又有大量的信息,这样的情况同样也适用于使用网页静态化来解决。
网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于SEO。
另外我们如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。Nginx可以承载5万的并发,而Tomcat只有几百。
Freemarker入门案例
Test.ftl
<html> <head> <meta charset="utf-8"> <title>Freemarker入门小DEMO </title> </head> <body> <#--我只是一个注释,我不会有任何输出 --> ${name},你好。${message} <h3>assigne指令</h3> <#assign linkman="周先生"> 联系人:${linkman} <#assign info={"mobile":"13301231212",'address':'北京市昌平区王府街'} > 电话:${info.mobile} 地址:${info.address} <h3>if指令</h3> <#if success=true> 你已通过实名认证 <#else> 你未通过实名认证 </#if> <h3>list指令</h3> ----商品价格表----<br> <#list goodsList as goods> ${goods_index+1} 商品名称: ${goods.name} 价格:${goods.price}<br> </#list> <h3>内建函数</h3> <h4>获取集合大小</h4> 共 ${goodsList?size} 条记录 <h4>转换JSON字符串为对象</h4> <#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account} <h4>日期格式化</h4> 当前日期:${today?date} <br> 当前时间:${today?time} <br> 当前日期+时间:${today?datetime} <br> 日期格式化: ${today?string("yyyy年MM月")} <h4>数字转换为字符串</h4> 累计积分:${point} 累计积分:${point?c} <h3>空值处理运算符</h3> <h4>判断某变量是否存在:“??”</h4> <#if aaa??> aaa变量存在 <#else> aaa变量不存在 </#if> <h4>缺失变量默认值:“!”</h4> ${aaa!'-'} <h3>运算符</h3> <h4>算数运算符</h4> FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , % <h4>逻辑运算符</h4> 逻辑运算符有如下几个: 逻辑与:&& 逻辑或:|| 逻辑非:! 逻辑运算符只能作用于布尔值,否则将产生错误 <h4>比较运算符</h4> 表达式中支持的比较运算符有如下几个: 1 =或者==:判断两个值是否相等. 2 !=:判断两个值是否不等. 3 >或者gt:判断左边值是否大于右边值 4 >=或者gte:判断左边值是否大于等于右边值 5 <或者lt:判断左边值是否小于右边值 6 <=或者lte:判断左边值是否小于等于右边值 注意: =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况, </body> </html>
后台 Demo01:
package com.liuwenwu.freemarker; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class Demo001 { public static void main(String[] args) throws IOException, TemplateException { // 1.创建配置类 Configuration configuration = new Configuration(Configuration.getVersion()); // 2.设置模板所在的目录 configuration.setDirectoryForTemplateLoading( new File("F:\\java2\\javaxl_lunece_freemarker\\src\\main\\resources")); // 3.设置字符集 configuration.setDefaultEncoding("utf-8"); // 4.加载模板 Template template = configuration.getTemplate("test.ftl"); // 5.创建数据模型 Map map = new HashMap(); map.put("name", "小李飞刀 "); map.put("message", "欢迎来到神奇的博客网站:http://www.javaxl.com!"); map.put("success", true); 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); map.put("goodsList", goodsList); map.put("today", new Date()); map.put("point", 102920122); // 6.创建Writer对象 Writer out = new FileWriter(new File("F:\\java2\\javaxl_lunece_freemarker\\src\\main\\webapp\\freemarker\\test.html")); // 7.输出 template.process(map, out); // 8.关闭Writer对象 out.close(); } }
效果图:
将网页静态化用于博客网站
网页模板 blogDetail.ftl
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Python Django 模板层(AJAX)-javaxl-晓码阁-博客专栏</title> <link rel="stylesheet" href="./freemarkerDemo_files/bootstrap.min.css"> <link rel="stylesheet" href="./freemarkerDemo_files/bootstrap-theme.min.css"> <link rel="stylesheet" href="./freemarkerDemo_files/blog.css"> <script src="./freemarkerDemo_files/jquery-1.11.2.min.js.下载"></script> <script src="./freemarkerDemo_files/bootstrap.min.js.下载"></script> <style type="text/css"> body { padding-top: 10px; padding-bottom: 40px; } </style> </head> <body> <div class="container"> <script type="text/javascript"> function checkData() { var q = document.getElementById("q").value.trim(); if (q == null || q == "") { alert("请输入您要查询的关键字!"); return false; } else { return true; } } </script> <div class="row"> <div class="col-md-12" style="padding-top: 10px"> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">展开</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="http://www.javaxl.com/index"><b style="color: black"><strong>首页</strong></b></a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="http://122.114.92.43/p4/index" target="_blank"><b color="black"><strong>美食</strong></b></a></li> <li><a href="http://59.110.212.17/p5/index" target="_blank"><b color="black"><strong>知识库</strong></b></a></li> <li><a href="http://www.javaxl.com/abortMe" target="_blank"><b color="black"><strong>关于本站</strong></b></a></li> </ul> <form action="http://www.javaxl.com/admin/blog/q" class="navbar-form navbar-right" role="search" method="post" onsubmit="return checkData()"> <div class="form-group"> <input type="text" id="q" name="q" value="" class="form-control" placeholder="请输入要查询的关键字..."> </div> <button type="submit" class="btn btn-default">搜索</button> </form> </div> <!-- /.navbar-collapse --> </div> <!-- /.container-fluid --> </nav> </div> </div> <div class="row" style="margin-top: 50px;"> <!-- 真正展示博客内容的地方, 所有博客链接的列表->list.jsp 单条博客详情->view.jsp 呼和条件的博客详情列表->result.jsp --> <div class="col-md-9"> <script type="text/javascript" src="./freemarkerDemo_files/shCore.js.下载"></script> <link rel="stylesheet" href="./freemarkerDemo_files/shCoreDefault.css"> <script type="text/javascript"> /*本页面用于查看博客链接中的详细内容*/ SyntaxHighlighter.all(); function showOtherComment() { $(".otherComment").show(); } function loadimage() { document.getElementById("randImage").src = "/static/system/jsp/common/image.jsp?" + Math.random(); } function submitData() { var content = $("#content").val(); var imageCode = $("#imageCode").val(); if (content == null || content == "") { alert("请输入评论内容!"); } else if (imageCode == null || imageCode == "") { alert("请填写验证码!"); } else { $.post("/comment/save.do", { "content" : content, 'imageCode' : imageCode, 'blog.bid' : '323' }, function(result) { if (result.success) { window.location.reload(); alert("评论已提成成功,审核通过后显示!"); } else { alert(result.errorInfo); } }, "json"); } } </script> <div class="data_list"> <div class="data_list_title"> <img src="./freemarkerDemo_files/blog_show_icon.png" /> 博客信息 </div> <div> <div class="blog_title"> <h3> <strong>${blog.title }</strong> </h3> </div> <div class="blog_share"> <!-- <div class="bshare-custom"><a title="分享到QQ空间" class="bshare-qzone"></a><a title="分享到新浪微博" class="bshare-sinaminiblog"></a><a title="分享到人人网" class="bshare-renren"></a><a title="分享到腾讯微博" class="bshare-qqmb"></a><a title="分享到网易微博" class="bshare-neteasemb"></a><a title="更多平台" class="bshare-more bshare-more-icon more-style-addthis"></a><span class="BSHARE_COUNT bshare-share-count">0</span></div><script type="text/javascript" charset="utf-8" src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=2&lang=zh"></script><script type="text/javascript" charset="utf-8" src="http://static.bshare.cn/b/bshareC0.js"></script> --> </div> <div class="blog_info">发布时间:『${blog.releaseDate?datetime }』 博客类别:${blog.btid } 阅读(${blog.clickHit }) </div> <div class="blog_content">${blog.content }</div> </div> </div> </div> <!-- 右侧布局 --> <div class="col-md-3"> <div class="data_list"> <div class="data_list_title">博主信息</div> <div class="user_image"> <img src="./freemarkerDemo_files/index_1.jpg"> </div> <div class="nickName">javaxl_小李飞刀</div> <div class="userSign">(知识改变命运,教育改变生活)</div> </div> <div class="data_list"> <div class="data_list_title"> <img src="./freemarkerDemo_files/byType_icon.png"> 按日志类别 </div> <div class="datas"> <ul> <li><span><a href="http://www.javaxl.com/index.html?btid=9">java基础(71)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=1">自定义mvc(8)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=2">前端框架(39)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=4">索引框架(7)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=5">SSH(14)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=6">SSM(9)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=7">服务器部署(5)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=8">项目异常归总(5)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=10">安全框架(4)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=11">SpringBoot(15)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=12">程序人生(3)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=13">其他框架(5)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=14">开发工具(6)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=15">解决方案(7)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=16">23种设计模式(25)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=17">SpringCloud(14)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=18">第三方(4)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=19">Python(67)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?btid=20">底层探究(1)</a></span></li> </ul> </div> </div> <div class="data_list"> <div class="data_list_title"> <img src="./freemarkerDemo_files/byDate_icon.png"> 按日志日期 </div> <div class="datas"> <ul> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B408%E6%9C%88">2019年08月(36)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B407%E6%9C%88">2019年07月(27)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B406%E6%9C%88">2019年06月(47)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B405%E6%9C%88">2019年05月(61)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B404%E6%9C%88">2019年04月(18)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B403%E6%9C%88">2019年03月(50)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B402%E6%9C%88">2019年02月(57)</a></span></li> <li><span><a href="http://www.javaxl.com/index.html?releaseDateStr=2019%E5%B9%B401%E6%9C%88">2019年01月(13)</a></span></li> </ul> </div> </div> <div class="data_list"> <div class="data_list_title"> <img src="./freemarkerDemo_files/link_icon.png"> 友情链接 </div> <div class="datas"> <ul> <li><span><a href="http://www.baidu.com/" target="_blank">百度</a></span></li> <li><span><a href="http://122.114.92.43/p4/index" target="_blank">晓码阁-美食网</a></span></li> <li><span><a href="http://59.110.212.17/p5/index" target="_blank">晓码阁-知识库</a></span></li> </ul> </div> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div align="center" style="padding: 20px"> <span style="float: left;">Powered by <a href="http://www.javaxl.com/" target="_blank">博客首页</a> V1.0 </span> Copyright © 2018-2019 javaxl晓码阁 版权所有 </div> </div> </div> </div> </body> </html>
后台 Demo02
package com.liuwenwu.freemarker; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import com.liuwenwu.blog.util.DBAccess; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class Demo002 { @SuppressWarnings("rawtypes") public static void main(String[] args) throws IOException, TemplateException, SQLException { // 1.创建配置类 Configuration configuration = new Configuration(Configuration.getVersion()); // 2.设置模板所在的目录 configuration.setDirectoryForTemplateLoading( new File("F:\\java2\\javaxl_lunece_freemarker\\src\\main\\webapp\\freemarker")); // 3.设置字符集 configuration.setDefaultEncoding("utf-8"); // 4.加载模板 Template template = configuration.getTemplate("blogDetail.ftl"); // 5.创建数据模型 // Map map = new HashMap(); // map.put("name", "小李飞刀 "); // // 6.创建Writer对象 // Writer out = new FileWriter(new File("E:\\temp\\staticPage\\test.html")); // // 7.输出 // template.process(map, out); // 8.关闭Writer对象 // out.close(); createPage(template); } private static void createPage(Template template) throws SQLException, IOException, TemplateException { Connection con = DBAccess.getConnection(); String sql = "select * from t_lucene_freemarker_blog"; PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery(); Map map = new HashMap<>(); Map<String, Object> blog = new HashMap<>(); while(rs.next()) { blog.put("bid", rs.getObject("bid")); blog.put("title", rs.getObject("title")); blog.put("releaseDate", rs.getObject("releaseDate")); blog.put("btid", rs.getObject("btid")); blog.put("clickHit", rs.getObject("clickHit")); blog.put("content", rs.getObject("content")); map.put("blog", blog); // // 6.创建Writer对象 Writer out = new FileWriter(new File("F:\\java2\\javaxl_lunece_freemarker\\src\\main\\webapp\\freemarker\\"+blog.get("bid")+".html")); // 7.输出 template.process(map, out); // 8.关闭Writer对象 out.close(); } DBAccess.close(con, pst, rs); } }
效果: