重学SpringBoot3-集成Redis(十二)之点赞功能实现
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍
重学SpringBoot3-集成Redis(十二)之点赞功能实现
- 1. 点赞功能的场景分析
- 2. 项目环境配置
- 2.1. 依赖引入
- 2.2. Redis 配置
- 3. 点赞功能的实现
- 3.1. 点赞服务层
- 3.2. 点赞控制器
- 3.3. 演示
- 点赞操作
- 获取点赞数
- 检查用户是否点赞
- 取消点赞
- 4. 点赞功能的详细解释
- 4.1. 用户点赞和取消点赞
- 4.2. 统计点赞数
- 4.3. 判断用户是否点赞
- 5. Redis Set 数据结构的优势
- 6. 总结
在现代的应用中,点赞功能是一个非常常见的需求,尤其在社交媒体、博客等平台上。Redis 作为一个高性能的键值存储系统,由于其读写速度快、支持丰富的数据结构,因此非常适合用来实现实时的点赞功能。本文将介绍如何结合 Spring Boot 3 和 Redis 来实现一个高效的点赞功能。
1. 点赞功能的场景分析
点赞功能通常涉及以下场景:
- 用户点赞或取消点赞:某个用户对某篇文章或某条评论进行点赞或取消操作。
- 统计点赞数量:实时显示某个对象(如文章、视频、评论)的总点赞数。
- 用户点赞状态查询:判断某个用户是否对某个对象点赞过。
Redis 通过Set 数据结构可以很好地解决这些问题。Redis 的 Set 不允许重复元素,且支持快速添加、删除、判断成员是否存在等操作。

2. 项目环境配置
2.1. 依赖引入
首先,在 pom.xml 中引入 Spring Boot 3 和 Redis 的相关依赖,具体参考重学SpringBoot3-集成Redis(一)之基本使用:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2. Redis 配置
在 application.yml 中配置 Redis 连接:
spring:data:redis:host: localhostport: 6379 # Redis 端口password: redis123456 # 如果有密码可以在这里配置lettuce:pool:max-active: 100 # 最大并发连接数max-idle: 50 # 最大空闲连接数min-idle: 10 # 最小空闲连接数
3. 点赞功能的实现
在实现点赞功能时,通常会用 Redis 的 Set 数据结构来存储每个对象(如文章、视频)的点赞用户列表。每次点赞操作就是往这个 Set 中添加用户 ID,取消点赞则是从 Set 中移除用户 ID。
3.1. 点赞服务层
package com.coderjia.boot310redis.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;/*** @author CoderJia* @create 2024/10/10 下午 09:45* @Description**/
@Service
public class LikeService {@Autowiredprivate StringRedisTemplate redisTemplate;// Redis Key 前缀private static final String LIKE_KEY_PREFIX = "like:"; // 用户点赞public void likePost(String postId, String userId) {String redisKey = LIKE_KEY_PREFIX + postId;redisTemplate.opsForSet().add(redisKey, userId);}// 用户取消点赞public void unlikePost(String postId, String userId) {String redisKey = LIKE_KEY_PREFIX + postId;redisTemplate.opsForSet().remove(redisKey, userId);}// 查询某个帖子点赞数public Long getLikeCount(String postId) {String redisKey = LIKE_KEY_PREFIX + postId;return redisTemplate.opsForSet().size(redisKey);}// 判断用户是否点赞public boolean hasLiked(String postId, String userId) {String redisKey = LIKE_KEY_PREFIX + postId;return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(redisKey, userId));}
}
3.2. 点赞控制器
package com.coderjia.boot310redis.demos.web;import com.coderjia.boot310redis.service.LikeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @author CoderJia* @create 2024/10/10 下午 09:46* @Description**/
@RestController
@RequestMapping("/like")
public class LikeController {@Autowiredprivate LikeService likeService;// 点赞操作@PostMapping("/like")public String like(@RequestParam String postId, @RequestParam String userId) {likeService.likePost(postId, userId);return "Liked post: " + postId + " by user: " + userId;}// 取消点赞@PostMapping("/unlike")public String unlike(@RequestParam String postId, @RequestParam String userId) {likeService.unlikePost(postId, userId);return "Unliked post: " + postId + " by user: " + userId;}// 获取点赞数@GetMapping("/count")public Long getLikeCount(@RequestParam String postId) {return likeService.getLikeCount(postId);}// 检查用户是否点赞@GetMapping("/status")public boolean hasLiked(@RequestParam String postId, @RequestParam String userId) {return likeService.hasLiked(postId, userId);}
}
3.3. 演示
点赞操作
curl -X POST http://localhost:8080/like/like?postId=p101&userId=1

获取点赞数
curl http://localhost:8080/like/count?postId=p101

检查用户是否点赞
curl http://localhost:8080/like/status?postId=p101&userId=1

取消点赞
curl -X POST http://localhost:8080/like/unlike?postId=p101&userId=1

4. 点赞功能的详细解释
4.1. 用户点赞和取消点赞
每当用户点赞时,我们将用户 ID 存入 Redis 的 Set 中。由于 Redis 的 Set 不允许重复元素,用户多次点赞同一篇文章也只会被记录一次。
redisTemplate.opsForSet().add(redisKey, userId);
取消点赞则是将用户 ID 从 Set 中移除:
redisTemplate.opsForSet().remove(redisKey, userId);
4.2. 统计点赞数
统计点赞数非常简单,直接调用 Redis 的 size() 方法即可:
redisTemplate.opsForSet().size(redisKey);
这比使用传统数据库查询要快得多,尤其在大量用户点赞的情况下,Redis 能保持高性能。
4.3. 判断用户是否点赞
可以通过 Redis 的 isMember() 方法来判断某个用户是否已经对某篇文章点赞:
redisTemplate.opsForSet().isMember(redisKey, userId);
这一点对前端显示用户是否已点赞的状态非常重要,用户体验更好。
5. Redis Set 数据结构的优势
Redis 的 Set 数据结构非常适合用来存储点赞功能的用户列表,原因有以下几点:
- 唯一性:Redis Set 不允许重复元素,确保用户对同一篇文章只能点赞一次。
- 高性能:Redis 是内存级存储,读写速度极快,适合大规模的点赞操作。
- 丰富的操作:Set 提供了丰富的操作,如添加成员、删除成员、计算数量、检查成员是否存在等,这些操作都是 O(1) 复杂度,性能非常高。
6. 总结
通过结合 Spring Boot 3 与 Redis,我们可以轻松实现高效的点赞功能,并利用 Redis 的 Set 数据结构实现去重、快速统计等操作。相比于传统的数据库操作,使用 Redis 实现的点赞功能性能更高、扩展性更好,尤其适合用户量大、点赞操作频繁的应用场景。
持久化到数据库
仅使用 Redis:适用于对数据一致性要求不高的场景,比如短期有效的点赞数据,或者系统对少量点赞数据丢失不敏感。
Redis + MySQL方案:适用于对数据一致性要求高的场景,比如电商、社交平台中,点赞数据不能丢失,且需要长期保存。通常采用异步持久化,具体流程可以是:
- 用户点赞时,首先将数据写入 Redis。
- 通过定时任务(如每隔几分钟)或消息队列,将 Redis 中的点赞数据同步到数据库。
- 在定时任务或队列消费过程中,可以批量将点赞数据写入数据库,降低数据库的写入压力。
相关文章:
重学SpringBoot3-集成Redis(十二)之点赞功能实现
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(十二)之点赞功能实现 1. 点赞功能的场景分析2. 项目环境配置2.1. 依赖引入2.2. Redis 配置 3. 点赞功能的实现3.1. 点…...
Django-rest-framework(DRF)怎么实现Excel文件导出
目录 一、安装openpyxl库 二、openpyxl库介绍 1、工作簿 a、创建工作簿 b、加载工作簿 c、保存工作簿 2、工作表 a、获取工作表 b、创建和删除工作表 c、工作表属性设置 3、单元格 a、获取单元格 b、合并单元格 C、设置单元格样式 三、django集成openpyxl库 一、…...
零基础MySQL数据库入门一天学完
目录 课程介绍数据库的存在意义数据库历史及MySQL简介MySQL安装指南MySQL客户端工具介绍库操作详解表操作指南单表查询技巧多表查询实践MySQL函数速览新增、修改、删除操作索引优化策略视图应用实例事务处理机制数据备份与恢复日常维护与安全建议 1. 课程介绍 本指南旨在为初…...
【CSS Tricks】鼠标滚轮驱动css动画播放,使用js还是css?
目录 引言一、js实现1. 实现思路2. 实现案例3. 看下效果 二、css实现1. 代码修改2. 属性介绍2.1 看下浏览器支持性2.2 常用属性值2.2.1 scroll()2.2.2 view() 三、总结 引言 本篇为css的一个小技巧 页面中的动画效果随着滚轮的转动…...
《Electron 基础知识》设置 Vue 中引用的文件路径别名
vite.renderer.config.mjs 文件中配置 代码第1行,引入 resolve ;代码第 6 - 10 行,设置路径别名,注意没有后缀 /; import { resolve } from pathexport default defineConfig((env) > {return {resolve: {alias: …...
day 20 二叉树 part05
654.最大二叉树 注意类似用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。 题目链接/文章讲解:代码随想录 lass Solution { private:// 在左闭右开…...
003 Springboot操作RabbitMQ
Springboot整合RabbitMQ 文章目录 Springboot整合RabbitMQ1.pom依赖2.yml配置3.配置队列、交换机方式一:直接通过配置类配置bean方式二:消息监听通过注解配置 4.编写消息监听发送测试5.其他类型交换机配置1.FanoutExchange2.TopicExchange3.HeadersExcha…...
小猿口算脚本
实现原理:安卓adb截图传到电脑,然后用python裁剪获得两张数字图片,使用ddddocr识别数字,比较大小,再用adb命令模拟安卓手势实现>< import os import ddddocr from time import sleep from PIL import Imagedef …...
从 Reno TCP 到 Scalable TCP,HighSpeed TCP
前文 Scalable TCP 如何优化长肥管道 介绍了 Scalable TCP,但联系另一个类似的算法 HighSpeed TCP(简称 HSTCP),就会看到一个类似从 Reno TCP 经 BIC 到 CUBIC 的路线,但采用了不同的策略。 Reno TCP 经 BIC 到 CUBIC 路线的核心在于 “在长…...
使用Java调用OpenAI API并解析响应:详细教程
使用Java调用OpenAI API并解析响应:详细教程 在现代应用程序中,API调用是一个非常常见的任务。本文将通过一个完整的示例,讲解如何使用Java调用OpenAI的ChatGPT API,并通过ObjectMapper处理JSON响应。本文的示例不仅适用于OpenAI…...
深入学习并发编程中的 synchronized
文章目录 并发编程中的三个问题可见性原子性有序性 了解Java内存模型JMMsynchronized 保证三大特性synchronized 保证原子性synchronized 保证可见性synchronized 保证有序性 synchronized 的特性可重入特性不可中断特性 通过反汇编学习synchronized原理当修饰代码块时当修饰方…...
AMD R9-9950X相比较I9-14900K有哪些提升
AMD R9-9950X相比较I9-14900K有哪些提升?在处理器领域,AMD与英特尔的竞争从未停歇,每一次新品发布都引发业界的高度关注。近日,AMD推出了其新一代桌面级旗舰处理器——Ryzen 9 9950X(简称R9-9950X)…...
计算机毕业设计 基于Python的个性化旅游线路推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
总结:Flink之DataStream各API介绍
一、介绍 本文主要是详细介绍 DataStream<T> 类中的各个方法,并给出它们的使用场景。 二、基本方法 getId(): 作用:返回转换操作的唯一标识符。场景:当需要调试或日志记录时,有时候需要知道操作的 ID。getParallelism(): 作用:获取流的并行度。场景:在优化作业时…...
设计一个日志管理系统,支持多级别日志记录
设计一个日志管理系统,支持多级别日志记录 作为一名Python程序软件专家,我经常被问到关于日志管理系统的设计和实现。今天,我将分享一篇关于设计一个日志管理系统,支持多级别日志记录的博文,希望能够帮助大家更好地理解和使用Python语言。 日志管理系统的需求 在软件开…...
Javascript动态规划算法
JavaScript中的动态规划(Dynamic Programming,简称DP)是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法。它主要致力于将“合适”的问题拆分成更小的子目标,并通过建立状态转移方程、缓存并复用以往结果以及按…...
Java 循环里怎么删除元素才安全
首先 在 Java 中,当你在循环中遍历集合时,直接删除元素可能会引发 ConcurrentModificationException。为了安全地删除元素,推荐使用 Iterator 来进行删除操作。 以下是使用 Iterator 删除元素的常见模式: import java.util.Arr…...
LabVIEW晶体振荡器自动化测试系统
基于LabVIEW平台的晶体振荡器自动化测试系统解决了传统手工测试晶体振荡器繁琐且易出错的问题。该系统通过高度自动化的测试流程,提高了测试效率和精度,实现了数据的自动采集与处理,适用于电子、通信等领域的晶振测试需求。 项目背景与意义 …...
3.6.xx版本SpringBoot创建基于Swagger接口文档
介绍 基于Swagger构建的JavaAPI文档工具,实现后端功能的测试,并撰写API接口文档。 方法 pom.xml中引入依赖,要注意的是,本依赖使用的SpringBoot版本为3.6.xx <!--Knife4j--><dependency><groupId>com.github.xiaoymin<…...
Oracle 12201非PDBS模式单机部署(静默安装)
一、创建Oracle数据库的用户 groupadd oinstall groupadd dba groupadd asmadmin groupadd asmdba useradd -g oinstall -G dba,asmdba oracle -d /home/oracle passwd oracle二、配置Linux 服务器参数 cat /home/oracle/.bash_profile export ORACLE_HOSTNAMEH_orcle01 expo…...
开发者专属提示词库:提升AI协作效率的实战指南
1. 项目概述:一个为开发者量身定制的提示词宝库如果你是一名开发者,无论是前端、后端、运维还是算法工程师,我相信你都或多或少地接触过像 ChatGPT 这类大型语言模型。它们能写代码、解 Bug、解释概念,甚至帮你设计架构。但很多时…...
Wand-Enhancer:免费解锁WeMod专业版功能的终极本地增强工具
Wand-Enhancer:免费解锁WeMod专业版功能的终极本地增强工具 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 还在为WeMod专业版的高昂订阅费用…...
Token工厂:从“卖流量”到“卖Token”:中国移动砸百亿建Token生态,三大运营商的AI战争升级,阿里,百度,华为,字节跟进
5月9日,2026移动云大会上,中国移动市场经营部总经理邱宝华扔出一个新概念——"Token运营体系"。未来3-5年,中国移动将投入百亿级Token生态资源,建设千亿级算力基础设施,携手共创万亿级AI产业价值。"百亿…...
阴阳师自动化脚本OAS终极指南:轻松解放双手的完整教程
阴阳师自动化脚本OAS终极指南:轻松解放双手的完整教程 【免费下载链接】OnmyojiAutoScript Onmyoji Auto Script | 阴阳师脚本 项目地址: https://gitcode.com/gh_mirrors/on/OnmyojiAutoScript 阴阳师自动化脚本OAS是一款专门为《阴阳师》游戏设计的智能自动…...
企业级后端四层架构实战:从理论到代码的清晰落地
1. 项目概述:一个四层架构的实战蓝图最近在GitHub上看到一个挺有意思的项目,叫BTawaifi/four-layer-system。光看名字,你可能会觉得这又是一个老生常谈的“四层架构”理论教程,无非是Controller、Service、Repository那套东西。但…...
3步强力清理:Pearcleaner让你轻松解决Mac应用残留文件问题
3步强力清理:Pearcleaner让你轻松解决Mac应用残留文件问题 【免费下载链接】Pearcleaner A free, source-available and fair-code licensed mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner 你是否曾删除Mac应用后,发…...
AI全栈开发实战:基于Cursor的智能代码生成与架构设计
1. 项目概述:当AI代码助手遇上全栈开发最近在GitHub上看到一个挺有意思的项目,叫“Cursor-FullStack-AI-App”。光看名字,你大概能猜到它和Cursor这个AI代码编辑器有关,并且涉及全栈应用开发。但它的价值远不止于此。作为一个在前…...
基于Go的轻量级自托管IM系统OpenWhisp部署与架构解析
1. 项目概述:一个开源的即时通讯解决方案最近在折腾一个内部协作工具,需要集成一个轻量级的即时通讯模块。市面上成熟的方案不少,但要么是SaaS服务,数据不在自己手里,心里不踏实;要么是像Rocket.Chat、Matt…...
017、Docker在TinyML开发中的应用
017 Docker在TinyML开发中的应用 从一次“环境地狱”说起 上个月帮团队调一个STM32上的TinyML推理延迟问题,模型是MobileNetV2量化版,在开发板上跑得好好的,换到同事的Ubuntu 20.04机器上编译,死活链接不上CMSIS-NN库。折腾半天发现他系统里默认的arm-none-eabi-gcc版本是…...
【c++面向对象编程】第24篇:类型转换运算符:自定义隐式转换与explicit
目录 一、一个自然的想法 二、类型转换运算符的基本语法 写法 使用 三、隐式转换的风险 问题1:意外的不希望发生的转换 问题2:多个转换路径的歧义 问题3:与构造函数隐式转换叠加导致混乱 四、explicit:禁止隐式转换 语法…...
