首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >《苍穹外卖Day7:大一菜鸟的代码升空纪实》

《苍穹外卖Day7:大一菜鸟的代码升空纪实》

作者头像
张哈大
发布2025-05-31 08:41:37
发布2025-05-31 08:41:37
1630
举报
文章被收录于专栏:RedisRedis

前言

今天学习了如何添加缓存以及清理缓存(两种方式),完成了购物车的接口实现

1.任务报告

1.完成了缓存菜品的接口(用java调用Redis方法实现)

2.完成了缓存套餐的接口(用注解的方法实现)

3.完成了添加,查询,删除,清空购物车的接口

2.任务中的收获

2.1.缓存菜品

1.思考:

许多用户同时访问外卖平台(用户端),那么我们请求查询数据的速度会降低(用户查询一个菜品,等了几秒钟才显现出来,体验感极差),那么我们可以通过什么方式来增加访问速率呢 ==》 Redis缓存(由于Redis数据是存入内存中的,而服务端访问内存的速率是快于访问硬盘的速率的(Mysql数据默认存于硬盘)) ==》 但是不能直接把大量数据都存入内存吧(内存不适合存储大量数据)

2.分析由于我们用户端是对于菜品有菜品分类的,那么我们是不是可以根据分类id来存储具体数据

3.实现缓存菜品:

用户端点击查询菜品 ==》后端接收到请求 ==》判断当前分类下菜品缓存是否存在 ==》存在直接读缓存,返回缓存数据给用户端,不存在查询Mysql数据库,再进行Redis缓存数据,然后返回数据给用户端

4.清理缓存

分析:数据变更,那么我们缓存数据是不是也要改变,清理缓存,用户查询时再重新存入缓存,(新增,修改,批量删除,起售停售状态,当然这都是管理端接口的修改)

实现:

1.新增:前端传过来是一个菜品的基本数据(包含分类菜品id),那么我们可以直接通过分类菜品id删除Redis对应数据,等用户使用查询时,再存入Redis 2.修改:因为我们不知道管理员是否修改了分类id(要判断,需要多次查询数据库,过于繁琐),那么我们可以直接删除Redis所有数据,等用户使用查询时,再存入Redis 3.批量删除:由于是批量删除,可能会存在不同分类下的菜品删除,与上面修改菜品一样(需要判断,过于繁琐),那么我们可以直接删除Redis所有数据,等用户使用查询时,再存入Redis 4.起售停售状态:同样如此,传过来的参数是菜品id,你都不知道分类id,还需要查询数据库,那么我们可以直接删除Redis所有数据,等用户使用查询时,再存入Redis

注意:由于我们新增菜品默认菜品是停售状态,那么我们真正要展示给用户端还需要修改菜品状态(删除所有缓存),那么我们的新增的实现其实可以省略(你最终菜品还是需要修改状态(删除所有缓存)才能展示给用户)

2.2缓存套餐

1.简单方法:基于注解直接实现缓存操作(Spring Cache)

2.如何实现

1.导入Spring Cache坐标(POM中)

2.导入你想要的缓存实现坐标(EHCache ,Caffeine,Redis)

3.在方法中加入注解(具体功能与细节在知识点扩展中)

2.3添加购物车

1.分析:由于我们既有套餐也有菜品(类型不同,而且当菜品类型相同时其口味也会有不同),那么我们前端约束每次用点击加号(添加一个),前端就发出一个请求,后端接收请求实现操作

2.表的设计

展示图

一般要将菜品(套餐)名称,价格,口味(套餐的口味是固定的),数量,图片展示出来 而购物车本质是存的菜品id,套餐id,口味,创建时间(而菜品,套餐的具体数据是不是要通过它们的id来查询) 那么我们为了节省查询时间,就给购物车这个表添加了要展示的数据字段(避免每次都重复查询数据库),这些字段(本身是不需要添加的)称为冗余字段(一般这些数据字段是稳定的,不轻易修改的)

3.具体实现

前端发送请求(就是用户点击加号) ==》后端接收参数(菜品id和口味数据/套餐id) ==》创建购物车实体类对象(赋值) ==》动态根据userId(用户id,唯一标识,一个用户对应一个购物车),dishId(菜品id),setmealId(套餐id),口味数据(因为用户点菜品可以点不同口味,我们需要根据口味查询菜品的具体数据),来查询数据库并且返回 ==》判断返回数据是否存在 ==》存在,在返回数据的基础上将数量加一,不存在则进行下列操作 ==》判断添加数据是菜品还是套餐 ==》具体类型赋对应值

注意:我们一定要设置用户id(而这个,是由于在拦截器(用户)代码中设置了线程空间(里面存入了当时登录用户的id)),我们要使用时就直接从线程中取出即可,每个用户的id对应不同的购物车

3.知识点的扩展

3.1缓存注解
1.简介:Spring Cache基于代理(代理其方法,执行相应存缓存清理缓存的操作)
2.@CachePut

1.介绍:实现缓存存储

2.实现:

必写属性:cacheNames="名称" ==》指定缓存名称 key="Spring表达式语言" ==》下面

key的写法:

1.#方法形参名(如#user) 2.#result(方法返回值) 3.#p0(方法的第一位形参,依次类推#p1第二位形参) 4#a0(与3相同,就名称变了) 5.#root.args[](数组里填0,就代表方法第一位形参) 6.点 . 代表对象导航(就是取出对象里面的具体属性,如#user.name) 7.其实上面的最终作用就是生成一个key(只不过你可以利用不同的数据)

3.疑问:有什么用啊

1.因为用注解修饰,它是自动帮你存入缓存数据库中(Redis),那么你是不是需要指定一个key给它,值给你存 2.而且key是不是要不重复,而且key要定义的有意义,规律 3.而上面的两个属性就是来实现key的名称的 4.cacheNames代表的是这个类型数据的前缀名称(保持相同即可) 5. key则是你需要特意设置的不同值 6.最终组成效果:如cacheNames="userCache" ,key="#user.id" =》userCache::id(具体值)

注意:该注解是先执行完方法后才会执行注解的缓存功能(因此才能使用返回值数据)(一般#参数名称,使用的最多,其他的你可以自己翻看源码里面全部都有解释)

3.@Cacheable

1.介绍:执行方法之前会拿cacheNames+key属性组成的key去Redis中查询,能查到数据直接返回该数据,不执行方法,不能查到数据,则是执行方法,再将方法的返回值存入Redis中

2.该注解的属性与@CachePut属性基本一致(名称一样,唯一不同就是key没有#result这个写法了,从介绍知)

3.注意:该注解优先方法执行(先查Redis,没有执行方法,将方法返回值存入Redis)

4.@CacheEvict

1.介绍:方法执行完成后,会根据cacheNames+key属性组成的key去Redis中删除单一数据,如果你想要删除所有数据,那么将key换成allEntries(设置该属性为true,则是删除所有数据,false则不删数据)

2.该注解的属性用法与@Cacheable基本一致

3.注意:该注解功能是方法执行完成之后才进行删除操作

5.该注解最终逻辑与缓存菜品一样
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1.任务报告
  • 2.任务中的收获
    • 2.1.缓存菜品
    • 2.2缓存套餐
    • 2.3添加购物车
  • 3.知识点的扩展
    • 3.1缓存注解
      • 1.简介:Spring Cache基于代理(代理其方法,执行相应存缓存清理缓存的操作)
      • 2.@CachePut
      • 3.@Cacheable
      • 4.@CacheEvict
      • 5.该注解最终逻辑与缓存菜品一样
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档