黑马点评-达人探店

news/2024/4/30 21:42:06/文章来源:https://blog.csdn.net/abc123mma/article/details/127629134

摘要:达人探店业务:

  • 本质是发表blog和点赞等功能。
  • 利用Redis的Set实现点赞与取消点赞,
  • 然后利用SortedSet对点赞功能进行改进实现点赞排行的功能。

在学习的过程中,我们不应该急于写代码,首先分析业务逻辑,将业务的输入输出和过程都搞明白,然后根据业务逻辑写代码。最后完成调试

 实现代码:

BlogServiceImpl

@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);
}

达人探店-点赞功能

初始代码

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

问题分析:这种方式会导致一个用户无限点赞,明显是不合理的

造成这个问题的原因是,我们现在的逻辑,发起请求只是给数据库+1,所以才会出现这个问题

完善点赞功能

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞
  • 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)

实现步骤:

  • 给Blog类中添加一个isLike字段,标示是否被当前用户点赞
  • 修改点赞功能,利用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1
  • 修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段
  • 修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段

为什么采用set集合:

因为我们的数据是不能重复的,当用户操作过之后,无论他怎么操作,都是

具体步骤:

1、在Blog 添加一个字段--前端根据这个字段,来实现点赞标识业务

@TableField(exist = false)
private Boolean isLike;

2、修改代码  

 @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());}}

利用Redis中Set基本可以改进点赞功能,但是我们需要实现点赞排行榜,这就需要用到SortedSet。

点赞排行榜

我们接下来来对比一下这些集合的区别是什么

所有点赞的人,需要是唯一的,所以我们应当使用set或者是sortedSet

其次我们需要排序,就可以直接锁定使用sortedSet啦

修改代码

BlogServiceImpl

点赞逻辑代码:主要涉及到将Set变为SortedSet。

   @Overridepublic Result likeBlog(Long id) {// 1.获取登录用户Long userId = UserHolder.getUser().getId();// 2.判断当前登录用户是否已经点赞String key = BLOG_LIKED_KEY + id;Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());if (score == null) {// 3.如果未点赞,可以点赞// 3.1.数据库点赞数 + 1boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();// 3.2.保存用户到Redis的set集合  zadd key value scoreif (isSuccess) {stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());}} else {// 4.如果已点赞,取消点赞// 4.1.数据库点赞数 -1boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();// 4.2.把用户从Redis的set集合移除if (isSuccess) {stringRedisTemplate.opsForZSet().remove(key, userId.toString());}}return Result.ok();}private void isBlogLiked(Blog blog) {// 1.获取登录用户UserDTO user = UserHolder.getUser();if (user == null) {// 用户未登录,无需查询是否点赞return;}Long userId = user.getId();// 2.判断当前登录用户是否已经点赞String key = "blog:liked:" + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());blog.setIsLike(score != null);}

点赞列表查询列表

BlogController

@GetMapping("/likes/{id}")
public Result queryBlogLikes(@PathVariable("id") Long id) {return blogService.queryBlogLikes(id);
}

BlogService

@Override
public Result queryBlogLikes(Long id) {String key = BLOG_LIKED_KEY + id;// 1.查询top5的点赞用户 zrange key 0 4Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);if (top5 == null || top5.isEmpty()) {return Result.ok(Collections.emptyList());}// 2.解析出其中的用户idList<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());String idStr = StrUtil.join(",", ids);// 3.根据用户id查询用户 WHERE id IN ( 5 , 1 ) ORDER BY FIELD(id, 5, 1)List<UserDTO> userDTOS = userService.query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list().stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());// 4.返回return Result.ok(userDTOS);
}

最后代码总结,分析其中优秀代码:

主要是涉及到Stream流的用法。

Java 8 Stream | 菜鸟教程 (runoob.com)

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

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

相关文章

SpringBoot项目启动执行任务的几种方式

经过整理后得到以下几种常用方式&#xff0c;供大家参考。 1. 使用过滤器 init() &#xff1a;该方法在tomcat容器启动初始化过滤器时被调用&#xff0c;它在 Filter 的整个生命周期只会被调用一次。可以在这个方法中补充想要执行的内容。 Component public class MyFilter …

vs2017 外网远程调试

外网远程调试:由于外网的目标电脑IP无法直接访问&#xff0c;则需要第三方内网穿透工具辅助&#xff0c;本文使用NATAPP进行 注册一个账号&#xff1a;NATAPP -注册完成&#xff0c;登录后&#xff0c;在购买隧道中选择Free免费购买一个 购买成功后&#xff0c;在我的隧道中可…

突破出行市场桎梏,需要高端出行的精神内核?

如果高端出行是一本书&#xff0c;那么豪车可能只是封面和封底。真正重要的&#xff0c;是隐藏其中的服务的精神与体验的内核。 这一点&#xff0c;国内高端出行市场的探索者们应当深有体会。从早期高端巡游出租车&#xff0c;到BBA豪华车势力曾经推动的高端出行网约车&#x…

「设计模式」工厂方法模式

文章目录一、概念二、用途三、实现方式四、工厂方法模式的利与弊为什么要使用工厂来创建对象&#xff1f;为什么每种对象要单独有一个工厂&#xff1f;五、工厂方法与简单工厂的区别六、总结参考资料一、概念 工厂方法模式(Factory Method Pattern)又称为工厂模式&#xff0c;…

前端工具——01-VS Code的使用

前言 文章标题&#xff1a;《第一次使用 VS Code 时你应该知道的一切配置》。本文的最新内容&#xff0c;更新于 2020-06-19。大家完全不用担心这篇文章会过时&#xff0c;因为随着 VS Code 的版本更新和插件更新&#xff0c;本文也会随之更新。 本文的最新内容&#xff0c;也会…

腾讯云centos7安装mysql5.7

昨天服务器上的数据库被勒索了&#xff0c;重装系统之后不得不再装一次数据库&#xff0c;踩了很多坑&#xff0c;在此记录安装过程。 首先把centos7自带的数据库mariadb卸载掉&#xff0c;把MySQL的相关文件夹都删掉。 查看组件服务 rpm -qa | grep -i mariadb rpm -qa | gr…

Mybatics-连接配置

1、mysql连接数_MySQL配置参数优化 1.1、优化最大连接数max_connections 是MySQL最大并发连接数默认值是151 MySQL允许的最大连接数上限是32767 实际连接数是最大连接数的85%较为合适 查询数据库目前设置的最大并发连接数是多少 查询数据库目前实际连接的并发数是多少 在MyS…

SpringBoot集成JWT(极简版):

文章目录1.JWT依赖2.JWT工具类TokenUtils.java3.token示例4.拦截器JwtInterceptor.java5.拦截器设置InterceptorConfig.java6.统一接口WebConfig.java7.设置自定义头配置 CorsConfig .java8.GlobalExceptionHandler.java9.ServiceException.java10.设置token:11.最终效果&#…

离线下IDEA打开拷贝的完整工程,解决工程代码大量报错的问题

一、背景 在日常工作中&#xff0c;代码工程的保存和协作开发一般是通过代码仓库实现的。但是对于正常的多人研究开发时&#xff0c;工程代码的物理拷贝也是需要的&#xff0c;这可以节省工程代码依赖环境的安装和配置&#xff0c;同时也能保证代码完整和版本一致。 在大部分企…

【测试沉思录】9. 数据工厂低代码平台探索与实践

欢迎订阅我的新专栏《现代命令行工具指南》&#xff0c;精讲目前最流行的开源命令行工具&#xff0c;大大提升你的工作效率。 作者&#xff1a;吴锺瑞、刘洪初 编辑&#xff1a;毕小烦 一. 需求背景 造数据可能是日常迭代中最频繁也是最耗时的工作。 我们在20年8月对部门内的…

HashSet实现类的使用

【1】放入Integer类型数据package com.msb.test06;import java.util.HashSet;/*** @author : liu* 日期:10:36:57* 描述:IntelliJ IDEA* 版本:1.0*/ public class TestInteger {//这是一个main方法:是程序的入口public static void main(String[] args) {//创建一个HashSet集合…

Cannon.js -- 3d物理引擎

文章目录前言一、关于Cannon.js二、Cannon.js的使用最后注意点&#xff1a;优化事件其他本文完整代码下载&#xff1a;相关链接&#xff1a;前言 本篇将介绍Cannon.js -- 3d物理引擎的基础使用&#xff0c;并用Cannon.js与three.js写一个简单的demo 一、关于Cannon.js Q&…

什么是轮廓阴影和圆角

目录 outline box-shadow 将元素设置为一个圆形 outline outline 用来设置元素的轮廓线&#xff0c;用法和border一模一样 轮廓和边框不同的点&#xff0c;就是轮廓不会影响到可见框的大小 <!DOCTYPE html> <html lang"en"> <head><meta ch…

【CV】第 6 章:使用迁移学习的视觉搜索

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Protocol Buffers学习【Qt】

文章目录参考前言开发环境# 一、下载1. 打开网页2. 点击download3. 下载二、 编译1. 解压2. 用QC打开项目3. 编译并等待4. 打开 extract_includes.bat5. 新建lib文件夹三、使用1. 新建 lm.helloworld.proto2. Qt 新建 HelloProtobuf 子目录项目3. lib_protobuf 目录4. Writer 工…

腾讯云创建SVN支持多人协同办公

本文参考自&#xff1a; 如何在腾讯云轻量级服务器搭建svn_我的天才女友的博客-CSDN博客_腾讯云 svn 搭建SVN服务器-腾讯云 - 夜页子 - 博客园 一、配置要求 选择腾讯云CentOS的镜像进行安装 二、SVN服务端 1.SVN服务端的安装 yum install subversion 接下来输入y按回车继…

C语言练习---【求素数】(一篇带你掌握素数求解)

&#x1f996;作者&#xff1a;学写代码的恐龙 &#x1f996;博客主页&#xff1a;学写代码的恐龙博客主页 &#x1f996;专栏&#xff1a;【初级c语言】 &#x1f996;语录&#xff1a;❀未来的你&#xff0c;一定会感谢现在努力奋斗的自己❀ C语言练习---【求素数】&#x1…

数据分析 | Pandas 200道练习题,每日10道题,学完必成大神(7)

文章目录前期准备1. 以df的列名创建一个DataFrame2. 打印所有换手率为非数字的行3. 删除所有换手率为非数字的行4. 重置df的行号5. 绘制‘还手’密度曲线6. 计算后一天和前一天收盘价的差值7. 计算后一天与前一天收盘价的变化率8. 设置时间索引9. 使用时间索引&#xff0c;分别…

JavaScript 49 JavaScript 作用域

JavaScript 文章目录JavaScript49 JavaScript 作用域49.1 JavaScript 函数作用域49.2 局部 JavaScript 变量49.3 全局 JavaScript 变量49.4 JavaScript 变量49.5 自动全局49.6 严格模式49.7 HTML 中的全局变量49.8 警告49.9 JavaScript 变量的有效期49.10 函数参数49 JavaScrip…