redis实战-实现笔记点赞和点赞排行榜

发布探店笔记

探店笔记类似点评网站的评价,往往是图文结合。对应的表有两个:

tb_blog:探店笔记表,包含笔记中的标题、文字、图片等

tb_blog_comments:其他用户对探店笔记的评价

 

 保存笔记service层

@Overridepublic Result saveBlog(Blog blog) {// 获取登录用户UserDTO user = UserHolder.getUser();blog.setUserId(user.getId());// 保存探店博文save(blog);// 返回idreturn Result.ok(blog.getId());}

注意修改图片保存路径为自己的目录

 查看探店笔记

 对应的查询接口

@Override
public Result queryBlogById(Long id) {// 1.查询blogBlog blog = getById(id);if (blog == null) {return Result.fail("笔记不存在!");}// 2.查询blog有关的用户queryBlogUser(blog);return Result.ok(blog);
}

实现点赞

初步实现

初始代码,即用户一点击点赞按钮,请求这一接口直接访问数据库将这篇笔记的点赞数量+1,没有任何限制,这并不符合我们常规的点赞逻辑,我们应该实现的是一人一赞,当用户点赞之后,点赞按钮会高亮,再次点击按钮之后会取消点赞

@GetMapping("/likes/{id}")
public Result queryBlogLikes(@PathVariable("id") Long id) {//修改点赞数量blogService.update().setSql("liked = liked +1 ").eq("id",id).update();return Result.ok();
}

 完善功能

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞

  • 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)

实现步骤:

  • 给Blog类中添加一个isLike字段,标示是否被当前用户点赞

  • 修改点赞功能,利用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1,将这篇笔记点赞过的用户id存储到set集合中,实现去重

  • 修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段

  • 修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段

首先给blog类添加isLike字段,@TableField(exist = false)表示该字段不属于数据库字段

 先从redis中的set集合中判断该用户是否点过赞,如果已经点赞过会从set集合移除该用户,表示取消点赞,否则会先走数据库,并将用户id存入set集合中

 @Overridepublic Result likeBlog(Long id){// 1.获取登录用户Long userId = UserHolder.getUser().getId();// 2.判断当前登录用户是否已经点赞String key = BLOG_LIKED_KEY + id;Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());if(BooleanUtil.isFalse(isMember)){//3.如果未点赞,可以点赞//3.1 数据库点赞数+1boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();//3.2 保存用户到Redis的set集合if(isSuccess){stringRedisTemplate.opsForSet().add(key,userId.toString());}}else{//4.如果已点赞,取消点赞//4.1 数据库点赞数-1boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();//4.2 把用户从Redis的set集合移除if(isSuccess){stringRedisTemplate.opsForSet().remove(key,userId.toString());}}

点赞状态查询

 在用户进行点赞之后,我们还需要完善对应的查询笔记接口,以保证用户点赞后的高亮响应

对判断当前用户是否点赞该笔记,以及笔记对象要封装对应的用户信息这两个方法封装,原因是首页笔记分页查询以及笔记详情都要用到,实现代码复用

//笔记需要封装对应的用户信息 
void fillUserToBlog(Blog blog) {Long userId = blog.getUserId();User user = userService.getById(userId);blog.setName(user.getNickName());blog.setIcon(user.getIcon());}
//判断当前用户是否已经点赞笔记void isLikeBlog(Blog blog) {UserDTO user = UserHolder.getUser();
//这里进行空指针判断,原因是首页并不需要登录就能访问,所以当user为空时直接结束if (user == null) {return;}Long userId = user.getId();String key = BLOG_LIKED_KEY + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());blog.setIsLike(score != null);}

首先就是点进笔记,查看笔记详情时,有个点赞状态查询,我们需要找到对应的接口方法进行改造

  @Overridepublic Result queryBlogById(Long id) {Blog blog = getById(id);fillUserToBlog(blog);isLikeBlog(blog);return Result.ok(blog);}

对首页笔记分页查询的方法也需要进行改造,完善点赞状态和用户信息

@Overridepublic Result queryHotBlog(Integer current) {// 根据用户查询Page<Blog> page = query().orderByDesc("liked").page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));// 获取当前页数据List<Blog> records = page.getRecords();// 查询用户records.forEach(blog -> {fillUserToBlog(blog);isLikeBlog(blog);});return Result.ok(records);}

点赞排行榜

在探店笔记的详情页面,会把给该笔记点赞的人显示出来,比如最早点赞的TOP5,形成点赞排行榜,就像朋友圈的点赞的一样,按照时间顺序排序点赞的人,这要求我们采用能排序的数据结构来存储点赞用户的id而不是像set一样是无序的,list虽然能实现按添加顺序排序,但是list元素不能唯一,不能实现一人一赞的功能,故最后sortedSet来实现

改进点赞功能

我们现在要将点赞用户的id存储在sortedSet中,需要在原有代码的基础上进行改善,换成存储在sortedSet中,由于sortedSet没有直接判断该value是否在这一集合中的方法,只能获取该value的score值来判断是否存在

@Overridepublic Result likeBlog(Long id) {//获取登录用户Long userId = UserHolder.getUser().getId();//判断该用户是否已经点过赞String key = BLOG_LIKED_KEY + id;Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());if (score == null) {boolean isSuccess = update().setSql("liked=liked+1").eq("id", id).update();if (isSuccess) {stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());}} else {boolean isSuccess = update().setSql("liked=liked-1").eq("id", id).update();if (isSuccess) {stringRedisTemplate.opsForZSet().remove(key, userId.toString());}}return Result.ok();}
void isLikeBlog(Blog blog) {UserDTO user = UserHolder.getUser();if (user == null) {return;}Long userId = user.getId();String key = BLOG_LIKED_KEY + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());blog.setIsLike(score != null);

 我们先将点赞用户的前五位从sortset中取出来,需要注意的是,由于我们使用的是stringRedisTemplate,取出的元素是string类型的,我们需要对获取的id集合进行处理,这里使用stream流,将id集合都转化为Long类型,由于sql语句中的in查询出来的用户列表,又重新以id排序了,故我们需要拼接上order by进行排序

  @Overridepublic Result queryBlogLikes(Long id) {String key = BLOG_LIKED_KEY + id;Long userId = UserHolder.getUser().getId();Set<String> range = stringRedisTemplate.opsForZSet().range(key, 0, 4);List<Long> ids = range.stream().map(item -> Long.valueOf(item)).collect(Collectors.toList());String joinIds = StrUtil.join(",", ids);List<UserDTO> userDTOS = userService.query().in("id", ids).last("order by FIELD(id," + joinIds + "  )").list().stream().map(user ->BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(userDTOS);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139491.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis学习笔记9 动态SQL

Mybatis学习笔记8 查询返回专题_biubiubiu0706的博客-CSDN博客 动态SQL的业务场景&#xff1a; 例如 批量删除 get请求 uri?id18&id19&id20 或者post id18&id19&id20 String[] idsrequest.getParameterValues("id") 那么这句SQL是需要动态的 还…

AJAX学习

文章目录 创建 XMLHttpRequest 对象向服务器发送请求XMLHttpRequest.open()XMLHttpRequest.send()GET或POST 服务器响应XMLHttpRequest 的属性XMLHttpRequest.readyStateXMLHttpRequest.onreadystatechangeXMLHttpRequest.responseXMLHttpRequest.responseTypeXMLHttpRequest.r…

软件工程之总体设计

总体设计是软件工程中的一个重要阶段&#xff0c;它关注整个系统的结构和组织&#xff0c;旨在将系统需求转化为可执行的软件解决方案。总体设计决定了系统的架构、模块划分、功能组织以及数据流和控制流等关键方面。 可行性研究 具体方面&#xff1a;经济可行性、技术可行性…

PY32F003F18之DMA串口

PY32F003F18使用DMA串口&#xff0c;官方程序省FLASH&#xff0c;但不省内存。单片机内存够大&#xff0c;节省没意义&#xff0c;故做了修改&#xff0c;少用HAL库中的发送和接收&#xff0c;从里面抠出有用的部分&#xff0c;修修改改就可以了。 一、DMA串口初始化流程&…

Vue页面快速使用阿里巴巴矢量图标库

前面我已经写个一篇文章 阿里巴巴矢量图标如何使用_turbo夏日漱石的博客-CSDN博客 这篇文章非常详细地讲解了在html页面中如何使用阿里巴巴矢量图标库 下面我们讲解在vue页面中引入阿里巴巴矢量图标库icon的几种方法 目录 一、引入在线链接 1、 第九步链接引入在vue中应该是在…

安卓备份基带分区 备份字库 步骤解析 以免误檫除分区或者“格机” 后悔莫及

玩机搞机---安卓机型mtk和高通芯片查看分区 导出分区 备份分区的一些工具分析 修复基带 改串码 基带qcn 改相关参数 格机危害 手机基带的重要性前面几期博文我都有相关的说明。他区别于别的分区。而且目前手机的安全性越来越高。基带分区基本都是专机专用。而不像早期机型一…

【AI语言大模型】文心一言功能使用介绍

一、前言 文心一言是一个知识增强的大语言模型&#xff0c;基于飞桨深度学习平台和文心知识增强大模型&#xff0c;持续从海量数据和大规模知识中融合学习具备知识增强、检索增强和对话增强的技术特色。 最近收到百度旗下产品【文心一言】的产品&#xff0c;抱着试一试的心态体…

java服务内存说明及配置详解

java进程内存 JVM内存分布图: 【java进程内存】【堆外内存】 【jvm堆内存】 【堆外内存】 【Metaspace】 【Direct Memory】【JNI Memory】【code_cache】 … 堆外内存泄漏的排查在于【本地内存&#xff08;Native Memory&#xff09;】【Direct Memory】【JNI Memory】 一般…

期刊分类一览

分区情况 jcr分区 中科院分区 EI 理工科 一般是SCI的都是EI 国内的分区

网络安全深入学习第三课——热门框架漏洞(RCE—Struts2远程代码执行)

文章目录 一、Struts2框架介绍二、Struts2远程代码执行漏洞三、Struts2执行代码的原理四、Struts2框架特征五、漏洞手工POC六、漏洞工具复现 一、Struts2框架介绍 ------ Struts2是apache项目下的一个web 框架&#xff0c;普遍应用于阿里巴巴、京东等互联网、政府、企业门户网…

2023-09-20 Android CheckBox 让文字显示在选择框的左边

一、CheckBox 让文字在选择框的左边 &#xff0c;在布局文件里面添加下面一行就可以。 android:layoutDirection"rtl" 即可实现 android:paddingStart"10dp" 设置框文间的间距 二、使用的是left to right <attr name"layoutDirection">&…

一文掌握CodiMD安装与使用

简介&#xff1a;CodiMD 是一个基于 Markdown 语言的实时协作文档编辑器&#xff0c;它允许多个用户在同一个文档上进行实时编辑。CodiMD 的前身是 HackMD&#xff0c;但为了满足更开放的开源社区需求&#xff0c;CodiMD 作为其社区版本独立出来。 优势&#xff1a; 1. 开源且…

【Godot】解决游戏中的孤立/孤儿节点及分析器性能问题的分析处理

Godot 4.1 因为我在游戏中发现&#xff0c;越运行游戏变得越来越卡&#xff0c;当你使用 Node 节点中的 print_orphan_nodes() 方法打印信息的时候&#xff0c;会出现如下的孤儿节点信息 孤儿节点信息是以 节点实例ID - Stray Node: 节点名称(Type: 节点类型) 作为格式输出&a…

关于JPA +SpringBoot 遇到的一些问题及解决方法

关于JPA SpringBoot 遇到的一些问题及解决方法&#xff08;可能会有你正在遇到的&#xff09; 一、JpaRepository相关 1.1 org.springframework.dao.InvalidDataAccessResourceUsageException: Named parameter not bound : id; nested exception is org.hibernate.QueryEx…

【从0学习Solidity】33. 发送空投

【从0学习Solidity】 33. 发送空投 博主简介&#xff1a;不写代码没饭吃&#xff0c;一名全栈领域的创作者&#xff0c;专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构&#xff0c;分享一些项目实战经验以及前沿技术的见解。关注我们的主页&#xff0c;探索全栈…

day03_基础语法

今日内容 零、复习昨日 一、Idea安装&#xff0c;配置 二、Idea使用 三、输出语句 四、变量 五、数据类型 附录: 单词 零、 复习昨日 1 装软件(typora,思维导图) 2 gpt(学会让他帮你解决问题) 3 java发展(常识) 4 HelloWorld程序 5 编码规范 6 安装jdk,配置环境变量 电脑常识 任…

vuex如何安装、报错、安装版本注意事项

npm i vuex报错&#xff0c;为什么呢&#xff1f; 在2022.2.7&#xff0c;Vue3就变成了默认版本&#xff0c; Vue2中&#xff0c;必须要用Vuex的3版本 Vue3中&#xff0c;必须要用Vuex的4版本&#xff0c;否则会报错 npm i vuex 安装的就是4版本 如果我们需要安装3版本&…

LaTex打出上大下小的公式

想要在latex中打出如下word公式 首先使用 \atop符号 使用如下语句 d_{H(A,B)} max\{{sup\, inf \atop {a \in A\,b \in B}}\,d(a,b), {sup\, inf\,\atop {b\in B\,a\in\,A}}d(b,a)\}. ![在这里插入图片描述](https://img-blog.csdnimg.cn/0c842594716a4693b1124523d53bfcad…

Unity实现角色受到攻击后屏幕抖动的效果

文章目录 实现效果摄像机抖动脚本 玩家受伤其他文章 实现效果 首先看一下实现效果。 摄像机 我们要使用屏幕抖动&#xff0c;使用的是CinemachineVirtualCamera这个组件&#xff0c;这个组件需要在包管理器中进行导入。 导入这个组件之后&#xff0c;创建一个Chinemachine-…

【Spring】Spring Security学习笔记

基本概念 概念定义认证判断一个用户身份是否合法的过程(登录过程)会话为了避免用户的每次操作都进行认证, 将用户的信息保存在会话中. 常见的会话有基于session的模式和基于token的模式授权校验用户是否有权限访问某个资源 认证是为了验证用户的身份; 授权是为了验证用户是否有…