缓存菜品、套餐、购物车相关功能

一、缓存菜品

通过缓存的方式提高查询性能

1.1问题说明

大量的用户访问导致数据库访问压力增大,造成系统响应慢,用户体验差

1.2 实现思路

优先查询缓存,如果缓存没有再去查询数据库,然后载入缓存

将菜品集合序列化后缓存入redis  key为每个分类的id

1.3 代码开发(缓存菜品)

import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> list(Long categoryId) {
        //构造redis中的key,规则:dish_分类id
        String key ="dish_"+categoryId;
        //查询redis中是否存在菜品数据
        List<DishVO> list =(List<DishVO>) redisTemplate.opsForValue().get(key);
        if (list!=null&&list.size()>0){
            //如果存在,直接返回,无需查询数据库
            return Result.success(list);
        }
        //如果不存在,查询数据库,将查询到的数据放入redis中
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
         list = dishService.listWithFlavor(dish);
         redisTemplate.opsForValue().set(key,list);
         return Result.success(list);
    }

}

1.4 代码开发(清除缓存)

为什么要清除缓存? 为了保证数据的一致性,数据库修改后,缓存中的数据并没有发生改变,用户再次请求后不会请求到新修改的数据,而是过期的数据所以要清除缓存。

什么时候清除缓存? 后端修改数据后对缓存进行及时的清除

    /**
     * 统一清除缓存数据
     * @param pattern
     */
    private void cleanCache(String pattern){
        Set keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }

    }
 /**
     * 启用禁用菜品
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用菜品")
    public Result startOrStop(@PathVariable Integer status,Long id){
        log.info("启用禁用菜品,{},{}",status,id);
        dishService.startOrStop(status,id);
        //将所有的菜品缓存数据清理掉,所有以dish_开头的key
//        Set keys = redisTemplate.keys("dish_");
//        redisTemplate.delete(keys);
        cleanCache("dish_*");
        return Result.success();
    }

二、缓存套餐(基于SpringCache)

2.1 SpringCache

  • 被写死了(没有意义)
    @CachePut(cacheNames ="userCache",key = "abc")//如果使用SpringCache缓存数据,key的生成:userCache::abc            //生成的key 与cacheNames,key有关系 
  • 动态生成key  + SpEL表达式
    @CachePut(cacheNames ="userCache",key = "#user.id")//如果使用SpringCache缓存数据,key的生成:userCache::#user.id

2.2 入门案例

1.CachePut:将方法返回值放到缓存中

//    @CachePut(cacheNames ="userCache",key = "#user.id")//如果使用SpringCache缓存数据,key的生成:userCache::abc
    @PostMapping
//    @CachePut(cacheNames = "userCache",key ="#result.id")//对象导航
//    @CachePut(cacheNames = "userCache",key = "#p0.id")//#p0代表第一个参数
//    @CachePut(cacheNames = "userCache",key = "#a0.id")
    @CachePut(cacheNames = "userCache",key = "#root.args[0].id")//#root.args[0]代表第一个参数
    public User save(@RequestBody User user){
        userMapper.insert(user);
        return user;
    }

2.Cacheable:在方法执行前先查询缓存,如果缓存中有该数据,直接返回缓存中的数据。如果没有在方法执行后再将返回值放入缓存中

    @GetMapping
    @Cacheable(cacheNames = "userCache",key = "#id")
    public User getById(Long id){
        User user = userMapper.getById(id);
        return user;
    }

Cacheable 不能使用#result.id这种方式设置key的值 

3.CacheEvict :将一条或者多条数据从缓存中删除

  • 删除单条数据
    @CacheEvict(cacheNames = "userCache",key ="#id" )
    @DeleteMapping
    public void deleteById(Long id){
        userMapper.deleteById(id);
    }
  • 删除多条数据(allEntries = true)
    @CacheEvict(cacheNames = "userCache",allEntries = true)
	@DeleteMapping("/delAll")
    public void deleteAll(){
        userMapper.deleteAll();
    }

2.3实现思路

2.4代码开发

import com.sky.constant.StatusConstant;
import com.sky.entity.Setmeal;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController("userSetmealController")
@RequestMapping("/user/setmeal")
@Api(tags = "C端-套餐浏览接口")
public class SetmealController {
    @Autowired
    private SetmealService setmealService;

    /**
     * 条件查询
     *
     * @param categoryId
     * @return
     */
    @Cacheable(cacheNames = "setmealCache",key = "#categoryId")//key :setmealCache::100
    @GetMapping("/list")
    @ApiOperation("根据分类id查询套餐")
    public Result<List<Setmeal>> list(Long categoryId) {
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);

        List<Setmeal> list = setmealService.list(setmeal);
        return Result.success(list);
    }

    /**
     * 根据套餐id查询包含的菜品列表
     *
     * @param id
     * @return
     */
    @GetMapping("/dish/{id}")
    @ApiOperation("根据套餐id查询包含的菜品列表")
    public Result<List<DishItemVO>> dishList(@PathVariable("id") Long id) {
        List<DishItemVO> list = setmealService.getDishItemById(id);
        return Result.success(list);
    }
}
import com.github.pagehelper.Page;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 套餐管理
 */
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐管理相关接口")
@Slf4j
public class SetmealController {
    @Autowired
    private SetmealService setmealService;

    @CacheEvict(cacheNames = "setmealCache",key = "setmealDTO.categoryId")
    @PostMapping
    @ApiOperation("新增套餐接口")
    public Result save(@RequestBody SetmealDTO setmealDTO){
    log.info("新增套餐:{}",setmealDTO);
    setmealService.saveWithDish(setmealDTO);
    return Result.success();
    }

    /**
     * 套餐分页查询
     * @param setmealPageQueryDTO
     * @return
     */

    @GetMapping("/page")
    @ApiOperation("套餐分页查询")
    public Result<PageResult> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO){
    log.info("套餐分页查询:{}",setmealPageQueryDTO);
    PageResult pageResult  = setmealService.pageQuery(setmealPageQueryDTO);
    return Result.success(pageResult);

    }

    /**
     * 批量删除套餐
     * @param ids
     * @return
     */
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    @DeleteMapping
    @ApiOperation("批量删除菜品")
    public Result delete(@RequestParam List<Long> ids){
    log.info("批量删除套餐:{}",ids);
    setmealService.deleteBatch(ids);
    return Result.success();
    }
    /**
     * 根据id查询套餐,用于修改页面回显数据
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询套餐")
    public Result<SetmealVO> getById(@PathVariable Long id) {
        SetmealVO setmealVO = setmealService.getByIdWithDish(id);
        return Result.success(setmealVO);
    }

    /**
     * 修改套餐
     *
     * @param setmealDTO
     * @return
     */
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    @PutMapping
    @ApiOperation("修改套餐")
    public Result update(@RequestBody SetmealDTO setmealDTO) {
        setmealService.update(setmealDTO);
        return Result.success();
    }

    /**
     * 套餐起售停售
     * @param status
     * @param id
     * @return
     */
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    @PostMapping("/status/{status}")
    @ApiOperation("套餐起售停售")
    public Result startOrStop(@PathVariable Integer status, Long id) {
        setmealService.startOrStop(status, id);
        return Result.success();
    }


}

三、添加购物车

3.1需求分析和设计

3.2 代码开发

3.2.1Controller

import com.sky.dto.ShoppingCartDTO;
import com.sky.result.Result;
import com.sky.service.ShoppingCartService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user/shoppingCart")
@Api(tags = "C端购物车相关接口")
@Slf4j
public class ShoppingCartController {
    @Autowired
    private ShoppingCartService shoppingCartService;
    /**
     * 添加购物车
     * @param shoppingCartDTO
     * @return
     */
    @PostMapping("/add")
    @ApiOperation("添加购物车")
    public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
        log.info("添加购物车,商品信息为:",shoppingCartDTO);
        shoppingCartService.addShoppingCart(shoppingCartDTO);
        return Result.success();
    }

}

 3.2.2 Serveice层

import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private SetmealMapper setmealMapper;
    /**
     * 添加购物车
     * @param shoppingCartDTO
     */
    @Override
    public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {
        //判断当前加入到购物车中的商品是否已经存在了
        ShoppingCart shoppingCart = new ShoppingCart();
        BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
        Long userId = BaseContext.getCurrentId();
        shoppingCart.setUserId(userId);
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
        //如果已经存在了,只需要将其数量加1
        if (list !=null && list.size()>0){
            ShoppingCart cart = list.get(0);
            cart.setNumber(cart.getNumber()+1);
            shoppingCartMapper.updateNumberById(cart);
        }else {
            //如果不存在,需要插入一条购物车数据


            //判断本次添加购物车的是菜品还是套餐
            Long dishId = shoppingCartDTO.getDishId();
            if (dishId !=null){
                //本次添加的是菜品
                Dish dish = dishMapper.getById(dishId);
                shoppingCart.setName(dish.getName());
                shoppingCart.setImage(dish.getImage());
                shoppingCart.setAmount(dish.getPrice());
//                shoppingCart.setNumber(1);
//                shoppingCart.setCreateTime(LocalDateTime.now());
//
            }else {
                //本次添加的是套餐
                Long setmealId = shoppingCartDTO.getSetmealId();
                Setmeal setmeal = setmealMapper.getById(setmealId);
                shoppingCart.setName(setmeal.getName());
                shoppingCart.setImage(setmeal.getImage());
                shoppingCart.setAmount(setmeal.getPrice());
//                shoppingCart.setNumber(1);
//                shoppingCart.setCreateTime(LocalDateTime.now());

            }
            shoppingCart.setNumber(1);
            shoppingCart.setCreateTime(LocalDateTime.now());

            shoppingCartMapper.insert(shoppingCart);

        }





    }
}

四、查看购物车

4.1 需求分析和设计

4.2 代码开发

4.2.1Controller层

/**
     * 查看购物车
     * @return
     */

    @GetMapping("/list")
    @ApiOperation("查看购物车")
    public  Result<List<ShoppingCart>> list(){
    List<ShoppingCart> list = shoppingCartService.showShoppingCart();
    return  Result.success(list);

    }

4.2.2 Service层

    /**
     * 查看购物车
     * @return
     */
    @Override
    public List<ShoppingCart> showShoppingCart() {
        //获取当前微信用户的id
        Long userId = BaseContext.getCurrentId();
        ShoppingCart shoppingCart = ShoppingCart.builder()
                .userId(userId)
                .build();
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);

        return list;
    }

五、清空购物车

5.1 需求分析和设计

5.2 代码开发

5.2.1 Controller层

    /**
     * 清空购物车
     * @return
     */
    @DeleteMapping("/clean")
    public  Result clean(){
        shoppingCartService.cleanShoppingCart();
        return Result.success();

    }

5.2.2 Service层

    /**
     * 清空购物车
     */
    @Override
    public void cleanShoppingCart() {
        Long userId = BaseContext.getCurrentId();
        shoppingCartMapper.deleteByUserId(userId);


    }

5.2.3 Mapper层

    /**
     * 根据用户id删除购物车数据
     * @param userId
     */
    @Delete("delete from shopping_cart where user_id =#{userId}")
    void deleteByUserId(Long userId);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

流域生态系统水-碳-氮耦合过程模拟

原文链接&#xff1a;流域生态系统水-碳-氮耦合过程模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247599209&idx3&snbb447abff048424d640c4a45755451f7&chksmfa82058ecdf58c9810ec4c20ccaa521c71773422647f508b690ac4d90df1e273b65ae2db7521&…

财报解读:中通正在从“价格战”跳到“价值战?”

从数据来看&#xff0c;我国快递行业持续保持着上升势头。国家邮政局数据显示&#xff0c;今年1至2月我国快递发展指数为329.6&#xff0c;同比提升26.7%。 不过&#xff0c;在向好的行业趋势当中&#xff0c;相关企业仍有烦忧。一方面&#xff0c;行业竞争加剧&#xff0c;新…

IP定位技术打击网络犯罪

IP定位技术在打击网络犯罪中扮演着至关重要的角色。随着互联网的普及和网络技术的飞速发展&#xff0c;网络犯罪现象日益严重&#xff0c;对社会的稳定和安全造成了极大的威胁。IP定位技术的应用&#xff0c;为公安机关追踪和打击网络犯罪提供了有力的技术支持。 首先&#xff…

【OS探秘】【虚拟化】【软件开发】在Windows 11上安装mac OS虚拟机

一、所需原料 Windows 11主机、Oracle VM VirtualBox虚拟化平台、mac OS 11镜像文件 二、安装步骤 1、 在VBox管理器中&#xff0c;点击“新建”&#xff0c;进入向导模式&#xff0c;指定各个字段&#xff1a;

Navicat BI 工具 | 连接数据

早前&#xff0c;海外 LearnBI online 博主 Adam Finer 对 Navicat Charts Creator 这款 BI&#xff08;商业智能&#xff09;工具进行了真实的测评。上一期&#xff0c;我们介绍了这位博主对 Navicat BI 工具的初始之感。今天&#xff0c;我们来看看从连接数据的角度&#xff…

Redis是单线程还是多线程?(面试题)

1、Redis5及之前是单线程版本 2、Redis6开始引入多线程版本&#xff08;实际上是 单线程多线程 版本&#xff09; Redis6及之前版本&#xff08;单线程&#xff09; Redis5及之前的版本使用的是 单线程&#xff0c;也就是说只有一个 worker队列&#xff0c;所有的读写操作都要…

外包干了15天,技术退步明显。。。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

07、Lua 流程控制

Lua 流程控制 Lua 流程控制控制结构语句 Lua 流程控制 Lua编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码&#xff0c;在条件为 false 时执行其他指定代码。 以下是典型的流程控制流程图&#xff1a; 控制结构的条件表达式结…

基于RAG的大模型知识库搭建

什么是RAG RAG(Retrieval Augmented Generation)&#xff0c;即检索增强生成技术。 RAG优势 部分解决了幻觉问题。由于我们可以控制检索内容的可靠性&#xff0c;也算是部分解决了幻觉问题。可以更实时。同理&#xff0c;可以控制输入给大模型上下文内容的时效性&#xff0c…

007_how_to_start_learning_Matlab学习的启动与加速

Matlab学习的启动与加速 1. 前言 这个专题的Matlab博文系列&#xff0c;来到了传奇的007&#xff0c;我又准备放下技术工作的写作&#xff0c;来一点务虚和规划的内容。 这个系列的开始&#xff0c;也是一个随机发生的小概率事件&#xff0c;本来Python&#xff08;PyQt&…

Tomcat和Servlet了解

一,服务器概述 先了解下主机-系统-容器和程序这几个之间的关系. 主机&#xff1a;主机是指一台计算机设备&#xff0c;可以是物理服务器或虚拟服务器&#xff0c;用于存储数据、运行应用程序和提供服务。在这种情况下&#xff0c;主机是托管Ubuntu&#xff08;Linux系统&…

【数据结构】归并排序(不用递归)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解归并排序&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 归并排序&#xff08;用递归&#xff09; 之前我们写了一篇博客来介绍如何用递归实现归并排序…

回顾皆草木,唯你是青山~

新中式小飞袖连衣裙 每一件衣裳都是时间的礼赞 是炎炎夏日的一抹清新 传统元素与现代时尚设计相结合 面料舒适透气&#xff0c;裙摆飘逸灵动 宛如林间自由洒脱的小仙子~

网络安全:Kali Linux 进行SQL注入与XSS漏洞利用

目录 一、实验 1.环境 2.Kali Linux 进行SQL注入 3.Kali Linux 进行XSS漏洞利用 二、问题 1.XSS分类 2.如何修改beef-xss的密码 3.beef-xss 服务如何管理 4.运行beef报错 5.beef 命令的颜色有哪些区别 6.owasp-top-10 有哪些变化 一、实验 1.环境 &#xff08;1&a…

数据结构·二叉树(2)

目录 1 堆的概念 2 堆的实现 2.1 堆的初始化和销毁 2.2 获取堆顶数据和堆的判空 2.3 堆的向上调整算法 2.4 堆的向下调整算法 2.4 堆的插入 2.5 删除堆顶数据 2.6 建堆 3 建堆的时间复杂度 3.1 向上建堆的时间复杂度 3.2向下建堆的时间复杂度 4 堆的排序 前言&…

2024年生骨肉冻干深度比较:希喂、NWN、PURPOSE,哪一款更胜一筹?

在科学养宠的当今时代&#xff0c;生骨肉冻干已经成为猫咪日常饮食中不可或缺的一部分。高肉含量的生骨肉冻干不仅易吸收、好消化&#xff0c;更能给猫提供其他猫粮所不能提供的微量物质&#xff0c;更满足猫的全面营养需求。然而&#xff0c;面对市面上琳琅满目的生骨肉冻干品…

鸿蒙OS实例:同步获取应用配置的【versionCode和versionName】

1.同步方式获取 首先需要导包&#xff1a; import bundleManager from ohos.bundle.bundleManager 工具类&#xff1a; public static async getVersionName(): Promise<string> {try {let bundleInfo await bundleManager.getBundleInfoForSelf(bundleManager.Bundle…

从零开始搭建游戏服务器 第七节 创建GameServer

目录 前言正文创建GameServer模块修改配置创建NettyClient连接到登录服登录服修改创建协议游戏服注册到登录服 总结 前言 上一节我们使用自定义注解反射简化了协议解包和逻辑处理分发流程。 那么到了这里登录服登录服的架构已经搭建的差不多了&#xff0c;一些比较简单的、并发…

Android卡顿掉帧问题分析之实战篇

本文将结合典型实战案例&#xff0c;分析常见的造成卡顿等性能问题的原因。从系统工程师的总体角度来看 &#xff0c;造成卡顿等性能问题的原因总体上大致分为三个大类&#xff1a;一类是流程执行异常&#xff1b;二是系统负载异常&#xff1b;三是编译问题引起。 1 流程执行异…