200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 电商项目day12(商品详情页面静态化freemarker的入门)

电商项目day12(商品详情页面静态化freemarker的入门)

时间:2020-04-25 04:24:00

相关推荐

电商项目day12(商品详情页面静态化freemarker的入门)

今日目标:

掌握页面静态化技术

完成入门demo

熟练使用常用的demo

商品详情页面的展示

静态页面动态效果实现

一.freemarker入门Demo

1.首先为什么要使用freemarker技术?

FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。

FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。

解决高并发访问的问题,因为这样非常消耗性能,这样做肯定不对

1、商品数据量巨大,并且从三张表中获取数据。所以查询性能很差,用户体验很差

2、商品详情查看功能是频繁操作,如果每次从数据库中获取数据,给数据库造成很大的访问压力。

那我们如何解决呢?

1、将数据缓存到redis 数据量小,并且经常查询,很少发生变化的数据。

2、页面静态化。

像我们这么多的商品数据是不能存到redis数据库中的,我们只能采用一种页面静态化的技术,

我们考虑什么时候生成页面呢?

商品上架的时候。

tb_goods完成商品上架

*****注意:商品上架时,同步上架商品到索引库,并同时生成该商品对应的静态html页面。

商品下架时,同步删除索引库下架商品,并同时删除该商品对应的静态html页面。

freemarker模板的后缀是ftl

搭建一个工程实现freemarker入门demo

代码:

// 第一步:创建一个 Configuration 对象,直接 new 一个对象。构造方法的参数就是Configuration configuration = new Configuration(Configuration.getVersion());// freemarker 的版本号。// 第二步:设置模板文件所在的路径。configuration.setDirectoryForTemplateLoading(new File("D:\\IdeaProjects\\projectAll\\FreemarkDemo\\src\\main\\resources"));// 第三步:设置模板文件使用的字符集。一般就是 utf-8.configuration.setDefaultEncoding("utf-8");// 第四步:加载一个模板,创建一个模板对象。Template template = configuration.getTemplate("test.ftl");// 第五步:创建一个模板使用的数据集,可以是 pojo 也可以是 map。一般是 Map。Map map = new HashMap();map.put("name","张三");map.put("message","来自freemarker的世界");map.put("success",false);List goodList = new ArrayList();Map goods1 = new HashMap();goods1.put("name","苹果");goods1.put("price",5.8);Map goods2 = new HashMap();goods2.put("name","香蕉");goods2.put("price",9.9);goodList.add(goods1);goodList.add(goods2);map.put("goodList",goodList);//日期格式化map.put("today",new Date());//数字转化字符串map.put("point",123456789);map.put("aaa",null);map.put("bbb",null);// 第六步:创建一个 Writer 对象,一般创建一 FileWriter 对象,指定生成的文件名。Writer out = new FileWriter(new File("F:\\test.html"));// 第七步:调用模板对象的 process 方法输出文件。template.process(map,out);// 第八步:关闭流out.close();

ftl的模板:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><#--我是注釋標簽-->${name} 你好 ,我是 ${message}</body></html>

结果如图:

二.freemarker的常用指令

1.FTL指令

第五步:创建一个模板使用的数据集,可以是 pojo 也可以是 map。一般是 Map。Map map = new HashMap();map.put("name","张三");map.put("message","来自freemarker的世界");map.put("success",false);List goodList = new ArrayList();Map goods1 = new HashMap();goods1.put("name","苹果");goods1.put("price",5.8);Map goods2 = new HashMap();goods2.put("name","香蕉");goods2.put("price",9.9);goodList.add(goods1);goodList.add(goods2);map.put("goodList",goodList);//日期格式化map.put("today",new Date());//数字转化字符串map.put("point",123456789);map.put("aaa",null);map.put("bbb",null);// 第六步:创建一个 Writer 对象,一般创建一 FileWriter 对象,指定生成的文件名。

模板的配置:

第五步:创建一个模板使用的数据集,可以是 pojo 也可以是 map。一般是 Map。Map map = new HashMap();map.put("name","张三");map.put("message","来自freemarker的世界");map.put("success",false);List goodList = new ArrayList();Map goods1 = new HashMap();goods1.put("name","苹果");goods1.put("price",5.8);Map goods2 = new HashMap();goods2.put("name","香蕉");goods2.put("price",9.9);goodList.add(goods1);goodList.add(goods2);map.put("goodList",goodList);//日期格式化map.put("today",new Date());//数字转化字符串map.put("point",123456789);map.put("aaa",null);map.put("bbb",null);// 第六步:创建一个 Writer 对象,一般创建一 FileWriter 对象,指定生成的文件名。

算符运算符:

1.逻辑运算符:

逻辑运算符有如下几个:

逻辑与:&&

逻辑或:||

逻辑非:!

逻辑运算符只能作用于布尔值,否则将产生错误

2.比较运算符

1 =或者==:判断两个值是否相等.

2 !=:判断两个值是否不等.

3 >或者 gt:判断左边值是否大于右边值

4 >=或者 gte:判断左边值是否大于等于右边值

5 <或者 lt:判断左边值是否小于右边值

6 <=或者 lte:判断左边值是否小于等于右边值

注意: =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且 FreeMarker 是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker 会把>解释成 FTL 标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>

注意:一般用()把需要的逻辑判断的扩展起来

三.商品详情页面的分析以及实现

1.首先创建需要生成的freemarker的工程

page_web page_service page_interface

2.分为两部分,组装数据和组装模板,首先组装数据

分析:我们分析商品详情页可知,需要三张表的数据 tb_goods tb_goodsdesc tb_item 我们通过组合实体类获得的三张表的数据

后台代码:

@Service@Transactionalpublic class PageServiceImpl implements PageService {//一次注入三个表得数据@Autowiredprivate TbGoodsMapper tbGoodsMapper;@Autowiredprivate TbGoodsDescMapper tbGoodsDescMapper;@Autowiredprivate TbItemMapper itemMapper;@Overridepublic Goods findOne(Long goodsId) {//获取goods表的数据TbGoods tbGoods = tbGoodsMapper.selectByPrimaryKey(goodsId);//获得goodsdesc表的数据TbGoodsDesc tbGoodsDesc = tbGoodsDescMapper.selectByPrimaryKey(goodsId);//获得item表的数据TbItemExample example = new TbItemExample();TbItemExample.Criteria criteria = example.createCriteria();criteria.andGoodsIdEqualTo(goodsId);List<TbItem> itemList = itemMapper.selectByExample(example);Goods goods = new Goods();goods.setTbGoods(tbGoods);goods.setTbGoodsDesc(tbGoodsDesc);goods.setItems(itemList);return goods;}

@RestController@RequestMapping("/page")public class PageController {@Referenceprivate PageService pageService;@Autowiredprivate FreeMarkerConfigurer freeMarkerConfigurer;@RequestMapping("/genHtml")public String genHtml(Long goodsId){try {// 第一步:创建一个 Configuration 对象,直接 new 一个对象。构造方法的参数就是Configuration configuration = freeMarkerConfigurer.getConfiguration();// freemarker 的版本号。// 第四步:加载一个模板,创建一个模板对象。Template template = configuration.getTemplate("item.ftl");// 第五步:创建一个模板使用的数据集,可以是 pojo 也可以是 map。一般是 Map。Goods goods = pageService.findOne(goodsId);List<TbItem> items = goods.getItemList();for (TbItem item : items) {//在这呢我们不要将组合实体类返回,因为返回还的遍历,取值,我们直接在这封装给map就可以了Map<String,Object> map = new HashMap<>();map.put("goods", goods);map.put("item",item);// 第六步:创建一个 Writer 对象,一般创建一 FileWriter 对象,指定生成的文件名。Writer out = new FileWriter("F:\\item\\"+item.getId()+".html");// 第七步:调用模板对象的 process 方法输出文件。template.process(map,out);// 第八步:关闭流out.close();}return "success.............";} catch (Exception e) {e.printStackTrace();return "fail............";}}}

模板的抽取:

抽取完一部分,记得及时引入刚刚抽取的代码

页面展示完后,我们添加需要的静态资源就能看到,

四.页面的展示

1.需求分析:

如下图所示:

我们知道goods表中有

category1Id category2Id category2Id

后台代码:

List<TbItem> itemList = itemMapper.selectByExample(example);//组装分类的信息String category1Name = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory1Id()).getName();String category2Name = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory2Id()).getName();String category3Name = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id()).getName();Goods goods = new Goods();//获取封装的的map集合Map<String,String> categoryMap = new HashMap<>();//将数据封装到map集合中categoryMap.put("category1Name",category1Name);categoryMap.put("category2Name",category2Name);categoryMap.put("category3Name",category3Name);goods.setCategoryMap(categoryMap);

注意我们一定要在goods的组合实体类中添加categoryMap的Map集合,最后注意打包到仓库

2.替换照片

{"color":"金色","url":"http://192.168.25.133/group1/M00/00/01/wKgZhVwbIGmABW-LAACnGz_9YE0694.jpg"}]--><#assign imageList=goods.tbGoodsDesc.itemImages?eval><!--放大镜效果--><div class="zoom"><#if (imageList?size>0)><!--默认第一个预览--><div id="preview" class="spec-preview"><span class="jqzoom"><img jqimg="${imageList[0].url}" src="${imageList[0].url}" width="400px" height="1000px"/></span></div>

3.实现规格的选项

<#--[{"attributeValue":["移动4G","联通3G"],"attributeName":"网络"},{"attributeValue":["32G","128G"],"attributeName":"机身内存"}]--><#assign specList=goods.tbGoodsDesc.specificationItems?eval><#list specList as spec><dl><dt><div class="fl title"><i>${spec.attributeName}</i></div></dt><#list spec.attributeValue as value><dd><a href="javascript:;" class="selected">${value}<span title="点击取消选择">&nbsp;</span></a></dd></#list></dl></#list>

五.静态页面的动态效果实现

1.需求:

页面:<div class="controls"><input autocomplete="off" type="text" value="{{num}}" minnum="1" class="itxt" /><a href="javascript:void(0)" class="increment plus" ng-click="addNum(num+1)">+</a><a href="javascript:void(0)" class="increment mins" ng-click="addNum(num-1)">-</a></div>

pageController.js

app.controller("pageController",function($scope,$controller){//继承代码$controller("baseController",{$scope:$scope});//商品数量的加减动态数量$scope.num = 1;$scope.addNum = function(num){$scope.num = num;if($scope.num<1){$scope.num=1;}}})

注意:一定要在模板中映入资源

<#--映入资源--><script type="text/javascript" src="plugins/angularjs/angular.min.js"> </script><script type="text/javascript" src="js/base.js"> </script><script type="text/javascript" src="js/controller/baseController.js"> </script><script type="text/javascript" src="js/controller/pageController.js"> </script>

2.实现规格选项的动态切换

思路:通过获得规格列表,判断是否相等,如果都相等,获取它的id值,然后拼接成url地址,重新刷新页面通过location.href

app.controller("pageController",function($scope,$controller){//继承代码$controller("baseController",{$scope:$scope});//商品数量加减动态效果$scope.num=1;$scope.addNum=function(num){$scope.num=num;if($scope.num<1){$scope.num=1;}}//当前商品记录规格对象 var spec={"网络":"移动3G","机身内存":"64G"};//当前商品规格选项是否选择的方法$scope.isSelected=function(specName,specOption){if(spec[specName]==specOption){return true;}else{return false;}}//规格选项切换动态效果实现$scope.updateSpecAttribute=function(specName,specOption){//更新当前商品规格数据spec[specName]=specOption;//构建规格组合列表/*var specList=[{id:1369284,spec:{"网络":"移动3G","机身内存":"64G"}},{id:1369285,spec:{"网络":"移动3G","机身内存":"128G"}},{id:1369286,spec:{"网络":"移动4G","机身内存":"64G"}},{id:1369287,spec:{"网络":"移动4G","机身内存":"128G"}},];*/for(var i=0;i<specList.length;i++){if(matchObject(specList[i].spec,spec)){location.href=specList[i].id+".html";}}}//map1={"网络":"移动3G","机身内存":"64G"}//map2={"网络":"移动3G","机身内存":"64G","颜色":"red"}matchObject=function(map1,map2){for(var k in map1){if(map1[k]!=map2[k]){return false;}}//反向遍历,可以对于第二个多的在判断for(var k in map2){if(map2[k]!=map1[k]){return false;}}return true;}});

页面代码:

<script type="text/javascript">//当前商品记录规格对象var spec=${item.spec};//构建规格组合列表var specList=[<#list goods.itemList as item>{id:${item.id?c},spec:${item.spec}},</#list>];</script>

<#--class="selected"--><#list spec.attributeValue as value><dd><a href="javascript:;" ng-click="updateSpecAttribute('${spec.attributeName}','${value}')" class="{{isSelected('${spec.attributeName}','${value}')?'selected':''}}">${value}<span title="点击取消选择">&nbsp;</span></a></dd></#list></dl></#list>

六.总结

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。