静态化?
这里我们以网页静态化技术之一的Freemarker 为例子。以电商为原型
对于电商网站的商品详情页来说,至少几百万个商品,每个商品又有大量的信息,这样的情况同样也适用于使用网页静态化来解决
网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于SEO。
另外我们如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。Nginx可以承载5万的并发,而Tomcat只有几百。
那什么是 Freemarker?
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。
FreeMarker与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。
它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等
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':'101019212'}" /><#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>
Demo001
package com.javaxl.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("E:\\y2---study2\\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", "欢迎来到神奇的博客网站:!");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", 10292);// 6.创建Writer对象Writer out = new FileWriter(new File("E:\\y2---study2\\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="/jsp/jstl/core" prefix="c"%><%@ taglib prefix="fmt" uri="/jsp/jstl/fmt"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "/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> <spanclass="icon-bar"></span> <span class="icon-bar"></span></button><a class="navbar-brand" href="/index"><bstyle="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"><bcolor="black"><strong>美食</strong></b></a></li><li><a href="http://59.110.212.17/p5/index" target="_blank"><bcolor="black"><strong>知识库</strong></b></a></li><li><a href="/abortMe" target="_blank"><bcolor="black"><strong>关于本站</strong></b></a></li></ul><form action="/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"><imgsrc="./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="/b/buttonLite.js#style=-1&uuid=&pophcol=2&lang=zh"></script><script type="text/javascript" charset="utf-8" src="/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><ahref="/index.html?btid=9">java基础(71)</a></span></li><li><span><ahref="/index.html?btid=1">自定义mvc(8)</a></span></li><li><span><ahref="/index.html?btid=2">前端框架(39)</a></span></li><li><span><ahref="/index.html?btid=4">索引框架(7)</a></span></li><li><span><ahref="/index.html?btid=5">SSH(14)</a></span></li><li><span><ahref="/index.html?btid=6">SSM(9)</a></span></li><li><span><ahref="/index.html?btid=7">服务器部署(5)</a></span></li><li><span><ahref="/index.html?btid=8">项目异常归总(5)</a></span></li><li><span><ahref="/index.html?btid=10">安全框架(4)</a></span></li><li><span><ahref="/index.html?btid=11">SpringBoot(15)</a></span></li><li><span><ahref="/index.html?btid=12">程序人生(3)</a></span></li><li><span><ahref="/index.html?btid=13">其他框架(5)</a></span></li><li><span><ahref="/index.html?btid=14">开发工具(6)</a></span></li><li><span><ahref="/index.html?btid=15">解决方案(7)</a></span></li><li><span><ahref="/index.html?btid=16">23种设计模式(25)</a></span></li><li><span><ahref="/index.html?btid=17">SpringCloud(14)</a></span></li><li><span><ahref="/index.html?btid=18">第三方(4)</a></span></li><li><span><ahref="/index.html?btid=19">Python(67)</a></span></li><li><span><ahref="/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><ahref="/index.html?releaseDateStr=%E5%B9%B408%E6%9C%88">08月(36)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B407%E6%9C%88">07月(27)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B406%E6%9C%88">06月(47)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B405%E6%9C%88">05月(61)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B404%E6%9C%88">04月(18)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B403%E6%9C%88">03月(50)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B402%E6%9C%88">02月(57)</a></span></li><li><span><ahref="/index.html?releaseDateStr=%E5%B9%B401%E6%9C%88">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="/"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 <ahref="/" target="_blank">博客首页</a> V1.0</span> Copyright © - javaxl晓码阁 版权所有</div></div></div></div></body></html>
Demo002
package com.javaxl.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.javaxl.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("E:\\y2---study2\\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("E:\\y2---study2\\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);}}
效果图:
使用页面静态化后的url