当前位置: 首页 > news >正文

Java项目-苍穹外卖-Day07-redis缓存应用-SpringCache/购物车功能

文章目录

  • 前言
  • 缓存菜品
    • 问题分析和实现思路
    • 缓存菜品数据
    • 清理缓存数据
    • 功能测试
  • SpringCache
    • 介绍
    • 入门案例
  • 缓存套餐
  • 购物车功能
    • 添加购物车
      • 需求分析和产品原型
      • 测试
    • 查看购物车
    • 清空购物车

前言

本章节主要是进行用户端的购物车功能开发
和redis作为mysql缓存的应用以及SpringCache的介绍
因为很多人查询数据库会导致mysql的查询效率降低,可以通过redis作为缓存来解决

实现产品原型
在这里插入图片描述
基本可以看出一些功能
添加购物车
查看购物车
清空购物车
以及我们进行redis应用的缓存菜品和套餐
还有一个自己的作业 就是增减购物车内商品的功能

缓存菜品

问题分析和实现思路

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

缓存菜品数据

这个挺简单的
就是根据redis中有无对应数据来进行操作
注意redis返回的数据类型(存入时是什么,取出来就是什么)
redis中的string可以对应java中的任意类型

@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中的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);}Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品list = dishService.listWithFlavor(dish);//如果不存在,查询数据库,讲查询到的数据库放入redis中redisTemplate.opsForValue().set(key,list);return Result.success(list);}}

清理缓存数据

有可能我们管理端会修改/删除/新增菜品
你们上一次的查询到redis的要跟着更新
要不然sql和redis中数据不一致,管理端作出的更改用户端如果还是去查redis就看不到
这里就只写
admin中DishController中修改的方法

  @PostMapping@ApiOperation("新增菜品")public Result save(@RequestBody DishDTO dishDTO){log.info("新增菜品:{}",dishDTO);dishService.saveWithFlavor(dishDTO);//清理缓存数据cleanCache("dish_"+dishDTO.getCategoryId());return Result.success();}@DeleteMapping@ApiOperation("菜品的批量删除")public Result delete(@RequestParam List<Long> ids){//传参为1,2,3这种,想要mvc帮我们自动封装需要用到@RequestParam,否则只能字符串接收自己解析log.info("菜品批量删除:{}",ids);dishService.deleteBatch(ids);//这个比较复杂,所以直接全部删除 dish_*就表示以dish_开头的key//需要先将对应全部key取出然后再删除cleanCache("dish_*");return Result.success();}@PutMapping@ApiOperation("修改菜品")public Result update(@RequestBody DishDTO dishDTO) {log.info("修改菜品,对应信息为:{}",dishDTO);dishService.updateWithFlavor(dishDTO);//仔细想想更改 可以设计一个分类(只更改名称价格什么的) 也可以涉及两个(菜品分类的变更)//所以这里也清理掉所有缓存cleanCache("dish_*");return Result.success();}@PostMapping("/status/{status}")@ApiOperation("起售,停售菜品")public Result startOrStop(@PathVariable Integer status,Long id){log.info("起售停售菜品:{},{}",status,id);dishService.startOrStop(status,id);//这里也全部清理掉,需要查表对应分类id情况有点复杂cleanCache("dish_*");return Result.success();}这个是新增方法/*** 清理缓存数据* @param pattern*/private void cleanCache(String pattern){Set keys = redisTemplate.keys(pattern);redisTemplate.delete(keys);}

功能测试


看对应更换分类后有没有sql语句输出
和修改分类菜品后对应的分类菜品情况

SpringCache

介绍

在这里插入图片描述
在这里插入图片描述
admin,增删改数据只需要清除缓存,CachePut是user那边查询数据时同步缓存用的
只有需要查才会放入缓存
@Cacheable用于select(查询)
@CachePut一般用于新增
@CacheEvict就是用户端的更改,删除等等

入门案例

导入依赖
redis和springcache
其他正常的那些依赖就不介绍了
在这里插入图片描述
再进行一下文件配置
在这里插入图片描述
controller里面提起写好了方法主要是学一下springcache
在这里插入图片描述
往下就是使用springcache的正常流程了
1.再springboot启动类开启缓存注解
在这里插入图片描述

比如这个请求
我们存储用户,一般是希望同时存储到缓存中
所以我们用==@CachePut修饰==
对应的属性 cacheNames和key是与redis中的key有关的
redis中的key=cacheNames::key
key一般是动态获取,使不同用户对应不同key,可以获取user的id
格式是 key = #user(参数).id
有人可能问刚开始还没传id,怎么获取对应id,user参数和user返回值是一个,然后其实操作是先插入到sql数据库然后再进行缓存的(mybatis进行操作返回id给user对象)
在这里插入图片描述
也可以这样写,result引用方法的返回值
在这里插入图片描述
其实还有很多用法
但是还是最推荐第一种

查询相关的语句,先看redis有没有,没有查数据库的然后存到redis中
用到@Cacheable注解,这里就不能用result,具体可以看注解里有对应的注释说明
然后我们要查询的key就是userCache::id (因为我们新增就是用这个,然后查询也要用这个可以)

在这里插入图片描述
删除一条数据
使用@CaheEvict来进行缓存数据的删除,保障数据库和缓存的数据一致性

在这里插入图片描述
删除所有的缓存的键值对
把key属性变为allEntries属性并且设为true
在这里插入图片描述

缓存套餐

在这里插入图片描述
在这里插入图片描述
改的不多
这是admin包下的setmealController

@RestController
@RequestMapping("/admin/setmeal")
@Api("套餐相关接口")
@Slf4j
public class SetmealController {/*** 新增套餐*/@Autowired SetmealService setmealService;@PostMapping@ApiOperation("新增套餐")@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")public Result save(@RequestBody SetmealDTO setmealDTO){log.info("新增套餐信息:{}",setmealDTO);setmealService.saveWithDish(setmealDTO);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 setmealPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("分页查询")public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){log.info("套餐分页查询:{}",setmealPageQueryDTO);PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);return Result.success(pageResult);}/*** 批量删除套餐* @param ids* @return*/@DeleteMapping@ApiOperation("批量删除套餐")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result delete(@RequestParam List<Long> ids){//让Spring自动处理字符串变成集合log.info("批量删除套餐:{}",ids);setmealService.deleteBatch(ids);return Result.success();}/*** 修改套餐* @param setmealDTO* @return*/@PutMapping@ApiOperation("修改套餐")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result update(@RequestBody SetmealDTO setmealDTO){log.info("修改套餐信息:{}",setmealDTO);setmealService.update(setmealDTO);return Result.success();}/*** 套餐起售停售* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("套餐起售停售")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result startOrStop(@PathVariable Integer status, Long id) {setmealService.startOrStop(status, id);return Result.success();}}

购物车功能

添加购物车

需求分析和产品原型

菜品:设置口味数据:点击的是选择规格然后才能加入购物车
未设置口味数据:直接加入
套餐:直接加入
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设置冗余字段可以增加查询速度(不用查多表查单表即可)
在这里插入图片描述
注意点非常多,代码还是挺难实现的,建议仔细看看不同情况 菜品 套餐的处理
菜品有无口味,如果包含该菜品/套餐需要实现数量+1而不是新增操作了
设计多个表 setmeal dish 等 且可能涉及回查操作
重点就是搞清我们插入需要什么数据,什么数据还没有,怎么进行获取!!!

ShoppingCartController

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

ShoppingCartMapper

@Mapper
public interface ShoppingCartMapper {/*** 动态条件查询* @param shoppingCart* @return*/List<ShoppingCart> list(ShoppingCart shoppingCart);/*** 根据id修改商品数量* @param shoppingCart*/@Update("update shopping_cart set number = #{number} where id= #{id}")void updateNumberById(ShoppingCart shoppingCart);/**** @param shoppingCart*/@Insert("insert into shopping_cart(name,user_id,dish_id,setmeal_id,dish_flavor,number,amount,image,create_time)" +"values(#{name},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{image},#{createTime}) ")void insert(ShoppingCart shoppingCart);
}

对应xml文件

<mapper namespace="com.sky.mapper.ShoppingCartMapper"><select id="list" resultType="com.sky.entity.ShoppingCart">select * from shopping_cart<where><if test="userId != null">and user_id = #{userId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where></select>
</mapper>

重量级ShoppingCartServiceImpl

@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {@Autowiredprivate ShoppingCartMapper shoppingCartMapper;@Autowiredprivate DishMapper dishMapper;@Autowiredprivate SetmealMapper setmealMapper;/*** 添加购物车* @param shoppingCartDTO*/public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {//添加购物车两种情况1.本身就在购物车里面 就让对应的number+1 不是的话就添加//判断是否已经存在ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);//还少userIdLong currentId = BaseContext.getCurrentId();shoppingCart.setUserId(currentId);List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);//如果存在,只需要将数量+1//实际上只能查出来一条if (list != null && list.size()>0){ShoppingCart cart = list.get(0);cart.setNumber(cart.getNumber()+1);//update shopping_cart set number = ? where id = ?shoppingCartMapper.updateNumberById(cart);}else {//如果不存在,只需要插入一条购物车数据//然后是插入,但是插入的话前段没提供name,image等信息所以要先查一下//菜品差菜品表,套餐查套餐表//判断是菜品还是套餐Long dishId = shoppingCartDTO.getDishId();if(dishId != null){//菜品Dish dish = dishMapper.getById(dishId);shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shoppingCart.setAmount(dish.getPrice());//购物车价格是amount}else {Long setmealId = shoppingCartDTO.getSetmealId();Setmeal setmeal = setmealMapper.getById(setmealId);shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shoppingCart.setAmount(setmeal.getPrice());//购物车价格是amount}shoppingCart.setNumber(1);//第一次添加数量肯定为1shoppingCart.setCreateTime(LocalDateTime.now());shoppingCartMapper.insert(shoppingCart);}}
}

测试


自己去把套餐和对应的菜品都添加一下,再看看数量变化,一个菜品+两次debug看一下对应语句对不对
再去数据库检查一下

查看购物车

产品原型
在这里插入图片描述
接口设计
在这里插入图片描述
controller

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

ShoppingCartServiceImpl

/*** 查看购物车* @return*/public List<ShoppingCart> showShoppingCart() {Long id = BaseContext.getCurrentId();List<ShoppingCart> list = shoppingCartMapper.list(ShoppingCart.builder().userId(id).build());return list;}
}

mapper的list是用之前的定义的方法所以没有mapper层
自己测试

清空购物车

在这里插入图片描述
controller

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

service

    /*** 清空购物车数据*/public void cleanShoppingCart() {Long id = BaseContext.getCurrentId();shoppingCartMapper.deleteByUserId(id);}
}

Mapper

    /*** 清空购物车* @param id*/@Delete("delete  from shopping_cart where user_id=-#{id}")void deleteByUserId(Long id);
}

自己测试

相关文章:

Java项目-苍穹外卖-Day07-redis缓存应用-SpringCache/购物车功能

文章目录 前言缓存菜品问题分析和实现思路缓存菜品数据清理缓存数据功能测试 SpringCache介绍入门案例 缓存套餐购物车功能添加购物车需求分析和产品原型测试 查看购物车清空购物车 前言 本章节主要是进行用户端的购物车功能开发 和redis作为mysql缓存的应用以及SpringCache的…...

零知识证明(zk-SNARK)(一)

全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge&#xff0c;简洁非交互式零知识证明&#xff0c;简洁性使得运行该协议时&#xff0c;即便statement非常大&#xff0c;它的proof大小也仅有几百个bytes&#xff0c;并且验证一个proof的时间可以达到毫秒…...

linux中打印数据的行缓冲模式

1. 回车换行符在Window下和在Linux下的区别&#xff1a; 在Window下&#xff1a;回车换行符为\r\n 在Linux下&#xff1a;回车换行符为\n \n为换行符&#xff0c;换行相当于光标跳转到下一行的这个位置 \r为回车符&#xff0c;回车相当于光标跳转到当前行的最左边的位置 所以…...

香橙派OrangePi zero H2+ 驱动移远4G/5G模块

目录 1 安装系统和内核文件&#xff1a; 1.1 下载镜像 1.2 内核头安装 1.2.1 下载内核 1.2.2 将内核头文件导入开发板中 1.2.3 安装内核头 2 安装依赖工具&#xff1a; 2.1 Installing Required Host Utilities 3 驱动步骤&#xff1a; 3.1 下载模块驱动文件…...

自动驾驶——【规划】记忆泊车特殊学习路径拟合

1.Back ground 如上图&#xff0c;SLAM学习路线Start到End路径&#xff0c;其中曲线SDAB为D档位学习路径&#xff0c;曲线BC为R学习路径&#xff0c;曲线AE为前进档D档学习路径。 为了使其使用记忆泊车时&#xff0c;其驾驶员体验感好&#xff0c;需去除R档倒车部分轨迹&#x…...

【跟小嘉学 Rust 编程】十六、无畏并发(Fearless Concurrency)

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

Android 进阶——图形显示系统之VSync和 Choreographer的创建详解(一)

引言 前一篇文章Android 进阶——图形显示系统之底层图像显示原理小结(一)介绍了关于Android 图形显示系统的基础理论,相信你对于Android的图形显示系统中图形界面渲染刷新机制有了更深的了解,接下来进一步讲解VSync和Choreography的联系和作用。 一、VSync 信号的产生概…...

SQL Server开启变更数据捕获(CDC)

一、CDC简介 变更数据捕获&#xff08;Change Data Capture &#xff0c;简称 CDC&#xff09;&#xff1a;记录 SQL Server 表的插入、更新和删除操作。开启cdc的源表在插入、更新和删除操作时会插入数据到日志表中。cdc通过捕获进程将变更数据捕获到变更表中&#xff0c;通过…...

八、性能测试

八、性能测试 8.1 性能测试代码 #include"ConcurrentAlloc.h"// ntimes 一轮申请和释放内存的次数 // rounds 轮次 void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {std::vector<std::thread> vthread(nworks);std::atomic<size_t&g…...

景芯SoC 芯片全流程培训

【全网唯一】景芯SoC是一款用于芯片全流程培训的低功耗ISP图像处理SoC&#xff0c;采用低功耗RISC-V处理器&#xff0c;内置ITCM SRAM、DTCM SRAM&#xff0c;集成包括MIPI、ISP、CNN、QSPI、UART、I2C、GPIO、百兆以太网等IP&#xff0c;采用SMIC40工艺设计流片。 培训数据包括…...

目标检测后的图像上绘制边界框和标签

效果如图所示&#xff0c;有个遗憾就是CV2在图像上显示中文有点难&#xff0c;也不想用别的了&#xff0c;所以改成了英文&#xff0c;代码在下面了&#xff0c;一定要注意一点&#xff0c;就是标注文件的读取一定要根据自己的实际情况改一下&#xff0c;我的所有图像的标注文件…...

Leetcode: 1. 两数之和 【题解超详细】

前言 有人夜里挑灯看花&#xff0c;有人相爱&#xff0c;有人夜里开车看海&#xff0c;有人leetcode第一题都做不出来。 希望下面的题解可以帮助你们开始 你们的 leetcode 刷题 的 天降之路 题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中…...

PHP 通过 Redis 解决并发请求的操作问题

比如PHP收到两个并发的请求A和B&#xff0c;要求只能其中一个请求处理S1操作&#xff0c;另一个请求直接返回失败&#xff0c;可以通过redis去解决&#xff1a; SETNX&#xff08;SET if Not eXists&#xff09;是 Redis 中的一个原子命令&#xff0c;用于设置键-值对&#xf…...

浅谈信息论和信息编码

目录 背景 信息是什么 信息度量 小白鼠实验 哈夫曼编码 密码学 其它应用 背景 克劳德艾尔伍德香农&#xff08;Claude Elwood Shannon&#xff09;出生于 1916 年 美国密歇根州。1936 年毕业于密歇根大学&#xff0c;获得数学和电子工程学士学位。之后&#xff0c;他在麻…...

【测试】笔试02

文章目录 1. 下面不属于软件测试步骤的是2. 关于测试驱动开发&#xff0c;描述错误的是3. 在软件测试中&#xff0c;圈复杂度&#xff08;Cyclomatic complexity&#xff09;&#xff1a;代码逻辑复杂度的度量&#xff0c;提供了被测代码的路径数量。圈复杂度可通过系统控制流图…...

公司内部网段多管控乱,该如何规范跨网文件传输交换?

古往今来&#xff0c;高筑墙一直是有效的防御措施。从边塞长城到护城河外的高高城墙&#xff0c;都是利用隔离地域的形式实现保护安全域的效果。这样一来&#xff0c;城内的安全域可以在遇到危险时受到有效保护。 在企业网络安全防护方面&#xff0c;网络安全域隔离也是网络安全…...

Ceph入门到精通-OSD waring 设置建议

OSD 以下检查表明 OSD 节点存在问题。 警告 1 在 /var/lib/ceph/osd 中找到的多个ceph_fsid值。 这可能意味着您正在托管许多集群的 OSD 此节点或某些 OSD 配置错误以加入 您期望的集群。 2 设置可能会导致数据丢失&#xff0c;因为如果 未达到最小值&#xff0c;Ceph 将不会确…...

软件测试工程师如何快速理解业务?

1. 阅读需求文档和业务资料 仔细阅读与业务相关的文档和资料对于理解业务至关重要。 需求文档通常描述了软件的功能和用户需求&#xff0c;而业务规范则详细说明了业务流程、规则和标准。 仔细阅读这些文档&#xff0c;你可以了解业务的基本概念、要求和流程。 同时&#x…...

【教程】部署apprtc服务中安装google-cloud-cli组件的问题及解决

#0# 前置条件 已经安装完成node&#xff0c;grunt&#xff0c;node 组件和python pip包等。需要安装google-cloud-cli组件。 Ubuntu安装google-cloud-cli组件 apprtc项目运行需要google-cloud-cli前置组件&#xff0c;且运行其中的dev_appserver.py。 根据google官方的关于安…...

C++——shared_ptr:make_shared的用处,与shared_ptr直接构造的区别

shared_ptr shared_ptr继承自__shared_ptr&#xff0c;其中有两个对象&#xff0c;一个是指向资源的指针&#xff0c;一个是控制块&#xff0c;指向一个引用计数对象。控制块中存储了强引用和弱引用的计数&#xff0c;强引用Uses代表shared_ptr对象的引用计数&#xff0c;弱引…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...

ArcPy扩展模块的使用(3)

管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如&#xff0c;可以更新、修复或替换图层数据源&#xff0c;修改图层的符号系统&#xff0c;甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...

python读取SQLite表个并生成pdf文件

代码用于创建含50列的SQLite数据库并插入500行随机浮点数据&#xff0c;随后读取数据&#xff0c;通过ReportLab生成横向PDF表格&#xff0c;包含格式化&#xff08;两位小数&#xff09;及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...

二叉树-144.二叉树的前序遍历-力扣(LeetCode)

一、题目解析 对于递归方法的前序遍历十分简单&#xff0c;但对于一位合格的程序猿而言&#xff0c;需要掌握将递归转化为非递归的能力&#xff0c;毕竟递归调用的时候会调用大量的栈帧&#xff0c;存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧&#xff0c;而非…...