商城积分系统的代码实现(上)-- 积分账户及收支记录
一、背景
上一系列文章,我们说了积分的数模设计及接口设计,接下里,我们将梳理一下具体的代码实现。
使用的语言的java,基本框架是spring-boot,持久化框架则是Jpa。
使用到的技术点有:
- 分布式锁(积分发放和消耗,在分布式场景下,防止网络重试带来的重复请求问题)
- 乐观锁(更新积分账户表和积分订单表)
- 事件驱动机制(积分账户遇有变更,及时通知用户,发送消息提醒)
限于篇幅,我们将分文两篇来讲:
- 积分账户及收支记录
- 积分订单的退款和结算
二、积分的收入
用户能够通过三种途径获得积分,发放的核心逻辑是一致的,但三者的前置校验不同。
所以,我们定义三个不同的方法,各自校验完成,统一调用发放积分的方法。
因为涉及多次操作数据库,需要开启事务,并且修改事务的隔离级别为Isolation.READ_COMMITTED,见下代码。(原因见后文的乐观锁实现)
- 购买虚拟货币/积分
@Lock(name = POINTS_DISTRIBUTE_LOCK_PRE, key = "'buy:orderNo:' + #orderNo")@Transactional(rollbackFor = Throwable.class, isolation = Isolation.READ_COMMITTED)public Long grantByBuy(Integer schoolId, Long userId, String pointsType, Integer points,String orderNo, String remark, String token) {// 查询是否已经发放过,防止重复boolean syncSuccess = this.syncPointsOrder(orderNo, schoolId, userId, pointsType, points);if (!syncSuccess) {return null;}return this.grant(schoolId, userId, PointsChannelEnum.BUY.getCode(), PointsChannelEnum.BUY.getName(),pointsType, points,orderNo, null, remark, token);}
- 手动发放积分
@Lock(name = POINTS_DISTRIBUTE_LOCK_PRE, key = "'artificial:userId:' + #userId")@Transactional(rollbackFor = Throwable.class, isolation = Isolation.READ_COMMITTED)public Long grantByArtificial(Integer schoolId, Long userId,String pointsType, Integer points,String optUserId, String remark, String token) {return this.grant(schoolId, userId, PointsChannelEnum.GRANT_BY_HAND.getCode(),PointsChannelEnum.GRANT_BY_HAND.getName(), pointsType, points,null, optUserId, remark, token);}
- 做任务,获得积分奖励
@Lock(name = POINTS_DISTRIBUTE_LOCK_PRE, key = "'grant:userId:' + #userId + ':channelCode:' + #channelCode")@Transactional(rollbackFor = Throwable.class, isolation = Isolation.READ_COMMITTED)public Long grantByChannel(Integer schoolId, Long userId,String channelCode, String pointsType,String remark, String token) {// 校验channelCodePointsChannel pointsChannel = pointsChannelRepository.findByCodeAndPointsType(channelCode, pointsType);Precondition.notNull(pointsChannel, "积分渠道[%s]未配置", channelCode);Precondition.isTrue(pointsChannel.getRewardPoints() > 0, "积分渠道配置的积分数必须大于0");return this.grant(schoolId, userId,channelCode, pointsChannel.getName(), pointsType, pointsChannel.getRewardPoints(),null, null, remark, token);}
1、发放积分
除了校验token不能重复使用外,第一步是增加账户的余额,第二步是保存账户的收支记录,第三步是异步通知操作(提醒用户,积分账户有变更,因为非主流程,所以异步,这里采用事件驱动机制)。
private Long grant(Integer schoolId, Long userId,String channelCode, String channelName,String pointsType, Integer rewardPoints,String orderNo, String optUserId, String remark, String token) {if (log.isInfoEnabled()) {log.info("开始发放积分, 入参列表:[schoolId={}, userId={}, channelCode={}, pointsType={}, rewardPoints={}, " +"orderNo={}, optUserId={}, remark={}, token={}]",schoolId, userId, channelCode, pointsType, rewardPoints, orderNo, optUserId, remark, token);}// 校验token不能重复使用(略)//1.账户增加余额PointsAccount pointsAccount = pointsAccountService.findPointsAccount(schoolId, userId, pointsType);if (null == pointsAccount) {// 创建账户pointsAccountService.save(schoolId, userId, pointsType, rewardPoints);} else {boolean updateSuccess = this.optimisticUpdateAccount(GRANT_POINTS_ACCOUNT,pointsAccount.getId(), pointsAccount.getPoints(),rewardPoints, pointsAccount.getVersion());if (!updateSuccess) {if (log.isWarnEnabled()) {log.warn("发放积分出现错误, [schoolId={}, userId={}, channelCode={}, pointsType={}, rewardPoints={}]",schoolId, userId, channelCode, pointsType, rewardPoints);}Precondition.isTrue(false, "发放积分给用户%d出现错误", userId);}}//2.保存账户变更记录PointsAccountFlow flow = pointsAccountFlowService.savePointsAccountFlow(FlowTypeEnum.INCREASE,schoolId, userId, pointsType,rewardPoints, channelCode, channelName,orderNo, optUserId, remark);// 3. 发布异步事件,提醒用户其账户有变更。(略)if (log.isInfoEnabled()) {log.info("完成发放积分, [schoolId={}, userId={}, channelCode={}, pointsType={}, rewardPoints={}, " +"orderNo={}, optUserId={}, remark={}, token={}]",schoolId, userId, channelCode, pointsType, rewardPoints, orderNo, optUserId, remark, token);}return flow.getId();}
2、乐观锁实现账户的变更
乐观更新账户, 重试N次,如果更新失败,则再次查询DB最新数据。
我们使用的是mysql数据库,其默认隔离级别是可重复读,所以上文需要指定方法的隔离级别是Isolation.READ_COMMITTED,否则在同一个事务中,读取不到其他事务提交的最新数据。
这是关于数据库的隔离级别,第二点,因为我们使用的jpa持久化框架,它有着著名的一级缓存和二级缓存;所以我们需要手动清除其一级缓存。
@Autowiredprivate EntityManager entityManager;//清除jpa一级缓存entityManager.clear();
第三点,我们在update行记录的时候,判断version是否一致。
- optimisticUpdateAccount()
private boolean optimisticUpdateAccount(int optType, long accountId, int points, int thisPoints, long version) {int time = 0;boolean success = false;while (time < MAX_RETRY_TIME) {int result = 0;switch (optType) {// 这两种情况是增加余额// 发放积分case GRANT_POINTS_ACCOUNT:// 回退积分case ROLLBACK_POINTS_ACCOUNT:result = pointsAccountService.updateAccountPoints(accountId,points + thisPoints,version);break;// 这两种情况是减少余额// 使用积分case USE_POINTS_ACCOUNT:// 积分订单的退款case REFUND_POINTS_ACCOUNT:result = pointsAccountService.updateAccountPoints(accountId,points - thisPoints,version);break;default:break;}if (result == 1) {success = true;break;}//清除jpa一级缓存entityManager.clear();try {Thread.sleep(100);} catch (InterruptedException e) {log.error("乐观锁更新账户余额中的sleep出现异常", e);}PointsAccount pointsAccount = pointsAccountService.findPointsAccount(accountId);Precondition.notNull(pointsAccount, "积分账户不存在");version = pointsAccount.getVersion();points = pointsAccount.getPoints();time++;}return success;}
- modifyAccountPoints()
@Modifying@Query(value = "update PointsAccount set points = :points, version = version + 1, modifiedDate = now() " +" where id = :id and version = :oldVersion ")int modifyAccountPoints(@Param("id") long id,@Param("points") int points,@Param("oldVersion") long oldVersion);
三、消耗积分
分为四步:
- 1、更新账户的余额,保证此次消耗的积分是小于等于账户的余额
- 2、保存账户变更记录
- 3、发布异步事件,通知用户其账户变更
- 4、更新积分订单表:已使用积分数、可用积分数、可结算积分数
关于积分订单表的更新,见下一篇文章。
@Lock(name = POINTS_DISTRIBUTE_LOCK_PRE, key = "'use:orderNo:' + #orderNo")@Transactional(rollbackFor = Throwable.class, isolation = Isolation.READ_COMMITTED)public void use(Integer schoolId, Long userId, String orderNo, String pointsType, Integer points, String remark) {if (log.isInfoEnabled()) {log.info("开始消费积分, 入参列表:[schoolId={}, userId={}, orderNo={}, pointsType={}, points={}, remark={}]",schoolId, userId, orderNo, pointsType, points, remark);}//1.更新账户的余额this.updateAccount(USE_POINTS_ACCOUNT, schoolId, userId, pointsType, points);//2.保存账户变更记录pointsAccountFlowService.savePointsAccountFlow(FlowTypeEnum.DECREASE,schoolId, userId,pointsType, points,PointsChannelEnum.USE.getCode(), PointsChannelEnum.USE.getName(),orderNo, null,remark);//3.发布异步事件,通知用户其账户变更(略)//4.更新积分订单表中的已使用积分数和可用积分数以及可结算积分数// 根据userId/schoolId/pointsType查询可用的的积分,按时间先后顺序扣减订单的可用积分数this.updatePointsOrderByUse(schoolId, userId, pointsType, points);if (log.isInfoEnabled()) {log.info("完成消费积分, [schoolId={}, userId={}, orderNo={}, pointsType={}, points={}, remark={}]",schoolId, userId, orderNo, pointsType, points, remark);}}
四、积分的回退
当商品的定价是纯积分方式,或者积分+现金的组合方式,这类商品发生退款后,我们需要把用户消耗的积分回退其账户。
所谓积分的回退,相当于给用户再次发放等量的积分。
@Lock(name = POINTS_DISTRIBUTE_LOCK_PRE, key = "'rollback:orderNo:' + #orderNo")@Transactional(rollbackFor = Throwable.class, isolation = Isolation.READ_COMMITTED)public void rollback(Integer schoolId, Long userId, String orderNo, String pointsType, Integer points) {if (log.isInfoEnabled()) {log.info("开始回退积分, 入参列表:[schoolId={}, userId={}, orderNo={}, pointsType={}, points={}]",schoolId, userId, orderNo, pointsType, points);}// 仅检查账户是否存在PointsAccount pointsAccount = pointsAccountService.findPointsAccount(schoolId, userId, pointsType);Precondition.isTrue(null != pointsAccount, "积分账户[%d]不存在", userId);//1.把扣除的积分回退到用户的账户余额里boolean updateSuccess = this.optimisticUpdateAccount(ROLLBACK_POINTS_ACCOUNT,pointsAccount.getId(), pointsAccount.getPoints(),points, pointsAccount.getVersion());if (!updateSuccess) {if (log.isWarnEnabled()) {log.warn("回退积分出现错误, [schoolId={}, userId={}, orderNo={}, pointsType={}, points={}]",schoolId, userId, orderNo, pointsType, points);}Precondition.isTrue(false, "回退用户[%d]的积分出现错误", userId);}//2.保存账户变更记录pointsAccountFlowService.savePointsAccountFlow(FlowTypeEnum.INCREASE,schoolId, userId, pointsType,points, PointsChannelEnum.CANCEL_ORDER.getCode(), PointsChannelEnum.CANCEL_ORDER.getName(),orderNo, null, "订单号[" + orderNo + "]取消");//3.发布异步事件,通知用户其账户变更(略)if (log.isInfoEnabled()) {log.info("完成回退积分, [schoolId={}, userId={}, orderNo={}]", schoolId, userId, orderNo);}}
五、总结
本文详细介绍了积分操作的五个方法,总体的实现逻辑都是更新账户的余额、保存账户的收支记录、最后通知用户其账户余额有变更。
无非是他们的校验逻辑不一样罢了,所以逻辑实现的方法必须复用。
消耗积分和积分的回退,区别有两点:
- 1、是否更新积分订单表
- 2、前者是减少账户的余额,后者是增加账户的余额。
后文,我们将梳理积分订单的实现。
相关文章:
![](https://img-blog.csdnimg.cn/direct/8e135746724f45f8a8eb211b45b0c6c3.png)
商城积分系统的代码实现(上)-- 积分账户及收支记录
一、背景 上一系列文章,我们说了积分的数模设计及接口设计,接下里,我们将梳理一下具体的代码实现。 使用的语言的java,基本框架是spring-boot,持久化框架则是Jpa。 使用到的技术点有: 分布式锁…...
![](https://img-blog.csdnimg.cn/direct/dffb025a07044c958daffd0684af3cb9.jpeg#pic_center)
【C++进阶9】异常
一、C语言传统的处理错误的方式 终止程序,如assert 如发生内存错误,除0错误时就会终止程序返回错误码 需要程序员自己去查找对应的错误 z如系统的很多库的接口函数都是通 过把错误码放到errno中,表示错误 二、C异常概念 异常:函…...
![](https://img-blog.csdnimg.cn/direct/2d720a11e147402b9f07c702e34d374b.gif)
RecyclerVIew->加速再减速的RecyclerVIew平滑对齐工具类SnapHelper
XML文件 ItemView的XML文件R.layout.shape_item_view <?xml version"1.0" encoding"utf-8"?> <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"100dp"android:layout_heig…...
![](https://img-blog.csdnimg.cn/direct/ae56c0d8596245d7bd8da7ed9fdf3c82.png)
突破SaaS产品运营困境:多渠道运营如何集中管理?
随着数字化时代的到来,SaaS(软件即服务)产品已成为企业日常运营不可或缺的工具。然而,在竞争激烈的市场环境下,SaaS产品运营越来越重视多渠道、多平台布局,以更广泛地触及潜在用户,然而…...
![](https://i-blog.csdnimg.cn/direct/01e20842236444409e0c711b28a0c671.jpeg)
智能语音热水器:置入NRK3301离线语音识别ic 迈向智能家居新时代
一、热水器语音识别芯片开发背景 在科技的今天,人们对于生活品质的追求已不仅仅满足于基本的物质需求,更渴望通过智能技术让生活变得更加便捷、舒适。热水器作为家庭生活中不可或缺的一部分,其智能化转型势在必行。 在传统热水器使用中&#…...
![](https://img-blog.csdnimg.cn/direct/bf2883daad7c4f90b27eb9a355db8c73.png)
Redis集群部署合集
目录 一. 原理简述 二. 集群配置 2.1 环境准备 2.2 编译安装一个redis 2.3 创建集群 2.4 写入数据测试 实验一: 实验二: 实验三: 实验四: 添加节点 自动分配槽位 提升节点为master: 实验…...
![](https://www.ngui.cc/images/no-images.jpg)
【HDFS】关于Hadoop的IPC.Client类的一些整理
org.apache.hadoop.ipc.Client 类是IPC服务的一个客户端。 IPC请求把一个Writable对象当做参数,返回一个Writable对象当做结果value。 一个IPC服务运行在某个端口上,并且由参数class和value class定义。 Router里的IPC.Client对象就两个 有这样一个类:ClientCache 看名字就…...
![](https://img-blog.csdnimg.cn/img_convert/acb9ebb45f0c4e5c136be197cf33e810.png)
Swoole v6 能否让 PHP 再次伟大?
现状 传统的 PHP-FPM 也是多进程模型的的运行方式,但每个进程只能处理完当前请求,才能接收下一个请求。而且对于 PHP 脚本来说,只是接收请求和响应请求,并不参与网络通信。对数据库资源的操作,也是一次请求一次有效&am…...
![](https://www.ngui.cc/images/no-images.jpg)
C++ STL Iterator Adapter
1. std::back_insert_iterator 使用 // back_insert_iterator example #include <iostream> // std::cout #include <iterator> // std::back_insert_iterator #include <vector> // std::vector #include <algorithm> // std::copy…...
![](https://www.ngui.cc/images/no-images.jpg)
android-aidl5
aidl类是实现Manager和Service通信的桥梁。 例如在修改Android Wifi功能的时候看到WifiManager管理WifiService; AIDL是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。 比如onclick(),用oneway修…...
![](https://img-blog.csdnimg.cn/direct/8a03d717d89c4233b8a21c7a1bc68c9b.png)
day01-项目介绍及初始化-登录页
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 day01-项目介绍及初始化-登录页一、人力资源项目介绍1.1项目架构和解决方案主要模块解决的问题 二、拉取项目基础代码1.引入库2.升级core-js版本到3.25.5按照完整依…...
![](https://img-blog.csdnimg.cn/direct/770b47d9fd3a453f943a1027e45a430f.png)
华为开发者大会:全场景智能操作系统HarmonyOS NEXT
文章目录 一、全场景智能操作系统 - HarmonyOS NEXT1.1 系统特性1.2 关于架构、体验和生态 二、应用案例2.1 蚂蚁mpaas平台的性能表现 三、新版本应用框架发布3.1 新语言发布3.2 新数据库发布3.3 新版本编译器的发布 四、CodeArts和DataArts4.1 CodeArts4.2 DataArts 五、总结 …...
![](https://www.ngui.cc/images/no-images.jpg)
深度学习二分类评估详细解析与代码实战
深度学习二分类的实战代码:使用 Trainer API 微调模型. https://huggingface.co/learn/nlp-course/zh-CN/chapter3/3 如果你刚接触 自然语言处理,huggingface 是你绕不过去的坎。但是目前它已经被墙了,相信读者的实力,自行解决吧。…...
![](https://www.ngui.cc/images/no-images.jpg)
c++笔记容器详细介绍
C标准库提供了多种容器来存储和管理数据。这些容器属于<vector>, <list>, <deque>, <map>, <set>, <unordered_map>, <unordered_set>等头文件中。这些容器各有优缺点,适用于不同的场景。下面详细介绍几种主要的容器及其…...
![](https://img-blog.csdnimg.cn/direct/b837dd761dac4273baecc91fb23b77bb.png)
CS144 Lab3 TCPSender复盘
一.基础概念 1.TCPSender在TCPSocket中的地位与作用 Lab0中实现了基于内存模拟的流控制-字节流(ByteStream),底层使用std::deque实现,根据最大容量Capacity进行容量控制。个人理解它相当于应用层的输入输出缓存区,用户…...
![](https://img-blog.csdnimg.cn/direct/15fd9ef462d345469cf139fb57a33454.png#pic_center)
建筑可视化中使用云渲染的几大理由
在建筑行业中,可视化技术已成为不可或缺的一部分。无论是设计方案的展示、施工进度的模拟,还是最终效果的呈现,建筑可视化都发挥着至关重要的作用。 建筑可视化是指通过计算机技术和图形学算法,将建筑设计、规划和施工过程中的数据…...
![](https://img-blog.csdnimg.cn/direct/2efc9ba8753e44e19ae516ee2ebb3018.png)
Python数据可视化-地图可视化
1.首先绘制实现数据可视化的思维导图 具体要实现什么功能-怎么处理,先把思路写好 数据来源: 爬取的数据 运行结果: 部分代码: 完整代码请在下方↓↓↓👇获取 转载请注明出处!...
![](https://img-blog.csdnimg.cn/direct/ebf52667e85c4d37bf5054879b8ec06c.png)
leetcode 动态规划(基础版)单词拆分
题目: 题解: 一种可行的dp做法是基于完全背包问题,将s看成是一个背包,wordDict看作是物品,然后往s中放入物品判断最终是否可以变为给定的s即可。这道题和上一题都用到了在dp如何枚举连续子串和状态表示:枚…...
![](https://img-blog.csdnimg.cn/direct/dcfb20f770d94902ad112037555fc0f3.png)
Ubuntu/Linux调试安装南京来可CAN卡
准备好USB rules文件和can driver文件备用! 必做:放置USB rules文件到对应位置处理权限问题 而后:安装内核driver并编译。需求众多依赖编译环境,视情况安装填补。如GCC,G,make等等 进入对应64bit文件夹中,添加权限,执…...
![](https://www.ngui.cc/images/no-images.jpg)
vue2+TS获取到数据后自动叫号写法
1.父组件写法 初始化: //引入子组件 <odialog ref"odialogRef" onSure"onSurea"></odialog> //子传父private onSurea() {// 初始化信息/重新叫号来的数据this.initTabelData()setTimeout(() > {// 播放声音的数据this.search…...
![](https://www.ngui.cc/images/no-images.jpg)
28、架构-边界:微服务的粒度
微服务的粒度 在设计微服务架构时,确定微服务的粒度是一个关键问题。粒度过大或过小都会带来不同的问题,因此需要找到合理的粒度来划分微服务。下面详细探讨微服务粒度的合理范围及其影响因素。 1. 微服务粒度的上下界 微服务的粒度不应该只有唯一正确…...
![](https://img-blog.csdnimg.cn/direct/33d461e4ca89466b91d9d2da4480c9a5.png)
开源API网关-ApacheShenYu首次按照启动遇到的问题
一.背景 公司有API网关产品需求,希望有图形化的后台管理功能。看到了ApacheShenYu,作为Apache的顶级项目,直接认可了。首先,感谢各位大神的付出,初步看这个项目是国内大厂中的大神创立的,在此表示膜拜&…...
![](https://img-blog.csdnimg.cn/direct/2f7fa506dcbb440bae2b95c6c4fb0f15.png)
uniapp获取证书秘钥、Android App备案获取公钥、签名MD5值
一、 uniapp获取证书秘钥 打开uniapp开发者中心下载证书打开cmd输入以下这段代码,下载提供查看到的密钥证书密码就可以了!下载证书在 java 环境下运行才可以 // your_alias 换成 证书详情中的别名,your_keystore.keystore 改成自己的证书文件…...
![](https://www.ngui.cc/images/no-images.jpg)
QT 如何储存多种数据类型(QVariant )
QVariant 是 Qt 框架中用于存储各种数据类型的类。它提供了一个强大的类型系统,允许你在运行时存储和检索多种类型的数据,而不需要在编译时确定类型。QVariant 的主要优点在于它的灵活性和通用性,这使得它在 Qt 的很多组件和机制中都被广泛使…...
![](https://www.ngui.cc/images/no-images.jpg)
持续总结中!2024年面试必问的操作系统面试题(九)
上一篇地址:持续总结中!2024年面试必问的操作系统面试题(八)-CSDN博客 十七、解释什么是操作系统的安全性和它的重要性。 操作系统的安全性(Operating System Security)是指操作系统采取的一系列措施来保…...
![](https://www.ngui.cc/images/no-images.jpg)
操作系统入门 -- 文件管理
操作系统入门 – 文件管理 1.文件管理概述 1.1 文件系统基本功能 目前,计算机内存的容量依然有限,并且其特性决定了数据无法长时间保存,因此把执行的数据以文件形式保存在外存中,等到需要使用时再调入内存。所以,操…...
![](https://www.ngui.cc/images/no-images.jpg)
由浅入深,走进深度学习(2)
今天分享的学习内容主要就是神经网络里面的知识啦,用到的框架就是torch 在这里我也是对自己做一个学习记录,如果不符合大家的口味,大家划走就可以啦 可能没有什么文字或者原理上的讲解,基本上都是代码,但是我还是想说…...
![](https://img-blog.csdnimg.cn/direct/310a788eefd74616aa098f1882f86799.png)
【Python Tips】创建自己的函数包并安装进Anaconda,像引入标准包一样直接import导入
目录 一、引言 二、方法步骤 步骤一:创建包目录结构 步骤二:配置__init__.py文件 步骤三:文件夹外配置setup.py文件 步骤四:终端Pip安装 三、结尾 一、引言 在编写项目代码的时候,有些自定义功能的函数是可以复用的。…...
![](https://img-blog.csdnimg.cn/direct/1d8e038ffefd47028a1edc36afd83bb2.png)
【Python机器学习实战】 | 基于支持向量机(Support Vector Machine, SVM)进行分类和回归任务分析
🎩 欢迎来到技术探索的奇幻世界👨💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…...
![](https://img-blog.csdnimg.cn/direct/7377356665a94e9e990dfbcb537c521f.png)
备份和还原
stai和dnta snat:源地址转换 内网---外网 内网ip转换成可以访问外网的ip 内网的多个主机可以使用一个有效的公网ip地址访问外部网络 DNAT:目的地址转发 外部用户,可以通过一个公网地址访问服务内部的私网服务。 私网的ip和公网ip做一个…...
![](https://www.ngui.cc/images/no-images.jpg)
Java数组的初始化方法
Java数组的初始化方法 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!在Java编程中,数组是一种非常基础也非常重要的数据结构,它能够存储…...
![](https://www.ngui.cc/images/no-images.jpg)
通过分离有色和无色pdf页面减少打印费
前言 该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具,去打印店打印全彩的毕业论文的话会比较贵,他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印,前者打印彩色,后者打印黑白…...
![](https://img-blog.csdnimg.cn/direct/df791a3dc1cb4ddabf474bb731dca4c0.png)
c语言--指针
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…...
![](https://img-blog.csdnimg.cn/f9f686b7a5ec435ab24bf9b05ec6429c.jpg)
python-九九乘法表(对齐式1)
[题目描述] 输出九九乘法表,输出格式见样例。输入格式: 无输出格式: 输出乘法表,对齐方式见样例输出。样例输入 无样例输出 来源/分类(难度系数:一星) 完整代码展示: #对齐式1 a[] …...
![](https://www.ngui.cc/images/no-images.jpg)
thinkphp单独为某个接口设置缓存
参考 官方文档 $this->request->cache(__URL__,600);只需要在接口方法的开头添加这个代码即可...
![](https://img-blog.csdnimg.cn/direct/ba352745970a4484a1dbbe22990fe252.png)
OpenCV视觉--视频人脸微笑检测(超详细,附带检测资源)
目录 概述 具体实现 1.加载分类器 2.打开摄像头并识别人脸 3.处理人脸并检测是否微笑 效果 总结 概述 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,广泛应用于图像处理和视频分析等领…...
![](https://img-blog.csdnimg.cn/direct/212f0040ebfe4daf812f83eaea683b69.png)
docker 搭建 AI大数据模型 --- 使用GPU
docker 搭建 AI大数据模型 — 使用GPU方式 搭建本地大模型,最简单的方法!效果直逼GPT 服务器GPU系统HP580 G8P40Rocky9.2 安装程序AnythingLLM前端界面Open WebUIChatOllamaollama 一、AnythingLLM 介绍 AnythingLLM 是 Mintplex Labs Inc. 开发的一…...
![](https://img-blog.csdnimg.cn/direct/3fbe39f0203646289992826c02cddd99.png)
面向对象, 常用类, 集合, 异常, JDBC, mysql数据库 复习
1.面向对象 (1)面向过程和面向对象 ● 面向过程的程序设计思想 (procedure -Oriented Programming),简称POP ● 关注的焦点是过程:过程就是操作数据的步骤。如果某个过程的实现代码重复出 现,那么就可…...
![](https://www.ngui.cc/images/no-images.jpg)
js取数组最大值之Math.max、Math.max.apply
js取数组最大值之Math.max、Math.max.apply Math.maxMath.max.applyapply()第一个参数为什么可以是null 最小值同理 Math.max Math.max(n1,n2,n3,…,nX) 支持传递多个参数,带有较大的值的那个数 Math.max(2,5,3,6,2,4,2,15,9,6,0,1)Math.max.apply apply() 语法&a…...
![](https://www.ngui.cc/images/no-images.jpg)
各种中间件的安装
文章目录 20232306mysql的wondows安装 2023 2306 mysql的wondows安装 常用mysql教程 springboot整合druid连接池SpringBoot配置Druid连接池 mysql的wondows安装 MySQL学习笔记 01、MySQL安装 这个是安装的具体思路 win10 安装 mysql 5.7 msi版的教程图文详解 这个是安装的…...
![](https://www.ngui.cc/images/no-images.jpg)
【Mysql】多表查询、隐式内链接、显式内连接、左外连接、右外连接
多表查询 什么是多表查询 •DQL: 查询多张表,获取到需要的数据 •比如 我们要查询家电分类下 都有哪些商品,那么我们就需要查询分类与商品这两张表 数据准备 创建db3_2 数据库 -- 创建 db3_2 数据库,指定编码 CREATE DATABASE db3_2 CHARACTER SET utf8;创建分类表与商品表 …...
![](https://img-blog.csdnimg.cn/direct/eea23983ebd44fd893f0519a6ed2afc4.png)
Linux驱动开发(三)--新字符设备驱动开发 LED驱动开发升级
1、新字符设备驱动原理 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可,但是这样会 带来两个问题 需要我们事先确定好哪些主设备号没有使用 会将一个主设备号下的所有次设备号都使用掉,比如现在设置 LED 这个主设备号为200&…...
![](https://img-blog.csdnimg.cn/direct/8ab7eac28ef44413be08920856a0dd1a.png)
MCU的最佳存储方案CS创世 SD NAND
大家都知道MCU是一种"麻雀"虽小,却"五脏俱全"的主控。它的应用领域非常广泛,小到手机手表,大到航空航天的设备上都会用到MCU.市面上目前几个主流厂商有意法半导体(其中最经典的一款就是STM32系列)…...
![](https://img-blog.csdnimg.cn/img_convert/55d46eba4dfb765c1d096fd83eed929e.jpeg)
40岁学习java是否需要报班学习?
在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」, 点个关注在评论区回复“666”之后私信回复“666”,全部无偿共享给大家!!!应该不需要。各种公开免费的…...
![](https://img-blog.csdnimg.cn/direct/17449499e847411487d6b919b721b881.png)
Vitis Accelerated Libraries 学习笔记--OpenCV 运行测试
目录 1. 简介 2. 实例测试 2.1 实例介绍 2.2 创建工程 2.2.1 创建工程 2.2.2 获取路径 2.2.3 设置路径 2.2.4 打开工程 2.2.5 添加文件 2.2.6 启动 GUI 2.2.7 配置 csim 参数 3 常见错误 3.1 核心共享库报错 4. 总结 1. 简介 在《Vitis Accelerated Libraries …...
![](https://img-blog.csdnimg.cn/direct/f8ff287aea394bcdb063008d7281f1f5.png)
加固三防平板如何提高轨道交通系统的运营效率?
在当今快节奏的社会中,轨道交通系统作为城市交通的重要组成部分,其运营效率的提升对于缓解交通拥堵、满足人们的出行需求以及促进城市的发展具有至关重要的意义。而加固三防平板作为一种先进的技术设备,正逐渐在轨道交通领域发挥着关键作用&a…...
![](https://www.ngui.cc/images/no-images.jpg)
Django 靓号管理系统:实现登录功能
本文将详细介绍如何在 Django 靓号管理系统中实现登录功能,包括用户认证、验证码生成、以及中间件的使用。我们将逐步展示所有相关代码,并附带详细注释。 1. 项目结构 首先,让我们看一下项目的基本结构: number ├── manage.py ├── monaco.ttf ├── number │ …...
![](https://img-blog.csdnimg.cn/direct/372a37fee8914d29b8ecc710b30c37e8.png)
【Solr 学习笔记】Solr 源码启动教程
Solr 源码启动教程 本教程记录了如何通过 IDEA 启动并调试 Solr 源码,从 Solr9 开始 Solr 项目已由 ant 方式改成了 gradle 构建方式,本教程将以 Solr 9 为例进行演示,IDE 选择使用 IntelliJ IDEA。 Solr github 地址:https://gi…...
![](https://www.ngui.cc/images/no-images.jpg)
Java中的事件驱动编程模型
Java中的事件驱动编程模型 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我将为大家介绍Java中的事件驱动编程模型。事件驱动编程模型是一种以事件为核心驱…...
![](https://img-blog.csdnimg.cn/img_convert/67c857e3801a011a6ba13adce8a6eb30.png)
Python 语法基础一
1.变量 python 中变量很简单,不需要指定数据类型,直接使用等号定义就好。python变量里面存的是内存地址,也就是这个值存在内存里面的哪个地方,如果再把这个变量赋值给另一个变量,新的变量通过之前那个变量知道那个变量…...
![](https://img-blog.csdnimg.cn/direct/175d3793b38849a9819de46ae79fe6bf.png#pic_center)
Flask 数据创建时出错
当我们在使用 Flask 创建数据时遇到错误,可能有多种原因,包括代码错误、数据库配置问题或依赖项错误。具体情况我会总结成一篇文章记录下,主要是归类总结一些常见的解决方法和调试步骤,帮助大家解决问题: 1、问题背景 …...
![](https://www.ngui.cc/images/no-images.jpg)
binary_cross_entropy_with_logits函数的参数设定
binary_cross_entropy_with_logits 该函数参数: logits (Tensor) - 输入预测值。其数据类型为float16或float32。 label (Tensor) - 输入目标值,shape与 logits 相同。数据类型为float16或float32。 weight (Tensor,可选) - 指定每个批次二…...
![](https://img-blog.csdnimg.cn/img_convert/df376f757fdfc494ba7e095d89b39a17.png)
【C++】相机标定源码笔记-相机内参标定类
相机内参标定类 该代码是一个关于摄像头内参处理类的实现。它主要做了以下几件事情: 1. 提供读取和保存相机内参的功能。 2. 允许用户设置一系列参数(如图像尺寸、棋盘格尺寸等)。 3. 支持从图像中检测棋盘格角点,并根据检测到的角…...
![](https://img-blog.csdnimg.cn/direct/7b86ecb12afd4a828a05e4b204644fbd.png)
tcpdump命令详解及使用实例
1、抓所有网卡数据包,保存到指定路径 tcpdump -i any -w /oemdata/123.pcap&一、tcpdump简介 tcpdump可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来去掉无用的信…...
![](https://img-blog.csdnimg.cn/direct/b4fcc393b59a40efb05605b972e18e19.png)
【机器学习】在【Pycharm】中的应用:【线性回归模型】进行【房价预测】
专栏:机器学习笔记 pycharm专业版免费激活教程见资源,私信我给你发 python相关库的安装:pandas,numpy,matplotlib,statsmodels 1. 引言 线性回归(Linear Regression)是一种常见的统计方法和机器学习算法&a…...
![](https://img-blog.csdnimg.cn/direct/512eaab3189146f5960f1f24a18df6f1.png)
每周题解:最大半连通子图
题目链接 最大半连通子图 题目描述 一个有向图 G ( V , E ) G\left(V,E\right) G(V,E) 称为半连通的 (Semi-Connected),如果满足: ∀ u , v ∈ V \forall u,v\in V ∀u,v∈V,满足 u → v u\to v u→v 或 v → u v\to u v→u࿰…...
![](https://www.ngui.cc/images/no-images.jpg)
L3规模化落地加速自动驾驶迎来发展新机遇
近日,工信部网站发布《四部门有序开展智能网联汽车准入和上路通行试点》通知,公布了9家首批智能网联汽车准入和上路通行试点联合体,即汽车生产企业+使用主体成对出现。其中,车企负责产品生产,测试则由相关平台提供。从发放L3自动驾驶测试牌照,到此次《通知》发布,不仅表…...
![](https://www.ngui.cc/images/no-images.jpg)
再破记录!东风风神L7无补能2162.8公里往返穿越羌塘
想象一下驰骋在高速公路上,周围是辽阔的羌塘无人区,一望无际的荒野,野生动物自由穿梭,神秘而充满挑战。这条路就是传说中的216国道,无疑是最无人居住的地区道路。从新疆民丰到西藏改则,800公里无人区没有加油站,这是对车辆极限性能和团队冒险精神的双重考验!最近,在这…...
![](https://www.ngui.cc/images/no-images.jpg)
ECMAScript 详解
ECMAScript 详解 ECMAScript(ES)是JavaScript的标准化脚本语言,由ECMA国际通过ECMA-262标准进行规范。ECMAScript定义了语法、类型、对象模型和内置对象等基本特性,是JavaScript、JScript和ActionScript等语言的核心部分。 以下…...
![](https://img-blog.csdnimg.cn/direct/b47e7bd5ef164f79853e9c48e1faf5c0.png)
vue3(一):Vue3简介、创建vue3工程、Vue3中的响应式
目录 一.Vue3简介 1.性能提升 2.源码升级 3.拥抱ts 4.新特性 (1)Composition API(组合API): (2)新的内置组件: (3)其他改变: 二.创建vue…...
![](https://img-blog.csdnimg.cn/direct/0601e1c8767d43c6aa3279dfbfb1ae02.png)
第十三届蓝桥杯国赛大学B组填空题(c++)
A.2022 动态规划 AC; #include<iostream> #define int long long using namespace std; int dp[2050][15]; //dp[i][j]:把数字i分解为j个不同的数的方法数 signed main(){dp[0][0]1;for(int i1;i<2022;i){for(int j1;j<10;j){//一种是已经分成j个数,这时只需每一个…...
![](https://www.ngui.cc/images/no-images.jpg)
C语言知识大纲
一、基础 (一)变量定义和使用 (二)数据类型的字节数 (三)变量转换 (四)程序主要结构 (五)if和else判断 (六)switch判断 (七)while循环 (八)do while循环 (九)for循环 (十)基本输入输出 (十一)数组定义和使用 (十二)函数定义和使用 (十三)指针 (十四)多级指针 (十…...