需求分析
运用 Freemarker 技术来实现商品详细页的静态化。通过地址栏输入某地址,如下形式
http://localhost:9101/gen_item.do?goodsId=149187842867952
能在本地电脑某目录生成商品详细页,页面的名称为商品 id.html
工程搭建
1.服务接口层
创建 pinyougou-page-interface 工程,创建 com.pinyougou.page.service 包,包下创建接口
/** * 商品详细页接口 * @author Administrator * */ public interface ItemPageService { /** * 生成商品详细页 * @param goodsId */ public boolean genItemHtml(Long goodsId); }
2.服务实现层
1)创建 war 工程 pinyougou-page-service
2)pom.xml 引入依赖 参见其它服务工程, 另外添加 freemarker 依赖
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> </dependency>
(3)添加 web.xml 参见其它服务工程
(4)spring 配置文件 参见其它服务工程 ,另外配置:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/ftl/" /> <property name="defaultEncoding" value="UTF-8" /> </bean>
(5)创建属性文件page.properties,用于配置网页生成目录,内容为:
pagedir=d:\\item\\
(6)建立 com.pinyougou.page.service.impl 包,包下建立类
@Service public class ItemPageServiceImpl implements ItemPageService { @Value("${pagedir}") private String pagedir; @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; } } }
(7)将 item.html 拷贝至 web-inf/ftl 下 ,修改扩展名为 ftl ,将商品名称用插值代替
<div class="sku-name"> <h4>${goods.goodsName}</h4> </div>
(8)在 D 盘建立文件夹 item,将必要的样式表和 Js 拷贝到此目录下,此目录为生成的目录
3 运营商管理后台
(1)pinyougou-manager-web 引入依赖 pinyougou-page-interface
(2)在 GoodsController.java 中新增方法
@Reference(timeout=40000) private ItemPageService itemPageService; /** * 生成静态页(测试) * @param goodsId */ @RequestMapping("/genHtml") public void genHtml(Long goodsId){ itemPageService.genItemHtml(goodsId); }
商品详情页模板构建
1.模板模块化引入
此时我们的 item.ftl 内容较多,当我们编辑时不容易快速找到编辑的位置,所以我们将头部分拆分到 head.ftl ,将尾部拆分到 foot.ftl ,用 include 指令在 item.ftl 中引入 。
2. 生成基本数据
在模板中找到合适的位置,用插值替换静态文本
<div class="news"><span>${goods.caption}</span></div>
<div class="fl price"><i>¥</i><em>${goods.price}</em><span>降价通知</span></div>
<div class="intro-detail"><!-- 商品详情 --> ${goodsDesc.introduction}</div>
<div id="two" class="tab-pane"><p>${goodsDesc.packageList}</p></div> <div id="three" class="tab-pane"><p>${goodsDesc.saleService}</p></div>
3 生成图片列表
编辑模板文件
<#--图片列表 --> <#assign imageList=goodsDesc.itemImages?eval />
这一句要转换图片列表的 json 字符串
图片部分的代码
<!--默认第一个预览--> <div id="preview" class="spec-preview"> <span class="jqzoom"> <#if (imageList?size>0)> <img jqimg="${imageList[0].url}" src="${imageList[0].url}" width="400px" height="400px" /> </#if> </span> </div> <!--下方的缩略图--> <div class="spec-scroll"> <div class="items"> <ul> <#list imageList as item> <li><img src="${item.url}" bimg="${item.url}" onmousemove="preview(this)" /></li> </#list> </ul> </div> </div>
4 生成扩展属性列表
修改模板 首先进行 json 转换
<#--扩展属性列表 --> <#assign customAttributeList=goodsDesc.customAttributeItems?eval />
显示扩展属性数据,如果扩展属性为空则不显示此条数据
<#list customAttributeList as item> <#if item.value??> <li>${item.text} :${item.value}</li> </#if> </#list>
5 生成规格列表
修改模板 转换规格列表
<#--规格列表 --> <#assign specificationList=goodsDesc.specificationItems?eval />
此时,我们需要使用嵌套循环
<#list specificationList as specification> <dl> <dt> <div class="fl title"> <i>${specification.attributeName}</i> </div> </dt> <#list specification.attributeValue as item> <dd><a href="javascript:;" >${item}</a></dd> </#list> </dl> </#list>
6 生成商品类型面包屑
修改 ItemPageServiceImpl ,读取三级商品分类名称,加入到数据模型中
@Service public class ItemPageServiceImpl implements ItemPageService { @Autowired private FreeMarkerConfig freeMarkerConfig; @Autowired private TbGoodsMapper goodsMapper; @Autowired private TbGoodsDescMapper goodsDescMapper; @Autowired private TbItemCatMapper itemCatMapper; @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); //3.商品分类 String itemCat1 = itemCatMapper.selectByPrimaryKey(goods.getCategory1Id()).getName(); String itemCat2 = itemCatMapper.selectByPrimaryKey(goods.getCategory2Id()).getName(); String itemCat3 = itemCatMapper.selectByPrimaryKey(goods.getCategory3Id()).getName(); dataModel.put("itemCat1", itemCat1); dataModel.put("itemCat2", itemCat2); dataModel.put("itemCat3", itemCat3); Writer out=new FileWriter("d:\\item\\"+goodsId+".html"); template.process(dataModel, out); out.close(); return true; } catch (Exception e) { // TODO Auto-generated catch blocke.printStackTrace(); return false; } } }
修改模板,展示商品分类面包屑
<ul class="sui-breadcrumb"> <li><a href="#">${itemCat1}</a></li> <li><a href="#">${itemCat2}</a></li> <li><a href="#">${itemCat3}</a></li> </ul>
商品详细页是静态页,所以在开发阶段我们可以使用 tomcat 来进行测试。部署在生产环境是部署在 Nginx 中。