需求分析
根據搜索關鍵字,頁面顯示相關的商品分類,根據相關的商品分類藉助分類模板從後臺查詢出品牌、規格以及規格選項進行顯示
爲了應對高併發,將根據相關的商品分類藉助分類模板從後臺查詢出品牌、規格以及規格選項保存到redis數據庫中,查詢的時候不再從關係數據庫中查詢,直接從更快的redis數據庫中查詢
涉及到的數據庫表有三個:
緩存實現
緩存這些數據要在運營商後臺管理中進行(因爲運營商後臺管理對這些數據進行增刪改查的操作),查詢這些數據是在搜索服務中調用,然後提供給搜索頁面
在原來的分類查詢業務的基礎上加入商品分類緩存
- 加入緩存
- 在商品搜索模塊,需要根據 分類名 得到模板Id
- 因此,在操作分類的模塊中,我們提前將分類數據緩存起來
- 緩存規則:分類名作爲 小鍵, 以模板id作爲值
@Autowired
private RedisTemplate redisTemplate;
public List<TbItemCat> findByParentId(Long pId) {
TbItemCatExample example = new TbItemCatExample();
Criteria criteria = example.createCriteria();
criteria.andParentIdEqualTo(pId);
List<TbItemCat> itemCats = itemCatMapper.selectByExample(example);
//加入緩存
Set keys = redisTemplate.boundHashOps("categoryList").keys();
if (keys!=null && keys.size()>0){
}else {//沒有任何的鍵,開始緩存
List<TbItemCat> allCats = findAll();
for (TbItemCat cat : allCats) {
redisTemplate.boundHashOps("categoryList").put(cat.getName(),cat.getTypeId());
}
System.out.println(">>>>>添加分類信息至緩存");
}
return itemCats;
}
在原來的分類模板查詢業務的基礎上加入商品分類模板緩存
- 商品搜索模塊,需要根據模板id,得到品牌、規格列表
- 所以,在此處,我們將模板的信息加入緩存
- 緩存的規則:
- 針對品牌:取一個品牌的大鍵brandList,然後以模板id作爲小鍵,品牌列表作爲值
- 針對規格:取一個規格的大鍵specList,然後以模板id作爲小鍵,規格 + 規格選項 的列表作爲值
@Autowired
private RedisTemplate redisTemplate;
public PageResult findPage(TbTypeTemplate typeTemplate, int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
TbTypeTemplateExample example=new TbTypeTemplateExample();
Criteria criteria = example.createCriteria();
if(typeTemplate != null){
if(typeTemplate.getName() != null && typeTemplate.getName().length() > 0){
criteria.andNameLike("%" + typeTemplate.getName() + "%");
} if(typeTemplate.getSpecIds() != null && typeTemplate.getSpecIds().length() > 0){
criteria.andSpecIdsLike("%" + typeTemplate.getSpecIds() + "%");
} if(typeTemplate.getBrandIds() != null && typeTemplate.getBrandIds().length() > 0){
criteria.andBrandIdsLike("%" + typeTemplate.getBrandIds() + "%");
} if(typeTemplate.getCustomAttributeItems() != null && typeTemplate.getCustomAttributeItems().length() > 0){
criteria.andCustomAttributeItemsLike("%" + typeTemplate.getCustomAttributeItems() + "%");
}
}
Page<TbTypeTemplate> page= (Page<TbTypeTemplate>)typeTemplateMapper.selectByExample(example);
List<TbTypeTemplate> list = null;
Set brandKeys = redisTemplate.boundHashOps("brandList").keys();
if (brandKeys!=null && brandKeys.size()>0){
}else{//緩存信息中沒有鍵,開始緩存
list = findAll();
for (TbTypeTemplate template : list) {
List<Map> brands = JSON.parseArray(template.getBrandIds(), Map.class);
redisTemplate.boundHashOps("brandList").put(template.getId(),brands);
}
}
Set specKeys = redisTemplate.boundHashOps("specList").keys();
if (specKeys!=null && specKeys.size()>0){
}else{//緩存信息中沒有鍵,開始緩存
if (list==null){
list = findAll();
}
for (TbTypeTemplate template : list) {
List<Map> specMaps = findSpecAndOptionsByTypeTemplateId(template.getId());
redisTemplate.boundHashOps("specList").put(template.getId(),specMaps);
}
System.out.println(">>>>>添加規格列表至緩存");
}
return new PageResult(page.getTotal(), page.getResult());
}
public List<Map> findSpecAndOptionsByTypeTemplateId(Long typeTemplateId) {
TbTypeTemplate tbTypeTemplate = typeTemplateMapper.selectByPrimaryKey(typeTemplateId);
// List的格式:[{"id":26,"text":"尺碼"},{"id":29,"text":"顏色"}]
List<Map> maps = JSON.parseArray(tbTypeTemplate.getSpecIds(), Map.class);
// map的格式:{"id":26,"text":"尺碼"}
for (Map map : maps) {
TbSpecificationOptionExample example = new TbSpecificationOptionExample();
TbSpecificationOptionExample.Criteria criteria = example.createCriteria();
criteria.andSpecIdEqualTo(Long.parseLong(map.get("id")+""));
List<TbSpecificationOption> specificationOptions = specificationOptionMapper.selectByExample(example);
map.put("options",specificationOptions);
// map的新格式變爲:{"id":26,"text":"尺碼", "options": [{id: 24, optionName: ""56寸}]}
}
return maps;
}
前端接口查詢緩存的實現
@Autowired
private RedisTemplate redisTemplate;
public Map<String, Object> search(Map searchMap) {
Map<String,Object> map = new HashMap<>();
//關鍵字高亮
highlight(searchMap,map);
//根據關鍵字獲取分類
categoryList(searchMap,map);
// 如果頁面傳遞過來了分類名,就不使用默認的第一個分類查詢品牌、規格了
if (!"".equals(searchMap.get("category"))){
brandAndSpecListSearch((String)searchMap.get("category"),map);
}else {
//查詢品牌規格列表
List<String> categoryList = (List<String>) map.get("categoryList");
if (categoryList.size()>0){
brandAndSpecListSearch(categoryList.get(0),map);
}
}
return map;
}
測試
控制檯打印
搜索之前
搜索之後
{
"categoryList": [
"電子書",
"牙膏/牙粉",
"手機"
],
"specList": [
{
"options": [
{
"id": 98,
"optionName": "移動3G",
"orders": 1,
"specId": 27
},
{
"id": 99,
"optionName": "移動4G",
"orders": 2,
"specId": 27
},
{
"id": 100,
"optionName": "聯通3G",
"orders": 3,
"specId": 27
},
{
"id": 101,
"optionName": "聯通4G",
"orders": 4,
"specId": 27
},
{
"id": 112,
"optionName": "電信3G",
"orders": 5,
"specId": 27
},
{
"id": 113,
"optionName": "電信4G",
"orders": 6,
"specId": 27
},
{
"id": 114,
"optionName": "移動2G",
"orders": 7,
"specId": 27
},
{
"id": 115,
"optionName": "聯通2G",
"orders": 8,
"specId": 27
},
{
"id": 116,
"optionName": "電信2G",
"orders": 9,
"specId": 27
},
{
"id": 117,
"optionName": "雙卡",
"orders": 10,
"specId": 27
}
],
"id": 27,
"text": "網絡"
},
{
"options": [
{
"id": 118,
"optionName": "16G",
"orders": 1,
"specId": 32
},
{
"id": 119,
"optionName": "32G",
"orders": 2,
"specId": 32
},
{
"id": 120,
"optionName": "64G",
"orders": 3,
"specId": 32
},
{
"id": 121,
"optionName": "128G",
"orders": 4,
"specId": 32
}
],
"id": 32,
"text": "機身內存"
}
],
"brandList": [
{
"id": 1,
"text": "聯想"
},
{
"id": 3,
"text": "三星"
},
{
"id": 2,
"text": "華爲"
},
{
"id": 5,
"text": "OPPO"
},
{
"id": 4,
"text": "小米"
},
{
"id": 9,
"text": "蘋果"
},
{
"id": 8,
"text": "魅族"
},
{
"id": 6,
"text": "360"
},
{
"id": 10,
"text": "VIVO"
},
{
"id": 11,
"text": "諾基亞"
},
{
"id": 12,
"text": "錘子"
}
],
"rows": [
{
"barcode": null,
"brand": "聯想",
"cartThumbnail": null,
"category": "電子書",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 149187842867963,
"id": 1369288,
"image": "http://192.168.2.123/group1/M00/00/00/wKgCe17TrT-AfRG1AADFbi0oR0A460.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 0,
"sellPoint": null,
"seller": "測試",
"sellerId": null,
"spec": null,
"specMap": {
"jishenneicun": "16G",
"wangluo": "移動4G"
},
"status": null,
"stockCount": null,
"title": "<span style='color:red'>測試</span>電子書nullnull",
"updateTime": "2020-06-01 10:56:47"
},
{
"barcode": null,
"brand": "聯想",
"cartThumbnail": null,
"category": "電子書",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 149187842867963,
"id": 1369289,
"image": "http://192.168.2.123/group1/M00/00/00/wKgCe17TrT-AfRG1AADFbi0oR0A460.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 0,
"sellPoint": null,
"seller": "測試",
"sellerId": null,
"spec": null,
"specMap": {
"jishenneicun": "16G",
"wangluo": "雙卡"
},
"status": null,
"stockCount": null,
"title": "<span style='color:red'>測試</span>電子書nullnull",
"updateTime": "2020-06-01 10:56:47"
},
{
"barcode": null,
"brand": "聯想",
"cartThumbnail": null,
"category": "電子書",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 149187842867963,
"id": 1369290,
"image": "http://192.168.2.123/group1/M00/00/00/wKgCe17TrT-AfRG1AADFbi0oR0A460.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 0,
"sellPoint": null,
"seller": "測試",
"sellerId": null,
"spec": null,
"specMap": {
"jishenneicun": "16G",
"wangluo": "移動3G"
},
"status": null,
"stockCount": null,
"title": "<span style='color:red'>測試</span>電子書nullnull",
"updateTime": "2020-06-01 10:56:47"
},
{
"barcode": null,
"brand": "小米",
"cartThumbnail": null,
"category": "電子書",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 149187842867964,
"id": 1369287,
"image": "http://192.168.2.123/group1/M00/00/00/wKgCe17TsLWAAWwDAADFbi0oR0A073.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 30,
"sellPoint": null,
"seller": "測試",
"sellerId": null,
"spec": null,
"specMap": null,
"status": null,
"stockCount": null,
"title": "電子書2",
"updateTime": "2020-06-01 10:56:17"
},
{
"barcode": null,
"brand": "魅族",
"cartThumbnail": null,
"category": "牙膏/牙粉",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 149187842867955,
"id": 1369279,
"image": "http://192.168.25.133/group1/M00/00/00/wKgZhVnGZfWAaX2hAAjlKdWCzvg173.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 100,
"sellPoint": null,
"seller": "千度商店",
"sellerId": null,
"spec": null,
"specMap": null,
"status": null,
"stockCount": null,
"title": "<span style='color:red'>測試</span>商品110",
"updateTime": "2017-09-23 21:47:51"
},
{
"barcode": null,
"brand": "中國移動",
"cartThumbnail": null,
"category": "手機",
"categoryid": null,
"costPirce": null,
"createTime": null,
"goodsId": 1,
"id": 1039296,
"image": "http://img12.360buyimg.com/n1/s450x450_jfs/t3034/299/2060854617/119711/577e85cb/57d11b6cN1fd1194d.jpg",
"isDefault": null,
"itemSn": null,
"marketPrice": null,
"num": null,
"price": 2699,
"sellPoint": null,
"seller": "中國移動",
"sellerId": null,
"spec": null,
"specMap": {
"jishenneicun": "16G",
"wangluo": "雙卡"
},
"status": null,
"stockCount": null,
"title": "合約惠機<span style='color:red'>測試</span>手機(請勿下單)",
"updateTime": "2015-03-08 21:33:18"
}
]
}