尚品汇-首页三级分类实现-nginx静态代理生成的静态页面(二十六)

news2024/10/2 10:32:41

目录:

(1)问题详解

(2)首页商品分类实现

(3)修改web-all模块

(4)页面渲染

(1)问题详解

(2)首页商品分类实现

前面做了商品详情,我们现在来做首页分类,我先看看京东的首页分类效果,我们如何实现类似效果:

思路:

  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一级分类的所有数据
        // 获取一级分类Id
        Long 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()) {
            // 获取二级分类Id
            Long 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 {

    @Autowired
    private ProductFeignClient productFeignClient;

    @GetMapping({"/","index.html"})
    public String index(HttpServletRequest request){
      // 获取首页分类数据
       Result result = productFeignClient.getBaseCategoryList();
      request.setAttribute("list",result.getData());
      return "index/index";
  }
}

可以额外添加功能:我们这里没做 

 

第二种:生成页面,nginx做静态代理方式:

 

 @Autowired
 private 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他抗并发的能力非常强

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979274.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【书生大模型实战营(暑假场)】入门任务三 Python 关卡

入门任务二 Python 关卡 参考&#xff1a; 教程任务 1 闯关任务 1.1 使用 Python 实现 wordcount import stringdef wordcount(text):# 去除标点符号text text.translate(str.maketrans(, , string.punctuation))# 转换为小写text text.lower()# 分割字符串成单词列表wo…

CH571F蓝牙orUSB摇杆鼠标

演示视频&#xff1a; 短视频刷个爽 程序基本上是基于官方的例程上改的&#xff0c;用到的例程有&#xff1a;蓝牙的HID_Mouse,USB的CompoundDev&#xff0c;还有ADC&#xff0c;按键中断。 主要原理 就是ADC采集采集摇杆电压&#xff0c;通过蓝牙HID或者USB的HID发送给电脑或…

文心一言 VS 讯飞星火 VS chatgpt (317)-- 算法导论22.3 9题

九、请给出如下猜想的一个反例&#xff1a;如果有向图G包含一条从结点u到结点v的路径&#xff0c;则任何对图G的深度优先搜索都将导致v.d⩽u.f。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 首先&#xff0c;我们需要澄清问题中的几个关键点。在图的深度优先…

想做抖音短视频,视频素材去哪里找啊?

各位抖音上的短视频创作者们&#xff0c;是否曾幻想过自己的作品能够在全网爆火&#xff0c;却常因为缺少那些能够让视频更加生动的素材而感到困扰&#xff1f;不用担心&#xff0c;今天我要为大家介绍几个优秀的视频素材网站&#xff0c;让你的抖音之路顺风顺水&#xff01; …

Linux系统中的高级用户空间与内核空间交互技术

Linux作为一种开源操作系统&#xff0c;具有良好的稳定性、安全性和自定制性&#xff0c;因而在各种设备和场景中得到广泛应用。作为Linux系统的核心组成部分&#xff0c;内核空间与用户空间交互技术对系统性能和功能扩展起着关键作用。本文将深入探讨Linux系统中的高级用户空间…

Vue Vine:带给你全新的 Vue 书写体验!

你好&#xff0c;我是 Kagol&#xff0c;个人公众号&#xff1a;前端开源星球。 上个月和 TinyVue 的小伙伴们一起参加了 VueConf 24 大会&#xff0c;有幸认识沈青川大佬&#xff0c;并了解了他的 Vue Vine 项目&#xff0c;Vue Vine 让你可以在一个文件中通过函数方式定义多…

系统化学习 H264视频编码(05)码流数据及相关概念解读

说明&#xff1a;我们参考黄金圈学习法&#xff08;什么是黄金圈法则?->模型 黄金圈法则&#xff0c;本文使用&#xff1a;why-what&#xff09;来学习音H264视频编码。本系列文章侧重于理解视频编码的知识体系和实践方法&#xff0c;理论方面会更多地讲清楚 音视频中概念的…

Nginx进阶-常见配置(二)

一、nginx 日志配置 nginx 日志介绍 nginx 有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志, 所需日志模块 ngx_http_log_module 的支持&#xff0c;日志格式通过 log_format 命令来定义&#xff0c;日志对于统计和排错是非常有利的&#xff0c;下面总…

【TwinCAT3教程】TwinCAT3 PLC 简单程序编写与调试

一、PLC 简单程序编写 1.1 新建TwinCAT3项目 (1)打开 TwinCAT 3,点击 New TwinCAT Project 新建 TC3 项目。 (2)选择 TwinCAT Project,输入项目名称和项目保存路径,然后点击确定。 1.2 添加PLC项目 1.2.1 步骤 (1)在树形资源管理器右键点击 PLC,选择 添加新项 新…

STM32F28335实验:继电器

继电器控制电机&#xff1a; 5s启动 5s停止 循环 管脚图&#xff1a; 管脚用的是GPIO15 驱动&#xff1a; beep.c /** leds.c** Created on: 2024年8月2日* Author: Administrator*/#include<relay.h>/***************************************************…

【算法设计题】查找给定结点的双亲结点(二叉树),第3题(C/C++)

目录 第3题 查找给定结点的双亲结点&#xff08;二叉树&#xff09; 得分点&#xff08;必背&#xff09; 题解 定义函数和初始化变量&#xff1a; 处理特殊情况&#xff1a; 遍历树&#xff1a; 中序遍历左子树&#xff1a; 处理右子树&#xff1a; 返回结果&#x…

LSTM实战之预测股票

&#x1f4c8; 用PyTorch搭建LSTM模型&#xff0c;轻松预测股票价格&#xff01;&#x1f680; Hey小伙伴们&#xff0c;今天给大家带来一个超级实用的项目教程——如何用PyTorch和LSTM模型来预测股票价格&#xff01;&#x1f31f; &#x1f50d; 项目背景 我们都知道股市是…

《Unity3D网络游戏实战》学习与实践--制作一款大乱斗游戏

角色类 基类Base Human是基础的角色类&#xff0c;它处理“操控角色”和“同步角色”的一些共有功能&#xff1b;CtrlHuman类代表“操控角色”​&#xff0c;它在BaseHuman类的基础上处理鼠标操控功能&#xff1b;SyncHuman类是“同步角色”类&#xff0c;它也继承自BaseHuman&…

MySQL的数据结构B+tree以及SQL优化

首先呢&#xff0c;我们知道MySQL的数据结构为Btree,那么其结构究竟是什么样的&#xff0c;为什么选择Btree&#xff0c;而不选择Btree。下面我们从其结构分析 1.Btree平衡多路查找树 B-tree结构的数据可以让系统高效的找到数据所在的磁盘块。为了描述B-Tree,首先定义一条记录…

入门mem0.NET

入门mem0.NET 安装包 如果你的项目使用了EntityFrameworkCore,那么你可以跟随这个教程走 <ItemGroup><PackageReference Include"mem0.NET" Version"0.1.7" /><PackageReference Include"mem0.NET.Qdrant" Version"0.1.7…

云动态摘要 2024-08-04

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 数据库上云优选 阿里云 2024-07-04 RDS、PolarDB、Redis、MongoDB 全系产品新用户低至首年6折起&#xff01; [免费体验]智能助手ChatBI上线 腾讯云 2024-07-02 基于混元大模型打造&…

java之IO篇——File、字节流、字符流

前言 IO流是用于读写文件中的数据&#xff0c;要读写文件之前可以创建文件获取文件对象再创建IO流&#xff0c;正文会先介绍File类&#xff0c;通过File类的构造方法获取文件的对象&#xff0c;创建文件或目录以及File类的一些方法获取文件对象的属性。后面还介绍了相关的IO流体…

Radxa ROCK 3C开发板编译Opencv,支持调用树莓派摄像头模块V2

目录 1、ROCK 3C和树莓派摄像头模块V2介绍2、ROCK 3C在rsetup开启支持3、测试指令4、编译Opencv4.1 增加swap&#xff0c;确保内存够用4.2 安装依赖和下载opencv4.3 编译参考链接 5、使用opencv调用树莓派摄像头模块V2 1、ROCK 3C和树莓派摄像头模块V2介绍 ROCK 3C 是一款基于…

刷题篇 - 01

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目一&#xff1a; 387. 字符串中的第一个唯一字符 - 力扣&#xff08;LeetCode&#xff09; public int firstUniqC…

订单定时状态处理业务(SpringTask)

文章目录 概要整体架构流程技术细节小结 概要 订单定时状态处理通常涉及到对订单状态进行定期检查&#xff0c;并根据订单的状态自动执行某些操作&#xff0c;比如关闭未支付的订单、自动确认收货等. 需求分析以及接口设计 需求分析 用户下单后可能存在的情况&#xff1a; …