需求:
網站首頁 - 商品分類展示( 使用緩存 - 提高效率 - 提高用戶滿意度 )
1.實現效果如下: (京東-首頁分類)
一、需求分析
1.表關係如下: ( 自關聯表 - tb_item_cat )
parent_id:
一級分類: 默認是 0
二級分類: 一級分類的id
三級分類: 二級分類的id
2.如何接收返回的JSON數據(三級分類數據)? ★
分析:
一級分類 -> 包含二級分類 -> 包含三級分類! ( 一對多對多 )
①自關聯表 -> 自關聯POJO對象! ( 本文使用 )
②Map集合接收 -> Map<String , Map<String , List>>
二、後端實現( 分佈式框架 )
1.數據層 - Mybatis
注: 只添加了特殊的sql語句 , 其餘都是逆向工程!
1.1 ItemCatDao.java
public interface ItemCatDao {
// 根據父類id - 0 , 查詢分類信息
List<ItemCat> selectByParentId(@Param("id") Long id);
}
1.2 ItemCatDao.xml ( 原因: 固定一級分類的長度 )
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.xxx.dao.item.ItemCatDao" >
<!-- 查詢三級分類信息 -->
<select id="selectByParentId" resultType="cn.xxx.pojo.item.ItemCat">
SELECT * FROM tb_item_cat WHERE parent_id = #{id} LIMIT 15
</select>
</mapper>
2.業務層 - Spring
2.1 ItemCatService.java
public interface ItemCatService {
List<ItemCat> findByItemCat3(Long parentId);
}
2.2 ItemCatServiceImpl.java ( 重點 )
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Resource
private ItemCatDao itemCatDao;
@Resource
private RedisTemplate<String,Object> redisTemplate;
@Override
public List<ItemCat> findByItemCat3(Long parentId01) {
// 1.先從redis緩存中 , 獲取三級分類信息!
List<ItemCat> itemCat01List = (List<ItemCat>) redisTemplate.boundValueOps("itemCat03").get();
// 2.若緩存中沒有數據 , 從數據庫中查詢( 並放到緩存中 )
if (itemCat01List==null){
// 緩存穿透 -> 請求排隊等候.
synchronized (this){
// 進行二次校驗?
itemCat01List = (List<ItemCat>) redisTemplate.boundValueOps("itemCat03").get();
if (itemCat01List==null){
// 創建一個集合 , 存放一級分類
itemCat01List = new ArrayList<>();
// 根據parent_id = 0 , 獲取一級分類信息!
List<ItemCat> itemCatList = itemCatDao.selectByParentId(parentId01);
for (ItemCat itemCat : itemCatList) {
// 設置一級分類信息!
ItemCat itemCat01 = new ItemCat();
itemCat01.setId(itemCat.getId());
itemCat01.setName(itemCat.getName());
itemCat01.setParentId(itemCat.getParentId());
// 根據一級分類的id -> 找到對應的二級分類!
List<ItemCat> itemCatList02 = new ArrayList<>();
ItemCatQuery itemCatQuery02 = new ItemCatQuery();
itemCatQuery02.createCriteria().andParentIdEqualTo(itemCat.getId());
List<ItemCat> itemCat02List = itemCatDao.selectByExample(itemCatQuery02);
for (ItemCat itemCat2 : itemCat02List) {
// 設置二級分類信息!
ItemCat itemCat02 = new ItemCat();
itemCat02.setId(itemCat2.getId());
itemCat02.setName(itemCat2.getName());
itemCat02.setParentId(itemCat2.getParentId());
// 根據二級分類的id -> 找到對應的三級分類!
List<ItemCat> itemCatList03 = new ArrayList<>();
ItemCatQuery itemCatQuery03 = new ItemCatQuery();
itemCatQuery03.createCriteria().andParentIdEqualTo(itemCat02.getId());
List<ItemCat> itemCat03List = itemCatDao.selectByExample(itemCatQuery03);
for (ItemCat itemCat3 : itemCat03List) {
itemCatList03.add(itemCat3);
}
itemCat02.setItemCatList(itemCatList03); // 二級分類中 添加 三級分類.
itemCatList02.add(itemCat02); // 添加二級分類.
}
itemCat01.setItemCatList(itemCatList02); // 一級分類中 添加 二級分類!
itemCat01List.add(itemCat01); // 添加一級分類
}
// 將查詢到的數據放入緩存中!
redisTemplate.boundValueOps("itemCat03").set(itemCat01List);
return itemCat01List;
}
}
}
// 3.若緩存中有數據 , 直接返回即可!
return itemCat01List;
}
}
3.視圖層 - SpringMVC
@RestController
@RequestMapping("/itemCat")
public class ItemCatController {
@Reference
private ItemCatService itemCatService;
@RequestMapping("/findByParentId.do")
public List<ItemCat> findByParentId(Long parentId) {
return itemCatService.findByItemCat3(parentId);
}
}
三、前端實現( angularjs )
1.初始化加載方法( 傳遞parent_id = 0 )
ng-init="findByParentId(0);"
2.前端遍歷展示( 鼠標移入移除 )
注: 遍歷名稱可能不一致 , 需要改變!
<div class="yui3-u Left all-sort-list">
<div class="all-sort-list2">
<div class="item {{flag?'hover':''}}" ng-repeat="itemCat1 in list" ng-mouseenter="flag=true"
ng-mouseleave="flag=false">
<h3><a href="">{{itemCat1.name}}</a></h3>
<!--通過三元表達式確定是顯示還是隱藏-->
<div class="item-list clearfix" style="display: {{flag?'block':'none'}}">
<div class="subitem">
<!--遍歷2級分類-->
<dl class="fore1" ng-repeat="itemCat2 in itemCat1.itemCat02List">
<dt><a href="">{{itemCat2.name}}</a></dt>
<dd>
<!--遍歷3級分類-->
<em ng-repeat="itemCat3 in itemCat2.itemCat03List">
<a href="">{{itemCat3.name}}</a>
</em>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>