day06:缓存商品、购物车


缓存菜品

问题说明

用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户访问量比较大,数据库访问压力随之增大。
image.png
结果:系统响应慢,用户体验差

实现思路

通过Redis来缓存菜品数据,减少数据库查询操作
image.png
缓存逻辑分析

  • 每个分类下的菜品保存一份缓存数据
  • 数据库中菜品数据有变更时清理缓存数据
    • 数据一致性

保证mysql数据与redis缓存数据一致性的解决方案

  1. 增量同步,数据库增删改什么,redis缓存就增删改什么,实稍微复杂,针对不同的情况处理
  2. 全量同步,将redis的数据删掉,重新将mysql数据写入到缓存(redis推荐这个,比较简单,内存操作很快,性能没什么影响)
    1. 实现步骤:商家执行增删改操作,删除redis数据,下次查询就会重新写入

代码开发

查询缓存实现

@ApiOperation("根据分类id查询菜品")
    @GetMapping("/list")
    public Result<List<DishVO>> findByCategoryId(Long categoryId){

        log.info("根据分类id查询菜品:{}",categoryId);

        //1.构造redis缓存key
        String key = "dish_" + categoryId;

        //2、使用redisTemplate查询缓存这个key数据,返回List<DishVO>
        List<DishVO> dishVOList = (List<DishVO>) redisTemplate.opsForValue().get(key);

        //3.判断dishVOList是否为null
        if (dishVOList == null){
            Dish dish = new Dish();
            dish.setCategoryId(categoryId);
            dish.setStatus(StatusConstant.ENABLE);
            dishVOList = dishService.findByCategoryIdOnUser(dish);

            //写入缓存
            if (dishVOList != null && dishVOList.size() > 0){
                redisTemplate.opsForValue().set(key,dishVOList);
            }
        }


        return Result.success(dishVOList);
    }

增删改保证mysql和redis的数据一致
image.png

缓存套餐

Spring Cache

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要一个简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:

  • EHCache
  • Caffeine
  • Redis

依赖

<dependency>
    <groupId>org.springframework.boot</groupId>   
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.7.3</version>
</dependency>

常用注解:
image.png

  1. @EnableCaching:开启SpringCache注解扫描
  2. @Cacheable:首先会查询缓存是否有数据,如果有直接返回,如果没有执行方法并且将方法返回值写入缓存,缺点:默认执行方法返回值为null,会缓存,导致缓存的数据为null;解决办法:unless,进行条件判断,作用是条件不成立写入缓存;#result是获取方法的返回值对象condition(了解即可),条件成立才写入缓存,但是这个不可以使用#result,无法获取返回值
  3. @CachePut:将方法返回值写入缓存; value:设置缓存名称,一个缓存名称相当于一个分类,这个缓存名称下可以有多个key key: 设置缓存的key 例如: value=“userCache” key=“#user.id” 生成缓存的格式 userCache::1
  4. @CacheEvict: 删除指定的key数据 key:删除指定id的缓存 allEntries:删除所有以userCache前缀的缓存

实现思路

具体的实现思路如下:

  • 导入Spring Cache和Redis相关maven坐标
  • 在启动类上加入@EnableCaching注解,开启缓存注解功能
  • 在用户端接口SetmealController的list方法上加入@Cacheable注解
  • 在管理端接口SetmealController的 save、delete、update、startOrStop等方法上加入@CacheEvict注解

添加购物车

需求分析和设计

生活中的购物车:用于暂时存放所选商品的一种手推车
接口设计
image.png
数据库设计表
image.png

代码开发

如果添加购物车存在的菜品或套餐,只需要在数量上+1,如果不存在,则添加对应的菜品和套餐。

 @Override
    public void insertShopCart(ShoppingCartDTO shoppingCartDTO) {

        ShoppingCart shoppingCart = new ShoppingCart();
        BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
        //查询自己的购物车数据
        shoppingCart.setUserId(BaseContext.getCurrentId());

        //判断当前商品是否在购物车中
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);

        if (shoppingCartList != null && shoppingCartList.size() == 1){
            //如果已存在,就更新数量,数量加1
            shoppingCart = shoppingCartList.get(0);
            shoppingCart.setNumber(shoppingCart.getNumber() + 1);
            ShoppingCartMapper.updateNumberById(shoppingCart);
        }else {
            //如果不存在,插入数据,数量就是1
            Long dishId = shoppingCart.getDishId();
            if (dishId != null){
                //添加到购物车的是菜品
                DishVO dishVO = dishMapper.findById(dishId);
                shoppingCart.setName(dishVO.getName());
                shoppingCart.setImage(dishVO.getImage());
                shoppingCart.setAmount(dishVO.getPrice());

            }else {
                //添加到购物车的是套餐
                SetmealVO setmealVO = setMealMapper.findById(shoppingCart.getSetmealId());
                shoppingCart.setName(setmealVO.getName());
                shoppingCart.setImage(setmealVO.getImage());
                shoppingCart.setAmount(setmealVO.getPrice());
            }
            shoppingCart.setNumber(1);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCartMapper.insert(shoppingCart);
        }
    }

查看购物车

需求分析和设计

接口设计
image.png

代码开发

 @Override
    public List<ShoppingCart> list() {
        ShoppingCart shoppingCart = ShoppingCart.builder().userId(BaseContext.getCurrentId()).build();
        return shoppingCartMapper.list(shoppingCart);
    }

清空购物车

需求分析和设计

接口设计
image.png

代码开发

 @Override
    public void deleteAll() {
        shoppingCartMapper.deleteAll(BaseContext.getCurrentId());
    }

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 05:56:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 05:56:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 05:56:03       45 阅读
  4. Python语言-面向对象

    2024-07-22 05:56:03       55 阅读

热门阅读

  1. python每日学习9:正则表达式

    2024-07-22 05:56:03       19 阅读
  2. Linux

    Linux

    2024-07-22 05:56:03      17 阅读
  3. 树上启发加点分治思想

    2024-07-22 05:56:03       17 阅读
  4. 配置文件格式 XML 快速上手

    2024-07-22 05:56:03       17 阅读
  5. Redis 数据结构—跳跃表(Skiplist)深度解析

    2024-07-22 05:56:03       16 阅读
  6. MySQL-显示所有错误信息

    2024-07-22 05:56:03       15 阅读
  7. Python 爬虫技术 第06节 HTTP协议与Web基础知识

    2024-07-22 05:56:03       11 阅读
  8. Oracle19.24发布,打补丁到19.24

    2024-07-22 05:56:03       13 阅读