品優購專案記錄:day12
今日目標:
(1)掌握 Freemarker常用的指令與內建函式
(2)完成商品詳細頁的資料顯示
(3)完成商品詳細頁的動態顯示
(4)完成商品詳細頁讀取SKU資訊的業務邏輯
(5)完成商品稽核呼叫功能
目錄
1、商品詳細頁-資料顯示
準備工作:搭建工程(page-interface、page-service),並編寫相關配置和引入相關依賴
1.1 配置
(1)配置Freemarker的bean,在WEB-INF下建立ftl資料夾
<!-- 配置freemarker-bean --> <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>
(2)配置存放商品詳細頁的位置,注意保證資料夾存在,還需要將樣式檔案拷入該目錄
## 商品詳細頁存放位置
PAGE_DIR=D:\\item\\
1.2 服務層
(1)page-interface,編寫ItemPageService介面
package com.pinyougou.page.service; /** * 商品詳細頁靜態化 * Author xushuai * Description */ public interface ItemPageService { /** * 生成商品詳細頁 * * @param goodsId 商品id * @return boolean */ boolean genItemPage(Long goodsId); }
(2)page-service,編寫ItemPageServiceImpl實現
package com.pinyougou.page.service.impl; import com.alibaba.dubbo.config.annotation.Service; import com.pinyougou.mapper.TbGoodsDescMapper; import com.pinyougou.mapper.TbGoodsMapper; import com.pinyougou.page.service.ItemPageService; import com.pinyougou.pojo.TbGoods; import com.pinyougou.pojo.TbGoodsDesc; import freemarker.template.Configuration; import freemarker.template.Template; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import java.io.FileWriter; import java.io.Writer; import java.util.HashMap; import java.util.Map; /** * 商品詳情頁靜態化實現 * Author xushuai * Description */ @Service @Transactional public class ItemPageServiceImpl implements ItemPageService { @Autowired private FreeMarkerConfigurer FreeMarkerConfigurer; @Autowired private TbGoodsMapper goodsMapper; @Autowired private TbGoodsDescMapper goodsDescMapper; @Value("PAGE_DIR") private String PAGE_DIR; @Override public boolean genItemPage(Long goodsId) { try { // 查詢商品基本資訊和商品擴充套件資訊 TbGoods tbGoods = goodsMapper.selectByPrimaryKey(goodsId); TbGoodsDesc tbGoodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId); // 將查詢到的資料封裝到Map Map<String, Object> data = new HashMap<>(); data.put("goods", tbGoods); data.put("goodsDesc", tbGoodsDesc); // 建立檔案輸出流 Writer out = new FileWriter(PAGE_DIR + goodsId + ".html"); // 使用模板生成商品詳細頁 Configuration configuration = FreeMarkerConfigurer.getConfiguration(); Template template = configuration.getTemplate("item.ftl"); template.process(data, out); return true; } catch (Exception e) { e.printStackTrace(); } return false; } }
1.3 基本測試
(1)拷貝靜態原型的item.html作為模板
(2)修改模板中的商品標題為插值:${goods.goodsName}
(3)測試
1.4 替換模板基本資訊為插值
(1)將item.ftl中的頭部和尾部分別放入另外兩個模板中,在item.ftl中使用<#include>匯入
(2)將商品基本資訊使用插值替換到模板中
1.5 替換模板圖片列表
(1)因為圖片列表為json串,我們需要將json串轉換為物件
<#-- 處理圖片列表Json串 -->
<#assign imageList = goodsDesc.itemImages?eval>
(2)遍歷生成的物件,展示圖片,注意限制圖片放大鏡的最大寬高
(3)效果
1.6 生成擴充套件屬性列表
(1)將擴充套件資訊的json串轉換為物件
<#-- 處理擴充套件屬性Json串 -->
<#if goodsDesc.customAttributeItems??>
<#assign attrList = goodsDesc.customAttributeItems?eval>
</#if>
(2)遍歷展示擴充套件資訊
(3)效果
1.7 生成規格列表
(1)將規格列表資訊的json串轉換為物件
<#-- 處理規格列表Json串 -->
<#if goodsDesc.specificationItems??>
<#assign specList = goodsDesc.specificationItems?eval>
</#if>
(2)展示規格資訊
(3)效果
1.8 生成商品型別麵包屑
(1)服務層實現(page-interface),修改ItemPageServiceImpl中的程式碼,主要為:查詢分類資訊
package com.pinyougou.page.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.mapper.TbGoodsDescMapper;
import com.pinyougou.mapper.TbGoodsMapper;
import com.pinyougou.mapper.TbItemCatMapper;
import com.pinyougou.page.service.ItemPageService;
import com.pinyougou.pojo.TbGoods;
import com.pinyougou.pojo.TbGoodsDesc;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
/**
* 商品詳情頁靜態化實現
* Author xushuai
* Description
*/
@Service
@Transactional
public class ItemPageServiceImpl implements ItemPageService {
@Autowired
private FreeMarkerConfigurer FreeMarkerConfigurer;
@Autowired
private TbGoodsMapper goodsMapper;
@Autowired
private TbGoodsDescMapper goodsDescMapper;
@Autowired
private TbItemCatMapper itemCatMapper;
@Value("${PAGE_DIR}")
private String PAGE_DIR;
@Override
public boolean genItemPage(Long goodsId) {
try {
// 獲取資料
Map<String, Object> data = getDataMap(goodsId);
// 建立檔案輸出流
Writer out = new FileWriter(PAGE_DIR + goodsId + ".html");
// 使用模板生成商品詳細頁
Configuration configuration = FreeMarkerConfigurer.getConfiguration();
Template template = configuration.getTemplate("item.ftl");
template.process(data, out);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 獲取模板需要的資料
*
* @param goodsId 商品ID
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
private Map<String, Object> getDataMap(Long goodsId) {
Map<String, Object> data = new HashMap<>();
// 查詢商品基本資訊和商品擴充套件資訊
TbGoods tbGoods = goodsMapper.selectByPrimaryKey(goodsId);
TbGoodsDesc tbGoodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId);
// 查詢商品分類資訊
String category1 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory1Id()).getName();
String category2 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory2Id()).getName();
String category3 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id()).getName();
// 將查詢到的資料封裝到Map
data.put("goods", tbGoods);
data.put("goodsDesc", tbGoodsDesc);
data.put("category1", category1);
data.put("category2", category2);
data.put("category3", category3);
return data;
}
}
(2)替換模板中的文字
(3)效果
2、商品詳細頁-前端邏輯
2.1 數量的加減
(1)拷貝相關的JS檔案到存放商品詳情頁的目錄中
(2)在js目錄中新建controller資料夾,編寫itemController.js檔案
app.controller('itemController', function ($scope) {
// 數量
$scope.num = 1;
// 增加數量
$scope.incrNum = function() {
$scope.num ++;
}
// 減少數量
$scope.decrNum = function() {
if($scope.num > 1) {
$scope.num --;
}
}
});
(2)修改模板,在模板中引入相關JS檔案和基本指令
(3)數量輸入框繫結變數,+號和-號繫結單擊事件
2.2 規格選擇
(1)在itemController.js中新增方法
// 選中的規格資料
$scope.specificationItems = {};
// 點選選中規格
$scope.selectSpec = function(name, value) {
// 設定給規格資料
$scope.specificationItems[name] = value;
}
// 判斷當前規格是否被選中
$scope.isSelected = function(name, value) {
if ($scope.specificationItems[name] == value) {
return true;
} else {
return false;
}
}
(2)模板中繫結變數和單擊事件
(3)效果
3、商品詳細頁-讀取SKU資訊
3.1 服務層實現(page-service)
(1)修改ItemPageServiceImpl中的getDataMap方法,新增獲取SKU列表資料的邏輯
(2)在頁面中將獲取到的SKU列表資料,生成變數,以後訪問都通過訪問這個變數
<script>
var skuList = [
<#list itemList as item>
{
"id" : ${item.id?c},
"title" : "${item.title!''}",
"price" : ${item.price?c},
"spec" : ${item.spec}
},
</#list>
];
</script>
(3)測試效果
3.2 載入預設的SKU標題和價格
(1)在itemController.js中新增方法
// 當前選擇SKU資訊
$scope.sku={};
// 載入預設的SKU資訊
$scope.loadSku = function() {
// 將skuList中的預設SKU資訊賦給當前選擇的SKU資訊
$scope.sku = skuList[0];
}
(2)在模板標題和價格處,繫結變數
(3)預設選中預設的規格,修改loadSku方法
(4)效果
3.3 選擇規格載入對應的標題和價格
(1)在itemController.js中新增方法
// 判斷兩個物件是否內容相同
$scope.matchObject = function(object1, object2) {
for (var key in object1) {
// 校驗當前鍵的值是否一致
if (object1[key] != object2[key]) {
return false;
}
}
for (var key in object2) {
// 校驗當前鍵的值是否一致
if (object2[key] != object1[key]) {
return false;
}
}
// 內容相同
return true;
}
// 獲取當前選中的SKU
findSku = function() {
for (var i = 0; i < skuList.length; i++) {
if ($scope.matchObject($scope.specificationItems,skuList[i].spec)) {// 規格匹配
// 當前迴圈到的sku為選中的sku
$scope.sku = skuList[i];
return ;
}
}
}
(2)在選擇規格時,改變標題和價格,即在selectSpec中呼叫findSku方法
(3)效果
3.4 預留加入購物車方法
(1)在itemController.js中新增方法
// 加入商品到購物車
$scope.addToCart = function() {
alert("SKU:" + $scope.sku.id + "加入購物車成功,購買數量為:" + $scope.num);
}
(2)加入購物車按鈕,繫結事件
(3)效果
4、稽核商品生成商品詳細頁
4.1 控制層(manager-web)
(1)修改GoodsController中的updateStatus方法,新增邏輯
其他:與搜尋模組對接
1、配置Nginx
(1)修改生成靜態網頁的位置(page-service)
## 商品詳細頁存放位置
PAGE_DIR=E:\\temp\\freemarker\\
(2)將資原始檔放入該資料夾中
(3)配置nginx.conf配置檔案(windows版,測試用)
3、對接
(1)修改圖片連結地址