尚品汇-首页三级分类实现-nginx静态代理生成的静态页面(二十六)
目录:
(1)问题详解
(2)首页商品分类实现
(3)修改web-all模块
(4)页面渲染
(1)问题详解
(2)首页商品分类实现
前面做了商品详情,我们现在来做首页分类,我先看看京东的首页分类效果,我们如何实现类似效果:
思路:
- 首页属于并发量比较高的访问页面,我看可以采取页面静态化方式实现,或者把数据放在缓存中实现
- 我们把生成的静态文件可以放在nginx访问或者放在web-all模块访问
(3)修改web-all模块
修改pom.xml
<dependencies>
<dependency><groupId>com.atguigu.gmall</groupId><artifactId>service-item-client</artifactId><version>1.0</version></dependency><dependency><groupId>com.atguigu.gmall</groupId><artifactId>service-product-client</artifactId><version>1.0</version></dependency></dependencies>
由于商品分类信息在service-product模块,我们在该模块封装数据,数据结构为父子层级
商品分类保存在base_category1、base_category2和base_category3表中,由于需要静态化页面,我们需要一次性加载所有数据,前面我们使用了一个视图base_category_view,所有我从视图里面获取数据,然后封装为父子层级
视图包含三级分类的所有数据
数据结构如下:json 数据结构
[{"index": 1,"categoryChild": [{"categoryChild": [{"categoryName": "电子书", # 三级分类的name"categoryId": 1},{"categoryName": "网络原创", # 三级分类的name"categoryId": 2},...],"categoryName": "电子书刊", #二级分类的name"categoryId": 1},...],"categoryName": "图书、音像、电子书刊", # 一级分类的name"categoryId": 1},...
"index": 2,"categoryChild": [{"categoryChild": [{"categoryName": "超薄电视", # 三级分类的name"categoryId": 1},{"categoryName": "全面屏电视", # 三级分类的name"categoryId": 2},...],"categoryName": "电视", #二级分类的name"categoryId": 1},...],"categoryName": "家用电器", # 一级分类的name"categoryId": 2}
]
二级:
三级:
ManageService接口
/*** 获取全部分类信息* @return*/
List<JSONObject> getBaseCategoryList();
ManageServiceImpl 实现类
com.alibaba.fastjson
三级分类视图: 一级,二级分类有重复的,三级分类没有重复的
发现有重复数据,需要去重:
使用distinct一次只能去重一个字段
使用分组去重,但是分组后,就不好获取其他数据了
所以最后是在java中利用api处理重复数据了
stream中的API有一个可以实现分组
Map<Long, List<BaseCategoryView>> category1Map =baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));
一级分类:
二级分类:
三级分类:没有重复的不需要分组
@Override
@GmallCache(prefix = "basecategoryList:")
public List<JSONObject> getBaseCategoryList() {// 声明几个json 集合ArrayList<JSONObject> list = new ArrayList<>();// 声明获取所有分类数据集合List<BaseCategoryView> baseCategoryViewList = baseCategoryViewMapper.selectList(null);// 循环上面的集合并安一级分类Id 进行分组 value 是一级分类对应的所有数据Map<Long, List<BaseCategoryView>> category1Map = baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));//定义一级分类的序号int index = 1;// 获取一级分类下所有数据for (Map.Entry<Long, List<BaseCategoryView>> entry1 : category1Map.entrySet()) {// 每一个entry 是一个键值对,key 一级分类的id value一级分类的所有数据// 获取一级分类IdLong category1Id = entry1.getKey();// 获取一级分类下面的所有集合List<BaseCategoryView> category2List1 = entry1.getValue();//category2List1.get(0).getCategory1Name() 一级分类的名字,一级分类的名字都是一样的,随便获取一个JSONObject category1 = new JSONObject();category1.put("index", index);category1.put("categoryId",category1Id);// 一级分类名称category1.put("categoryName",category2List1.get(0).getCategory1Name());// 变量迭代index++;// 循环获取二级分类数据Map<Long, List<BaseCategoryView>> category2Map = category2List1.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));// 声明二级分类对象集合List<JSONObject> category2Child = new ArrayList<>();// 循环遍历for (Map.Entry<Long, List<BaseCategoryView>> entry2 : category2Map.entrySet()) {// 获取二级分类IdLong category2Id = entry2.getKey();// 获取二级分类下的所有集合List<BaseCategoryView> category3List = entry2.getValue();// 声明二级分类对象JSONObject category2 = new JSONObject();category2.put("categoryId",category2Id);category2.put("categoryName",category3List.get(0).getCategory2Name());List<JSONObject> category3Child = new ArrayList<>();// 循环三级分类数据category3List.stream().forEach(category3View -> {JSONObject category3 = new JSONObject();category3.put("categoryId",category3View.getCategory3Id());category3.put("categoryName",category3View.getCategory3Name());category3Child.add(category3);});// 将三级数据放入二级里面category2.put("categoryChild",category3Child);// 添加到二级分类集合category2Child.add(category2);}// 将二级数据放入一级里面category1.put("categoryChild",category2Child);list.add(category1);}return list;
}
控制器ProductApiController
/*** 首页数据获取三级分类信息* @return*/
@GetMapping("getBaseCategoryList")
public Result getBaseCategoryList(){List<JSONObject> list = manageService.getBaseCategoryList();return Result.ok(list);
}
成功的添加到了Reids缓存
封装远程调用:
service-product-client添加接口
ProductFeignClient
/*** 获取全部分类信息* @return*/
@GetMapping("/api/product/getBaseCategoryList")
Result getBaseCategoryList();
降级函数
ProductDegradeFeignClient
@Override
public Result getBaseCategoryList() {return Result.fail();
}
(4)页面渲染
创建indexController:
页面模版渲染
第一种缓存渲染方式:
package com.atguigu.gmall.all.controller;@Controller
public class IndexController {@Autowiredprivate ProductFeignClient productFeignClient;@GetMapping({"/","index.html"})public String index(HttpServletRequest request){// 获取首页分类数据Result result = productFeignClient.getBaseCategoryList();request.setAttribute("list",result.getData());return "index/index";}
}
可以额外添加功能:我们这里没做
第二种:生成页面,nginx做静态代理方式:
@Autowiredprivate TemplateEngine templateEngine; @GetMapping("createIndex")
@ResponseBody
public Result createIndex(){// 获取后台存储的数据Result result = productFeignClient.getBaseCategoryList();// 设置模板显示的内容Context context = new Context();context.setVariable("list",result.getData());// 定义文件输入位置FileWriter fileWriter = null;try {fileWriter = new FileWriter("D:\\index.html");} catch (IOException e) {e.printStackTrace();}// 调用process();方法创建模板templateEngine.process("index/index",context,fileWriter);return Result.ok();
}
将生成的静态页面与css 放入html 中即可!
页面生成了不能直接访问,他需要css,js..
复制项目里的css..
然后再双击index,就可以看了:
nginx先试用Windows版本的nginx
修改本地的nginx配置文件:添加:
把生成的静态页面放到nginx目录下:
启动nginx
直接访问nginx的端口号:
就可以通过nginx实现代理访问静态资源 ,使用nginx他抗并发的能力非常强