FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等
网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于SEO。
另外我们如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。Nginx可以承载5万的并发,而Tomcat只有几百
FTL指令
(1) assign指令
1) 定义简单类型
<#assign linkman="佩奇">联系人:${linkman}
2) 定义对象类型
<#assign info={"mobile":"13301231212",‘address‘:‘佩奇街‘} >电话:${info.mobile} ?地址:${info.address}
(2) include指令
<#include "head.ftl">
(3) if指令
1) 在模板文件上添加
<#if success=true> ?你已通过实名认证<#else> ???你未通过实名认证</#if>
2) 在代码中对str变量赋值
在freemarker的判断中,可以使用= 也可以使用==
map.put("success", true);
(4) list指令
如果想在循环中得到索引,使用循环变量+_index就可以得到
<#list goodsList as goods> ?${goods_index+1} 商品名称: ${goods.name} 价格:${goods.price}<br></#list>
(5) 内建函数
共 ?${goodsList?size} ?条记录
(6) 转换JSON字符串为对象
<#assign text="{‘bank‘:‘工商银行‘,‘account‘:‘10101920201920212‘}" /> ???<#assign data=text?eval /> ???开户行:${data.bank} ?账号:${data.account}
(7) 日期格式化
代码dataModel.put("today", new Date());在模板文件中加入当前日期:${today?date} <br>当前时间:${today?time} <br> ??当前日期+时间:${today?datetime} <br> ???????日期格式化: ?${today?string("yyyy年MM月")}
(8) 数字转换为字符串
代码中对变量赋值:map.put("point", 102920122);修改模板:累计积分:${point}
(9) 空值处理运算符
1) 判断某变量是否存在:“??”
用法为:variable??,如果该变量存在,返回true,否则返回false
<#if aaa??> ?aaa变量存在<#else> ?aaa变量不存在</#if>
2) 缺失变量默认值:“!”
使用!对null值做转换处理
${aaa!‘-‘}
(10) 运算符
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)>
生成静态页面
(1) 依赖
<dependency> ???????<groupId>org.freemarker</groupId> ???????<artifactId>freemarker</artifactId></dependency>
(2) applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" ???xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" ???xmlns:context="http://www.springframework.org/schema/context" ???xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" ???xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ???????http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd ???????http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd ???????http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> ???????<context:component-scan base-package="com.xxx.details.service.impl"></context:component-scan> ???????<!-- freemarker --> ???<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> ?????? <!-- ftl文件存放路径 -->
<property name="templateLoaderPath" value="/WEB-INF/ftl/" /> ???????<property name="defaultEncoding" value="UTF-8" /> ???</bean></beans>
(3) web.xml
???<!-- 加载spring配置容器 --> ???<context-param> ???????<param-name>contextConfigLocation</param-name> ???????<param-value>classpath*:spring/applicationContext-*.xml</param-value> ???</context-param> ???<listener> ???????<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> ???</listener>
(4) 生成静态页面的class
@Servicepublic class ItemPageServiceImpl implements ItemPageService { private String "d:\\item\\";// 网页生成目录 ???????@Autowired ???private FreeMarkerConfig freeMarkerConfig; ???????@Autowired ???private TbGoodsMapper goodsMapper; ???????@Autowired ???private TbGoodsDescMapper goodsDescMapper; ???????????@Override ???public boolean genItemHtml(Long goodsId){ ???????????????????????try { ???????????Configuration configuration = freeMarkerConfig.getConfiguration(); ???????????Template template = configuration.getTemplate("item.ftl"); ???????????Map dataModel=new HashMap<>(); ???????????????????????//1.加载商品表数据 ???????????TbGoods goods = goodsMapper.selectByPrimaryKey(goodsId); ???????????dataModel.put("goods", goods); ???????????????????????//2.加载商品扩展表数据 ???????????????????????TbGoodsDesc goodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId); ???????????dataModel.put("goodsDesc", goodsDesc); ???????????????????????????????????Writer out=new FileWriter(pagedir+goodsId+".html"); ???????????template.process(dataModel, out); ???????????out.close(); ???????????return true; ???????????????????} catch (Exception e) { ???????????e.printStackTrace(); ???????????return false; ???????} ???}}
(5) ftl:/xxx-details-service/src/main/webapp/WEB-INF/ftl/item.ftl
<!DOCTYPE html><html><head> ???<meta charset="utf-8" /> ???<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"> ???<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /> ???<title>产品详情页</title> ????<link rel="icon" href="assets/img/favicon.ico"> ???<link rel="stylesheet" type="text/css" href="css/webbase.css" /> ???<link rel="stylesheet" type="text/css" href="css/pages-item.css" /> ???<link rel="stylesheet" type="text/css" href="css/pages-zoom.css" /> ???<link rel="stylesheet" type="text/css" href="css/widget-cartPanelView.css" /> ???????<!-- angular --> ???<script type="text/javascript" src="plugins/angularjs/angular.min.js"></script> ???????<!-- 自定义angular.js --> ???<script type="text/javascript" src="js/base.js"></script> ???<script type="text/javascript" src="js/controller/detailsController.js"></script> ???????<!-- freemarker --> ???<script> ???????var itemList = [ ???????????<#list itemList as item> ???????????????{ ???????????????????"id":${item.id?c}, ???????????????????"title":"${item.title!‘‘}", ???????????????????"price":${item.price?c}, ???????????????????????????????????????"spec": ${item.spec}, ???????????????????"num":${item.num?c}, ???????????????????"image":"${item.image}" ???????????????}, ???????????</#list> ???????]; ???????var specificationItems = ${goodsDesc.specificationItems}; ???</script></head><body ng-app="xxx" ng-controller="detailsController" ng-init="num=1;search()"><!--页面顶部 开始--><#include "head.ftl"><!-- 图片列表 --><#assign itemImages=goodsDesc.itemImages?eval><!-- 扩展属性列表 --><#assign customAttributeItems=goodsDesc.customAttributeItems?eval><!-- 规格列表 --><#assign specificationItems=goodsDesc.specificationItems?eval><!--页面顶部 结束--> ???<div class="py-container"> ???????<div id="item"> ???????????<div class="crumb-wrap"> ???????????????<ul class="sui-breadcrumb"> ???????????????????<li> ???????????????????????<a href="#">${itemCat1}</a> ???????????????????</li> ???????????????????<li> ???????????????????????<a href="#">${itemCat2}</a> ???????????????????</li> ???????????????????<li class="active"><a href="#">${itemCat3}</a></li> ???????????????</ul> ???????????</div> ???????????<!--product-info--> ???????????<div class="product-info"> ???????????????<div class="fl preview-wrap"> ???????????????????<!--放大镜效果--> ???????????????????<div class="zoom"> ???????????????????????<!--默认第一个预览--> ???????????????????????<div id="preview" class="spec-preview"> ???????????????????????????<span class="jqzoom"> ???????????????????????????????<#if itemImages?size gt 0> ???????????????????????????????????<img jqimg="${itemImages[0].url}" src="${itemImages[0].url}" width="400px" height="400px"/> ???????????????????????????????</#if> ???????????????????????????</span> ???????????????????????</div> ???????????????????????<!--下方的缩略图--> ???????????????????????<div class="spec-scroll"> ???????????????????????????<a class="prev"><</a> ???????????????????????????<!--左右按钮--> ???????????????????????????<div class="items"> ???????????????????????????????<ul> ???????????????????????????????????<#list itemImages as image> ???????????????????????????????????????<li> ???????????????????????????????????????????<img src="${image.url}" bimg="${image.url}" onmousemove="preview(this)" /> ???????????????????????????????????????</li> ???????????????????????????????????</#list> ???????????????????????????????</ul> ???????????????????????????</div> ???????????????????????????<a class="next">></a> ???????????????????????</div> ???????????????????</div> ???????????????</div> ???????????????<div class="fr itemInfo-wrap"> ???????????????????<div class="sku-name"> ???????????????????????<h4>{{item.title}}</h4> ???????????????????</div> ???????????????????<div class="news"><span>${goods.caption}</span></div> ???????????????????<div class="summary"> ???????????????????????<div class="summary-wrap"> ???????????????????????????<div class="fl title"> ???????????????????????????????<i>价 格</i> ???????????????????????????</div> ???????????????????????????<div class="fl price"> ???????????????????????????????<i>¥</i> ???????????????????????????????<em>{{item.price}}</em> ???????????????????????????????<span>降价通知</span> ???????????????????????????</div> ???????????????????????????<div class="fr remark"> ???????????????????????????????<i>累计评价</i><em>612188</em> ???????????????????????????</div> ???????????????????????</div> ???????????????????????<div class="summary-wrap"> ???????????????????????????<div class="fl title"> ???????????????????????????????<i>促 销</i> ???????????????????????????</div> ???????????????????????????<div class="fl fix-width"> ???????????????????????????????<i class="red-bg">加价购</i> ???????????????????????????????<em class="t-gray">满999.00另加20.00元,或满1999.00另加30.00元,或满2999.00另加40.00元,即可在购物车换购热销商品</em> ???????????????????????????</div> ???????????????????????</div> ???????????????????</div> ???????????????????<div class="support"> ???????????????????????<div class="summary-wrap"> ???????????????????????????<div class="fl title"> ???????????????????????????????<i>支 持</i> ???????????????????????????</div> ???????????????????????????<div class="fl fix-width"> ???????????????????????????????<em class="t-gray">以旧换新,闲置手机回收 ?4G套餐超值抢 ?礼品购</em> ???????????????????????????</div> ???????????????????????</div> ???????????????????????<div class="summary-wrap"> ???????????????????????????<div class="fl title"> ???????????????????????????????<i>配 送 至</i> ???????????????????????????</div> ???????????????????????????<div class="fl fix-width"> ???????????????????????????????<em class="t-gray">满999.00另加20.00元,或满1999.00另加30.00元,或满2999.00另加40.00元,即可在购物车换购热销商品</em> ???????????????????????????</div> ???????????????????????</div> ???????????????????</div> ???????????????????<div><h3>库存数量: ${item.num}</h3></div> ???????????????????<div class="clearfix choose"> ???????????????????????<div id="specification" class="summary-wrap clearfix"> ???????????????????????????<#list specificationItems as specificationItem> ???????????????????????????<!-- <dl ng-if="goods.tbGoodsDesc.specificationItems != null" ng-repeat="specificationItem in goods.tbGoodsDesc.specificationItems"> --> ???????????????????????????????<dl> ???????????????????????????????????<dt> ???????????????????????????????????<div class="fl title"> ???????????????????????????????????????<i>选择${specificationItem.attributeName}</i> ???????????????????????????????????</div> ???????????????????????????????????</dt> ???????????????????????????????????<!-- <dd ng-repeat="attributeValue in specificationItem.attributeValue"> --> ???????????????????????????????????<#list specificationItem.attributeValue as attributeValue> ???????????????????????????????????????<dd> ???????????????????????????????????????????<a href="javascript:void(0);" ng-click="changeItemId(‘${specificationItem.attributeName}‘, ‘${attributeValue}‘)" class="{{isDefault(‘${specificationItem.attributeName}‘, ‘${attributeValue}‘)?‘selected‘:‘‘}}">${attributeValue}<span title="点击取消选择"> </span></a> ???????????????????????????????????????</dd> ???????????????????????????????????</#list> ???????????????????????????????</dl> ???????????????????????????</#list> ???????????????????????????????????????????????????</div> ???????????????????????????????????????????<div class="summary-wrap"> ???????????????????????????<div class="fl title"> ???????????????????????????????<div class="control-group"> ???????????????????????????????????<div class="controls"> ???????????????????????????????????????<input autocomplete="off" type="text" value="1" minnum="1" class="itxt" ng-model="num"/> ???????????????????????????????????????<a href="javascript:void(0)" class="increment plus" ng-click="addNum(1)">+</a> ???????????????????????????????????????<a href="javascript:void(0)" class="increment mins" ng-click="addNum(-1)">-</a> ???????????????????????????????????</div> ???????????????????????????????</div> ???????????????????????????</div> ???????????????????????????<div class="fl"> ???????????????????????????????<ul class="btn-choose unstyled"> ???????????????????????????????????<li> ???????????????????????????????????????<a href="javascript:void(0);" ng-click="addToCart()" class="sui-btn ?btn-danger addshopcar">加入购物车</a> ???????????????????????????????????</li> ???????????????????????????????</ul> ???????????????????????????</div> ???????????????????????</div> ???????????????????</div> ???????????????</div> ???????????</div> ???????</div> ???</div> ???<!-- 底部栏位 --> ???<!--页面底部 ?开始 --><#include "foot.ftl"><!--页面底部 ?结束 --></body></html>
网页静态化(freemarker)
原文地址:https://www.cnblogs.com/lin-nest/p/10322903.html