Day07 緩存商品 購物車

緩存菜品

問題說明

用戶端小程序展示的菜品數據都是通過查詢數據庫獲得,如果用戶端訪問量比較大,數據庫訪問壓力隨之增大。

結果:系統響應慢,用戶體驗差

實現思路

通過 Redis 來緩存菜品數據,減少數據庫查詢操作。

緩存邏輯分析:

? ? ? ? 每個分類下的菜品保存一份緩存數據

? ? ? ? 數據庫中菜品數據有變更時清理緩存數據

代碼開發

首先是菜品緩存

package com.sky.controller.user;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 {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 根據分類id查詢菜品** @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根據分類id查詢菜品")public Result<List<DishVO>> list(Long categoryId) {//構造 redis 中的 keyString key = "dish_" + categoryId;//查詢 redis 中是否存在這個 key 的 valueList<DishVO> list = (List<DishVO>)redisTemplate.opsForValue().get(key);if(list != null && list.size() > 0){//如果這個 key 在 redis 中存在,就不去查 mysql,直接返回return Result.success(list);}Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//查詢起售中的菜品//redis 中沒有的話,就去 mysql 里面查,查到之后就存入 redislist = dishService.listWithFlavor(dish);redisTemplate.opsForValue().set(key, list);return Result.success(list);}}

為了保證 mysql 和 redis 中的數據庫的數據一致,我們需要清理緩存,所以當我們進行修改,刪除,起/停售,新增菜品 操作時需要清空緩存,為了代碼簡潔我們直接寫一個方法,直接調用這個方法即可

    /*** 清空緩存*/private void DeleteRedis(String pattern){Set keys = redisTemplate.keys(pattern);redisTemplate.delete(keys);}

功能測試

當我們調用該方法時,可以發現 Redis 里面的 key 消失了

緩存套餐

Spring Cache

實現思路

代碼開發

    @Cacheable(cacheNames = "setmealCache", key = "#categoryId") // key: setmealCache::categoryId@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);}
    @PostMapping@ApiOperation("新增套餐")@CacheEvict(cacheNames = "setmealCache", key = "setmealDTO.categoryId")public Result save(@RequestBody SetmealDTO setmealDTO) {setmealService.saveWithDish(setmealDTO);return Result.success();}
    @DeleteMapping@ApiOperation("批量刪除套餐")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result delete(@RequestParam List<Long> ids){setmealService.deleteBatch(ids);return Result.success();}
    @PutMapping@ApiOperation("修改套餐")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result update(@RequestBody SetmealDTO setmealDTO) {setmealService.update(setmealDTO);return Result.success();}
    @PostMapping("/status/{status}")@ApiOperation("套餐起售停售")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result startOrStop(@PathVariable Integer status, Long id) {setmealService.startOrStop(status, id);return Result.success();}

功能測試

和之前緩存菜品一樣,只需要看一下 Redis 里面是否緩存成功即可

添加購物車

需求分析和設計

代碼開發

具體業務邏輯見代碼

package com.sky.controller.user;import com.sky.result.Result;
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;@RestController("userShopController")
@RequestMapping("/user/shop")
@Slf4j
@Api(tags = "用戶端店鋪營業狀態相關接口")
public class ShopController {@AutowiredRedisTemplate redisTemplate;public static final String  KEY = "SHOP_STATUS";@GetMapping("/status")@ApiOperation("營業狀態查詢")public Result<Integer> result(){Integer status = (Integer) redisTemplate.opsForValue().get(KEY);log.info("當前店鋪的營業狀態為:{}", status == 1 ? "營業中": "打樣中");return Result.success(status);}}
package com.sky.service.impl;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.ShopCartMapper;
import com.sky.service.ShopCardService;
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;@Slf4j
@Service
public class ShopCardServiceImpl implements ShopCardService {@AutowiredShopCartMapper shopCartMapper;@AutowiredDishMapper dishMapper;@AutowiredSetmealMapper setmealMapper;@Overridepublic void add(ShoppingCartDTO shoppingCartDTO) {ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);shoppingCart.setUserId(BaseContext.getCurrentId());// 首先判斷要添加的是菜品還是套餐Long dishId = shoppingCartDTO.getDishId();Long setmealId = shoppingCartDTO.getSetmealId();if(dishId != null){// 傳入的是菜品,判斷購物車里是否有該菜品List<ShoppingCart> list = shopCartMapper.list(shoppingCart);// 菜品不為空,說明菜品已經存在,我們只需要讓它的數量 + 1if(list != null && list.size() > 0){//注意注意,因為這張表里每個菜品只能存一次,所以我的這個集合要么沒有元素,要么只有一個元素// 所以第一個元素也就是我們需要修改的那個ShoppingCart shoppingCart1 = list.get(0);shoppingCart.setNumber(shoppingCart1.getNumber() + 1);shoppingCart.setId(shoppingCart1.getId());//    log.info("當前菜品的數量為:{}", shoppingCart.getNumber());//    log.info("當前菜品的 id 為:{}",shoppingCart.getId());shopCartMapper.update(shoppingCart);return;}else{// 菜品為空,我們就需要查找對應的菜品數據,然后賦值給 shoppingCartDish dish = dishMapper.getById(dishId);shoppingCart.setNumber(1);shoppingCart.setAmount(dish.getPrice());shoppingCart.setCreateTime(LocalDateTime.now());shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shopCartMapper.insert(shoppingCart);return;}}else{// 傳入的是套餐,判斷購物車中是否有該套餐,邏輯和上面一樣List<ShoppingCart> list = shopCartMapper.list(shoppingCart);if(list != null && list.size() > 0){ShoppingCart shoppingCart1 = list.get(0);shoppingCart.setNumber(shoppingCart1.getNumber() + 1);shoppingCart.setId(shoppingCart1.getId());shopCartMapper.update(shoppingCart);return;}else{// 套餐為空Setmeal setmeal = setmealMapper.getById(setmealId);shoppingCart.setNumber(1);shoppingCart.setAmount(setmeal.getPrice());shoppingCart.setCreateTime(LocalDateTime.now());shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shopCartMapper.insert(shoppingCart);return;}}}
}
package com.sky.mapper;import com.sky.entity.ShoppingCart;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;import java.util.List;@Mapper
public interface ShopCartMapper {List<ShoppingCart> list(ShoppingCart shoppingCart);@Update("update sky_take_out.shopping_cart set number = #{number} where id = #{id}")void update(ShoppingCart shoppingCart);@Insert("insert into sky_take_out.shopping_cart(name, image, user_id, dish_id, setmeal_id, dish_flavor, number, amount, create_time)" +"values (#{name}, #{image}, #{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{createTime})")void insert(ShoppingCart shoppingCart);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.ShopCartMapper"><select id="list" resultType="com.sky.entity.ShoppingCart">select * from sky_take_out.shopping_cart<where><if test="userId != null">and user_id = #{userId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where></select></mapper>

功能測試

查看購物車

?需求分析和設計

代碼開發

    @GetMapping("/list")@ApiOperation("查看購物車信息")public Result<List<ShoppingCart>> showShoppingCart(){List<ShoppingCart> shoppingCart = shopCardService.list();return Result.success(shoppingCart);}
    @Overridepublic List<ShoppingCart> list() {ShoppingCart shoppingCart = ShoppingCart.builder().userId(BaseContext.getCurrentId()).build();List<ShoppingCart> shoppingCarts = shopCartMapper.list(shoppingCart);return shoppingCarts;}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.ShopCartMapper"><select id="list" resultType="com.sky.entity.ShoppingCart">select * from sky_take_out.shopping_cart<where><if test="userId != null">and user_id = #{userId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where></select></mapper>

功能測試

清空購物車

需求分析和設計

代碼開發

    @DeleteMapping("/clean")@ApiOperation("清空購物車")public Result clearShoppingCart(){log.info("清空購物車");shopCardService.clean();return Result.success();}
    @Overridepublic void clean() {shopCartMapper.clean(BaseContext.getCurrentId());}
    @Delete("delete from sky_take_out.shopping_cart where user_id = #{currentId}")void clean(Long currentId);

功能測試

直接可以看到數據庫中的數據被刪除了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93369.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93369.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93369.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jenkins(集群與流水線配置)

Jenkins&#xff08;集群與流水線配置&#xff09; Jenkins集群 集群化構建可以提升構建效率&#xff0c;也可以并發在多臺機器上執行構建。 安裝前提&#xff1a;內存至少512MB、Java 17 以上、Maven環境、Git環境 配置集群步驟 配置節點菜單新建節點查看節點配置狀態 新建完節…

深入剖析ROS參數服務器通信機制 ——共享全局數據的“云端倉庫”實現原理

?1. 核心概念&#xff1a;分布式數據共享容器? ?定位?&#xff1a;ROS參數服務器&#xff08;Parameter Server&#xff09;是ROS架構中的全局共享存儲系統&#xff0c;相當于機器人的“云端倉庫”。 ?作用?&#xff1a; 存儲多節點共享的靜態配置參數&#xff08;如機器…

21.AlexNet

雖然LeNet在手寫數字識別上取得了不錯的結果&#xff0c;但是他在對于更大的數據集效果就十分有限。 一方面&#xff0c;對于更大尺寸的圖像效果有限 另一方面&#xff0c;對于更多分類的任務效果有限 自LeNet后的十幾年&#xff0c;計算機視覺領域步入寒冬&#xff0c;神經網絡…

Shell腳本-條件判斷相關參數

一、前言在 Shell 腳本編程中&#xff0c;條件判斷 是實現流程控制的核心機制之一。無論是判斷文件是否存在、字符串是否相等&#xff0c;還是數值大小比較&#xff0c;都離不開條件判斷語句。本文將帶你全面掌握 Shell 腳本中與條件判斷相關的參數和語法&#xff0c;包括&…

何為“低空經濟”?

低空經濟&#xff08;Low-Altitude Economy&#xff09;是指以1000米以下空域&#xff08;部分場景可延伸至3000米&#xff09;為核心&#xff0c;以無人機&#xff08;UAV&#xff09;、電動垂直起降飛行器&#xff08;eVTOL&#xff09;、直升機、通航飛機等航空器為載體&…

線性代數 | 直觀理解一些概念

注&#xff1a;本文為 “線性代數 直觀理解概念” 相關合輯。 英文引文&#xff0c;機翻未校。 中文引文&#xff0c;略作重排。 如有內容異常&#xff0c;請看原文。 直觀理解線性代數的一些概念 2015-03-06 Updated: 2015-05-09 本文介紹矩陣的一些相關概念的直觀理解&…

Spring AI 集成阿里云百煉平臺

Spring AI 集成阿里云百煉平臺 創建API key 在阿里云百煉平臺創建API key設置系統變量。阿里云百煉 api key 創建 API 參考 官方API地址&#xff1a;https://bailian.console.aliyun.com &#xff08;1&#xff09;在阿里云百煉控制臺&#xff0c;選擇API參考菜單。 API…

Codeforces Round 859 (Div. 4) A - D + F - G2 題解

Codeforces Round 859 (Div. 4) A - D F - G2 題解A. Plus or Minus&#xff08;800 分難度&#xff09; 思路&#xff1a; 直接 if - else 判斷。 參考代碼&#xff1a; #include<bits/stdc.h> using namespace std; void solve(){int a, b, c;cin >> a >&g…

【Java web】Servlet 詳解

一、什么是 Servlet&#xff1f;—— 你不知道的 "網頁服務員"想象你走進一家網紅書店&#xff08;比如 "在線 Java 書店"&#xff09;&#xff0c;想買一本《Java 編程思想》。你告訴前臺服務員你的需求&#xff0c;服務員去倉庫找書、包裝、收款&#xf…

數據庫Microsoft Access、SQL Server和SQLite三者對比及數據庫的選型建議

SQLite本質是代碼庫&#xff0c;Access是單文件桌面DB&#xff0c;SQL Server是正經的C/S架構數據庫。這就像比較自行車、家用轎車和卡車&#xff0c;完全不同的設計目標。 核心區別對比表特性Microsoft AccessSQL ServerSQLite類型桌面DBMS (文件型)客戶端/服務器 RDBMS嵌入式…

【C++】默認構造函數,參數化構造函數,拷貝構造函數,拷貝賦值運算符, 移動構造函數 ,移動賦值運算符

1. 默認構造函數 (Default Constructor) 作用&#xff1a; 無參創建對象 簽名&#xff1a; ClassName() 特點&#xff1a; ①無參數或所有參數都有默認值 ②若未聲明任何構造函數&#xff0c;編譯器自動生成&#xff08;空實現&#xff09; ③用于容器默認初始化&#xff08;如…

辦公效率提升指南:完成重復任務自動化

手動操作容易出錯&#xff0c;尤其是在處理大量數據或復雜文檔時。它將PDF轉換、Word處理、Excel操作、OCR識別等高頻功能融為一體&#xff0c;界面清爽無冗余&#xff0c;零廣告打擾&#xff0c;專注提升工作效率。它內置七大核心模塊&#xff1a;自動任務、系統工具、文件處理…

數字煉金術:當API工作流遇見AI客服—點石成金的智能革命!

目錄 引言 一、藍耘元生代MaaS平臺概述 1.1 藍耘平臺的API服務 1.2 藍耘平臺的優勢 二、初識藍耘元生代MaaS平臺—帶你深度體驗 2.1 從零開始——平臺注冊與環境搭建 2.2 藍耘平臺的優勢在哪里&#xff1f; 三、API工作流調用技巧與實踐 3.1 API工作流設計與調用流程 …

HackMyVM-Uvalde

目錄信息搜集漏洞利用權限提升信息搜集 主機發現 ┌──(kali?kali)-[~] └─$ nmap -sn 192.168.21.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-16 01:10 EDT Nmap scan report for dev.medusa.hmv (192.168.21.6) Host is up (0.00015s latency). MAC Addr…

「Java EE開發指南」如何使用MyEclipse中的Web Fragment項目?

開發者可以通過使用Web Fragment項目模塊化應用程序部署描述符&#xff0c;本文提供如何使用它們的必要信息。 該特性在MyEclipse中可用。 MyEclipse v2025.1離線版下載 通過使用Web Fragment項目&#xff0c;您的Web應用程序部署描述符可以模塊化&#xff0c;就像能夠模塊化…

redis的key過期刪除策略和內存淘汰機制

一、key的過期刪除策略 原由&#xff1a;一般情況下&#xff0c;在使用redis作緩存&#xff0c;對k設置過期時間&#xff0c;當過期時間到后&#xff0c;k還是占用內存的&#xff0c;并沒有從內存中移除。 1.定時刪除 在設置key的過期時間的同時&#xff0c;為該key創建一個定…

NVIDIA Nsight Deep Learning Designer使用

一、關于產品 1.1 產品介紹 NVIDIA Nsight Deep Learning Designer 是一款面向 AI 推理開發者的可視化建模與優化工具。它支持基于 ONNX 格式的神經網絡模型編輯、結構可視化、性能分析與 TensorRT 引擎導出&#xff0c;幫助用戶更高效地設計、調優和部署高性能推理模型。該工…

Android 常見100道面試題(完整版)

一、基礎組件與核心原理Activity 相關Q1&#xff1a;請描述 Activity 的完整生命周期&#xff0c;從創建到銷毀經歷哪些關鍵方法&#xff1f;A&#xff1a;Activity 完整生命周期包括&#xff1a;onCreate&#xff08;初始化&#xff09;→ onStart&#xff08;可見&#xff09…

Navicat 為 SQLite 數據庫設置密碼指南

Navicat 為 SQLite 數據庫設置密碼指南 在 SQLite 中設置密碼實際上是通過加密實現的&#xff0c;Navicat 使用 SQLCipher 擴展來提供數據庫加密功能。以下是詳細的操作方法和注意事項&#xff1a; 在 Navicat 中設置密碼&#xff08;加密數據庫&#xff09; 步驟 1&#xff1a…

Spring Framework:Java 開發的基石與 Spring 生態的起點

在 Java 技術領域&#xff0c;Spring Framework 無疑是一座里程碑式的存在。它不僅徹底改變了 Java 企業級應用的開發模式&#xff0c;更以其為核心衍生出了龐大的 Spring 生態系統&#xff0c;成為無數開發者構建應用的首選技術棧。本文將以 Spring Framework 為核心&#xff…