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

仿牛客网项目---点赞模块的实现

本篇文章介绍一下项目中的点赞模块。

点赞模块是一个通过使用Redis实现的功能模块,它提供了点赞操作的处理逻辑和数据存取功能。通过服务类和控制器类的配合,点赞模块实现了用户对实体的点赞、点赞数量的查询、点赞状态的查询等功能。该模块使用了Redis作为数据存储,通过Redis的事务支持和数据结构操作,实现了点赞操作的原子性和高效性。同时,通过依赖注入和控制反转的思想,实现了代码的解耦和灵活性,使得点赞模块具有良好的可维护性和可扩展性。

首先我们写一个RedisKeyUtil的工具类,这个工具类提供了一些用于在Redis中生成键的方法。

public class RedisKeyUtil {// 某个实体的赞// like:entity:entityType:entityId -> set(userId)public static String getEntityLikeKey(int entityType, int entityId) {return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;}// 某个用户的赞// like:user:userId -> intpublic static String getUserLikeKey(int userId) {return PREFIX_USER_LIKE + SPLIT + userId;}// 某个用户关注的实体// followee:userId:entityType -> zset(entityId,now)public static String getFolloweeKey(int userId, int entityType) {return PREFIX_FOLLOWEE + SPLIT + userId + SPLIT + entityType;}// 某个实体拥有的粉丝// follower:entityType:entityId -> zset(userId,now)public static String getFollowerKey(int entityType, int entityId) {return PREFIX_FOLLOWER + SPLIT + entityType + SPLIT + entityId;}// 登录验证码public static String getKaptchaKey(String owner) {return PREFIX_KAPTCHA + SPLIT + owner;}// 登录的凭证public static String getTicketKey(String ticket) {return PREFIX_TICKET + SPLIT + ticket;}// 用户public static String getUserKey(int userId) {return PREFIX_USER + SPLIT + userId;}// 单日UVpublic static String getUVKey(String date) {return PREFIX_UV + SPLIT + date;}// 区间UVpublic static String getUVKey(String startDate, String endDate) {return PREFIX_UV + SPLIT + startDate + SPLIT + endDate;}// 单日活跃用户public static String getDAUKey(String date) {return PREFIX_DAU + SPLIT + date;}// 区间活跃用户public static String getDAUKey(String startDate, String endDate) {return PREFIX_DAU + SPLIT + startDate + SPLIT + endDate;}// 帖子分数public static String getPostScoreKey() {return PREFIX_POST + SPLIT + "score";}}

举例来说,通过使用getEntityLikeKey方法,可以生成一个用于存储特定实体点赞记录的键,通过使用getUserLikeKey方法,可以生成一个用于存储特定用户点赞记录的键。其他方法则可以生成用于存储用户数据、关注关系、验证码、登录凭证等的键。

看到这里,你应该会觉得很奇怪,为什么没有DAO层呢?

因为点赞数据的存储和查询需求可以完全由Redis满足,并且Redis作为一个高性能的内存数据库能够提供快速的读写操作,简化了数据访问的复杂性和开销,同时满足了性能要求。此外,点赞数据可能具有相对简单的数据结构,可以直接使用Redis的数据结构进行存储和查询,而不需要传统的数据库访问层。

所以说DAO层在这个项目就没有用到了,我这个项目的点赞模块用的是Redis,关于一些点赞的信息我是用redis来存的。

然后再来写LikeService文件,即service层。

@Service
public class LikeService {@Autowiredprivate RedisTemplate redisTemplate;// 点赞public void like(int userId, int entityType, int entityId, int entityUserId) {redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations operations) throws DataAccessException {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId);boolean isMember = operations.opsForSet().isMember(entityLikeKey, userId);operations.multi();if (isMember) {operations.opsForSet().remove(entityLikeKey, userId);operations.opsForValue().decrement(userLikeKey);} else {operations.opsForSet().add(entityLikeKey, userId);operations.opsForValue().increment(userLikeKey);}return operations.exec();}});}// 查询某实体点赞的数量public long findEntityLikeCount(int entityType, int entityId) {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);return redisTemplate.opsForSet().size(entityLikeKey);}// 查询某人对某实体的点赞状态public int findEntityLikeStatus(int userId, int entityType, int entityId) {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;}// 查询某个用户获得的赞public int findUserLikeCount(int userId) {String userLikeKey = RedisKeyUtil.getUserLikeKey(userId);Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey);return count == null ? 0 : count.intValue();}}
  1. like(int userId, int entityType, int entityId, int entityUserId):点赞方法,用于给特定实体点赞。它首先生成实体点赞的键和用户点赞的键,然后通过Redis的事务支持(multi()exec()方法)来保证点赞操作的原子性。根据用户是否已经点赞,执行相应的操作(添加或移除点赞),并更新用户点赞数。

  2. findEntityLikeCount(int entityType, int entityId):查询某实体的点赞数量。它使用RedisKeyUtil生成实体点赞的键,并通过Redis的opsForSet().size()方法获取集合的大小,即点赞数量。

  3. findEntityLikeStatus(int userId, int entityType, int entityId):查询某人对某实体的点赞状态。它使用RedisKeyUtil生成实体点赞的键,并通过Redis的opsForSet().isMember()方法判断用户是否已经点赞。

  4. findUserLikeCount(int userId):查询某个用户获得的赞数量。它使用RedisKeyUtil生成用户点赞的键,并通过Redis的opsForValue().get()方法获取用户点赞数。

最后写controller层,即LikeController。

@Controller
public class LikeController implements CommunityConstant {//省略了注入LikeService、HostHolder、EventProducer和RedisTemplate来处理点赞逻辑的代码@RequestMapping(path = "/like", method = RequestMethod.POST)@ResponseBodypublic String like(int entityType, int entityId, int entityUserId, int postId) {User user = hostHolder.getUser();// 点赞likeService.like(user.getId(), entityType, entityId, entityUserId);// 数量long likeCount = likeService.findEntityLikeCount(entityType, entityId);// 状态int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);// 返回的结果Map<String, Object> map = new HashMap<>();map.put("likeCount", likeCount);map.put("likeStatus", likeStatus);// 触发点赞事件if (likeStatus == 1) {Event event = new Event().setTopic(TOPIC_LIKE).setUserId(hostHolder.getUser().getId()).setEntityType(entityType).setEntityId(entityId).setEntityUserId(entityUserId).setData("postId", postId);eventProducer.fireEvent(event);}if(entityType == ENTITY_TYPE_POST) {// 计算帖子分数String redisKey = RedisKeyUtil.getPostScoreKey();redisTemplate.opsForSet().add(redisKey, postId);}return CommunityUtil.getJSONString(0, null, map);}}

上面这段代码是一个名为LikeController的控制器类,用于处理点赞相关的请求。它通过注入LikeServiceHostHolderEventProducerRedisTemplate来处理点赞逻辑。

控制器中的主要方法是like()方法,用于处理点赞请求。该方法接受实体类型、实体ID、实体创建者ID和帖子ID作为参数。在方法中,首先获取当前用户信息,然后调用likeService的点赞方法,对实体进行点赞操作。

接下来,通过调用likeService的方法获取点赞数量和点赞状态,并将结果存储在一个Map对象中。然后,根据点赞状态触发相应的点赞事件,创建一个Event对象,并通过eventProducer发送事件。

如果实体类型是帖子(ENTITY_TYPE_POST),则计算帖子的分数并存储到Redis中。

最后,通过CommunityUtil.getJSONString()方法将结果封装成JSON字符串并返回给前端。

控制器类通过调用likeService处理点赞逻辑,而不是使用DAO层进行数据访问。这是因为点赞操作的数据存储和查询可以完全由Redis满足,并且通过调用likeService提供的方法,可以直接在控制器中处理点赞逻辑,避免了引入额外的DAO层。

相关文章:

仿牛客网项目---点赞模块的实现

本篇文章介绍一下项目中的点赞模块。 点赞模块是一个通过使用Redis实现的功能模块&#xff0c;它提供了点赞操作的处理逻辑和数据存取功能。通过服务类和控制器类的配合&#xff0c;点赞模块实现了用户对实体的点赞、点赞数量的查询、点赞状态的查询等功能。该模块使用了Redis…...

【AI视野·今日CV 计算机视觉论文速览 第300期】Fri, 1 Mar 2024

AI视野今日CS.CV 计算机视觉论文速览 Fri, 1 Mar 2024 Totally 114 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers DistriFusion: Distributed Parallel Inference for High-Resolution Diffusion Models Authors Muyang Li, Tianle Cai, J…...

【单片机学习的准备】

文章目录 前言一、找一个视频是二、画图软件三、装keil5 仿真protues总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 项目需要&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、找一个视频是 https://www.b…...

力扣hot100:438.找到字符串中所有字母异位词

26个字符&#xff0c;我复制怎么了&#xff1f;26个字符我比较个数怎么了&#xff1f; 顶多时间复杂度*26 本题用固定窗口大小的滑动窗口每次比较包含26个元素的数组次数&#xff0c;最容易写。 动态窗口大小哈希表存数值&#xff08;双指针差值&#xff09;难想难写。 一、动态…...

Kali Linux 2024.1

Kali Linux 2024.1刚刚发布&#xff0c;标志着这个备受欢迎的安全重点Linux发行版在今年的首次重大更新。以其先进的渗透测试和安全审计功能而闻名&#xff0c;它是安全专业人员和爱好者的首选工具。 Kali 2024.1 亮点 本次发布由 Linux 内核 6.6 提供支持&#xff0c;突出了…...

springboot启动加载

目录 使用PostConstruct注解 实现InitializingBean接口 实现CommandLineRunner接口 实现ApplicationRunner接口 使用EventListener注解监听ApplicationReadyEvent事件 应用启动完成之前或者之后&#xff0c;我们需要拿数据库中的一些数据加载到本地缓存中。这些数据一般都…...

基于Java的智能停车场管理系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容A. 车主端功能B. 停车工作人员功能C. 系统管理员功能1. 停车位模块2. 车辆模块3. 停车记录模块4. IC卡模块5. IC卡挂失模块 三、界面展示3.1 登录注册3.2 车辆模块3.3 停车位模块3.4 停车数据模块3.5 IC卡档案模块3.6 IC卡挂…...

ESD Clamp cell是什么?

ESD CLAMP cell&#xff08;静电放电钳位单元&#xff09;是一种专门设计来保护集成电路&#xff08;IC&#xff09;免受静电放电&#xff08;ESD&#xff09;损害的电路元件。静电放电是在电子设备的组件之间或内部发生的突然电流放电&#xff0c;它可能会损坏电路或降低其性能…...

费率电能表

费率电能表是一种用于测量家庭、商业和工业用电的设备&#xff0c;有效的实现分段计费、分时计费&#xff0c;优化用电效率。费率电能表的产生是为了缓解高峰期的用电负荷&#xff0c;平衡各时间段的用电负荷&#xff1b;根据当地用电负荷曲线情况制定时段费率 在费率电能表中…...

2张图2秒钟3D重建!这款AI工具火爆GitHub,网友:忘掉Sora

只需2张图片&#xff0c;无需测量任何额外数据—— 当当&#xff0c;一个完整的3D小熊就有了&#xff1a; 这个名为DUSt3R的新工具&#xff0c;火得一塌糊涂&#xff0c;才上线没多久就登上GitHub热榜第二。 ▲image 有网友实测&#xff0c;拍两张照片&#xff0c;真的就重建…...

C++高级面试题:请解释 C++ 中的指针和引用之间的区别。

请解释 C 中的指针和引用之间的区别。 在 C 中&#xff0c;指针&#xff08;Pointers&#xff09;和引用&#xff08;References&#xff09;都是用于处理内存地址的工具&#xff0c;但它们有一些重要的区别&#xff1a; 语法和用法&#xff1a; 指针使用 * 运算符来访问其所…...

Git 配置处理客户端无法正常访问到 github 原网站时,npm 下载依赖包失败的问题

Git 配置处理客户端无法正常访问到 github 原网站时&#xff0c;npm 下载依赖包失败的问题 使用 github 的镜像网站地址或类似的替代产品地址&#xff0c;代替到 npm 拉取依赖包的 git 地址本地Git配置 例如&#xff1a;执行一下命令&#xff0c;则是以https://kgithub.com 替…...

前端爬虫+可视化Demo

爬虫简介 可以把互联网比做成一张 “大网”&#xff0c;爬虫就是在这张大网上不断爬取信息的程序。 爬虫是请求网站并提取数据的自动化程序。 省流&#xff1a;Demo实现前置知识&#xff1a; JS 基础Node 基础 &#xff08;1&#xff09;爬虫基本工作流程&#xff1a; 向…...

keepAlive

router c.js const view (name) > () > import(/views/文件夹名/ name) export const c [ {path: /xxx,name: aaa,meta: {title: 哈哈哈,admin: true,keepAlive:true //加这个},component: view(xxx) }, ]adminMain.vue <keep-alive><router-view v-if"…...

蓝桥杯练习题——dp

五部曲&#xff08;代码随想录&#xff09; 1.确定 dp 数组以及下标含义 2.确定递推公式 3.确定 dp 数组初始化 4.确定遍历顺序 5.debug 入门题 1.斐波那契数 思路 1.f[i]&#xff1a;第 i 个数的值 2.f[i] f[i - 1] f[i - 2] 3.f[0] 0, f[1] 1 4.顺序遍历 5.记得特判 …...

kotlin基础语法

1.变量 var a:Int 2 //声明类型的可变变量 var b 3 //代码推测可变变量类型 val c 6 //代码推测不可变常量类型 var d:String?null //可为null的String类型的可变变量 latei…...

淘宝天猫商家爬虫工具 电商采集软件使用教程

介绍&#xff1a; 淘宝和天猫是中国最大的电商平台之一&#xff0c;商家在这里销售各种商品。在市场竞争激烈的环境下&#xff0c;了解竞争对手的商品信息和价格变化对于电商运营来说非常重要。本文将介绍如何使用Python编写一个简单的淘宝天猫商家爬虫工具&#xff0c;以获取商…...

建库建表时,最容易忽略的10个细节

大家使用 DolphinDB 创建数据库和表时&#xff0c;有时对于分区列、分区类型和排序列的选择并不十分清晰。如果不加注意&#xff0c;可能导致查询速度变慢、数据丢失或插入错误等问题。合理地设置分区列、排序列和分区类型&#xff0c;有助于加快查询速度&#xff0c;减少内存使…...

【基础知识】什么是 PPO(Proximal Policy Optimization,近端策略优化)

什么是 PPO&#xff08;Proximal Policy Optimization&#xff0c;近端策略优化&#xff09; PPO&#xff08;Proximal Policy Optimization&#xff0c;近端策略优化&#xff09;是一种强化学习算法&#xff0c;由John Schulman等人在2017年提出。PPO属于策略梯度方法&#x…...

程序员如何选择职业赛道?

程序员如何选择职业赛道&#xff1f; 程序员的职业赛道就像是一座迷宫&#xff0c;充满了各种各样的岔路口。每个岔路口都代表着不同的方向&#xff0c;不同的技术领域&#xff0c;不同的职业发展道路。 前端开发 前端开发就像迷宫中的美丽花园&#xff0c;它是用户与网站或应…...

5步打造专业虚拟摄像头:OBS插件从部署到精通

5步打造专业虚拟摄像头&#xff1a;OBS插件从部署到精通 【免费下载链接】obs-virtual-cam obs-studio plugin to simulate a directshow webcam 项目地址: https://gitcode.com/gh_mirrors/ob/obs-virtual-cam OBS虚拟摄像头插件是一款能够将OBS Studio的专业直播画面转…...

城通网盘解析终极指南:如何免费获取高速直连下载地址

城通网盘解析终极指南&#xff1a;如何免费获取高速直连下载地址 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 在数字化信息时代&#xff0c;城通网盘作为国内广泛使用的文件分享平台&#xff0c;却因…...

第11天:函数组合、记忆化与定时器

今天复习了函数组合、记忆化、setTimeout 和 setInterval&#xff0c;以下是知识点梳理与问答整理。一、函数组合&#xff08;Compose / Pipe&#xff09;1. 什么是函数组合&#xff1f;我的回答&#xff1a;把上一个函数的返回值作为下一个函数的参数&#xff0c;形成流水线式…...

从“链表长度”到“游戏对象池”:用C++ std::list的size()函数设计一个简单的内存管理Demo

从链表长度到游戏对象池&#xff1a;用C std::list设计高效内存管理方案 在游戏开发中&#xff0c;频繁创建和销毁对象会导致内存碎片化与性能下降。想象一个2D射击游戏场景&#xff1a;玩家发射的子弹、随机生成的敌人都需要动态管理。传统new/delete直接操作内存的方式在这种…...

实战演练:基于快马平台与方锐理念构建短视频智能配乐应用

最近在做一个短视频创作的小工具&#xff0c;发现给视频配乐真是个技术活。正好看到网易方锐的AI音乐技术挺火的&#xff0c;就想着能不能用它的理念做个智能配乐助手。在InsCode(快马)平台上试了试&#xff0c;没想到还真搞出了一个能跑起来的demo&#xff0c;分享下我的实现思…...

NeuroKit2:神经生理信号处理的全流程解决方案

NeuroKit2&#xff1a;神经生理信号处理的全流程解决方案 【免费下载链接】NeuroKit NeuroKit2: The Python Toolbox for Neurophysiological Signal Processing 项目地址: https://gitcode.com/gh_mirrors/ne/NeuroKit 在神经科学与生理信号研究领域&#xff0c;高效处…...

AI辅助开发:让快马AI为你深度解读并延展Python antigravity的趣味文化

最近在玩Python的时候&#xff0c;发现了一个特别有意思的彩蛋——import antigravity。这个看似简单的语句背后&#xff0c;其实藏着一段有趣的开发者文化。今天我就来分享一下&#xff0c;如何用InsCode(快马)平台的AI功能&#xff0c;把这个彩蛋玩出更多花样。 初识antigrav…...

awesome-ai-resources部署指南:如何高效组织个人AI学习资料库

awesome-ai-resources部署指南&#xff1a;如何高效组织个人AI学习资料库 【免费下载链接】awesome-ai-resources Learn AI and LLMs from scratch using free resources 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-ai-resources 想要系统学习人工智能和大型…...

5个实用技巧:让waifu2x-caffe成为你的图像超分辨率利器

5个实用技巧&#xff1a;让waifu2x-caffe成为你的图像超分辨率利器 【免费下载链接】waifu2x-caffe waifu2xのCaffe版 项目地址: https://gitcode.com/gh_mirrors/wa/waifu2x-caffe waifu2x-caffe是一个基于Caffe深度学习框架的图像超分辨率与降噪工具&#xff0c;专为W…...

网站页面标题和描述如何设置更有利于SEO_网站标题、标题标签、副标题如何设置

网站页面标题和描述如何设置更有利于SEO_网站标题、标题标签、副标题如何设置 在当今数字化时代&#xff0c;网站的SEO&#xff08;搜索引擎优化&#xff09;至关重要。如何设置网站的页面标题和描述&#xff0c;不仅能提升网站的可见度&#xff0c;还能吸引更多的点击和流量。…...