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

06.利用Redis实现点赞功能

学习目标:

提示:学习如何利用Redisson实现点赞功能


学习产出:

解决方案:

  1. 点赞后的用户记录在Redis的set数据类型中

1. 准备pom环境

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope><version>5.1.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.17</version></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.23.1</version></dependency>

2. 配置ThreadLocal和过滤器

public class UserHolder {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();}
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {@Autowiredprivate StringRedisTemplate redis;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","/blog/hot","/shop/**","/shop-type/**","/voucher/**").order(2);registry.addInterceptor(new RefreshTokenInterceptor(redis)).addPathPatterns("/**").order(1);}
}
---------------------------------------------
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {//controller执行之前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.判断是否需要拦截ThreadLocalif (UserHolder.getUser()==null) {response.setStatus(401);return false;}//7.放行return true;}//渲染后返回给前台数据前@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//移除用户,避免内存泄露UserHolder.removeUser();}
}
---------------------------------------------------
@Slf4j
public class RefreshTokenInterceptor implements HandlerInterceptor {//这个对象不是由spring管理的所以不能用注解自动注入private StringRedisTemplate redis;public RefreshTokenInterceptor(StringRedisTemplate redis) {this.redis = redis;}//controller执行之前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取请求头中的tokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)) {return true;}//2.基于token获取redis中的用户//通过key取到hash中的map集合数据Map<Object, Object> userMap = redis.opsForHash().entries("login:token:" + token);//3.判断用户是否存在if (userMap.isEmpty()) {return true;}//5.将查询到的hash数据转为userDto对象UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//6.存在,保存用户信息到ThreadLocal中UserHolder.saveUser(userDTO);//7.刷新token有效期redis.expire(LOGIN_USER_KEY + token, 30, TimeUnit.MINUTES);log.info("我是第一个拦截器当前拦截所有请求的用户为,线程为{},{}",UserHolder.getUser(),Thread.currentThread());//8.放行return true;}

3. Controller层:负责接收请求和向下分配

@RestController
@RequestMapping("/blog")
public class BlogController{@Resourceprivate IBlogService blogService;@PutMapping("/like/{id}")public Result likeBlog(@PathVariable("id") Long id) {return blogService.likeBlog(id);}
}

4. Service层:负责业务的处理逻辑点赞功能

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {@Autowiredprivate IUserService userService;@Resourceprivate StringRedisTemplate redis;@Overridepublic Result likeBlog(Long id) {//1.获取登录用户Long userId = UserHolder.getUser().getId();//2.判断当前用户是否已经点赞String key = "blog:liked:" + id;Boolean member = redis.opsForSet().isMember(key, userId.toString());if (BooleanUtil.isFalse(member)) {//3.如果未点赞,可以点赞//3.1 点赞+1boolean isSuccess = update().setSql("liked= liked +1").eq("id", id).update();//3.2保存用户到Redis的set集合中if (isSuccess) {redis.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) {redis.opsForSet().remove(key,userId.toString());}}return null;}
}

相关文章:

06.利用Redis实现点赞功能

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redisson实现点赞功能 学习产出&#xff1a; 解决方案&#xff1a; 点赞后的用户记录在Redis的set数据类型中 1. 准备pom环境 <dependency><groupId>org.springframework.boot</groupId><artifactI…...

【React】生命周期和钩子函数

概念 组件从被创建到挂载到页面中运行&#xff0c;再到组件不用时卸载的过程。 只有类组件才有生命周期。 分为三个阶段&#xff1a; 挂载阶段更新阶段销毁阶段 三个阶段 挂载阶段 钩子函数 - constructor 创建阶段触发 作用&#xff1a;创建数据 之前定义状态是简写&…...

无涯教程-TensorFlow - 优化器

Optimizers是扩展类&#xff0c;其中包括用于训练特定模型的附加信息&#xff0c;Optimizers类使用给定的参数初始化&#xff0c;用于提高速度和性能&#xff0c;以训练特定模型。 TensorFlow的基本Optimizers是- tf.train.Optimizer 此类在tensorflow/python/training/opti…...

基于AQS+双向链表实现队列先进先出

学习AQS写的一个模拟案例 package com.tom.xiangyun.ch04_aqs;import com.tom.tuling.UnsafeFactory; import sun.misc.Unsafe;import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock;/*** 使用双向链表实现队列** author 钟棋…...

无涯教程-Perl - time函数

描述 此函数返回自纪元以来的秒数(对于大多数系统,是1970年1月1日UTC,00:00:00&#xff1b;对于Mac OS,是1904年1月1日,00:00:00)。适用于gmtime和本地时间。 语法 以下是此函数的简单语法- time返回值 此函数返回自纪元后数秒的整数。 例 以下是显示其基本用法的示例代…...

CUDA Bug<三>当__global__函数出现里面所有输出的数组都随机赋值了

问题具体描述&#xff1a; eg. __global__ void Updata_HomJm(float* H,float *HJm,float* fr,float *gr,float* ur,float* urgrJm,float*wpd,float *w, float *wJm,int n) { int idx blockIdx.x*blockDim.x threadIdx.x;float t 0.0;//H*zpint idx_Ai idx*n;for (int j…...

甜椒叶病害识别(Python代码,pyTorch框架,深度卷积网络模型,很容易替换为其它模型,带有GUI识别界面)

代码运行要求&#xff1a;Torch>1.13.1即可 1.数据集介绍&#xff1a; 第一个文件夹是细菌斑叶&#xff08;3460张&#xff09; 第二个文件夹是 健康&#xff08;4024张&#xff09; 2.整个文件夹 data文件夹存放的是未被划分训练集和测试集的原始照片 picture文件夹存放的…...

Python爬虫——scrapy_日志信息以及日志级别

日志级别&#xff08;由高到低&#xff09; CRITICAL&#xff1a; 严重错误 ERROR&#xff1a; 一般错误 WARNING&#xff1a; 警告 INFO&#xff1a; 一般警告 DEBUG&#xff1a; 调试信息 默认的日志等级是DEBUG 只要出现了DEBUG或者DEBUG以上等级的日志&#xff0c;那么这些…...

微信小程序 echarts 画多个横向柱状图

然后是json {"usingComponents": {"ec-canvas": "../../common/ec-canvas/ec-canvas"},"navigationBarTitleText": "主题活动" } ec-canvas获取方式 在链接里下载代码 然后copy ec-canvas文件夹到自己的项目 https://gi…...

【二叉树】572. 另一棵树的子树

572. 另一棵树的子树 解题思路 遍历二叉树的思路针对每一个节点判断该节点的子树和subtree是不是相等需要编写判断两个子树是否相等的函数 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* …...

220V转5V芯片三脚芯片-AH8652

220V转5V芯片三脚芯片是一种非常常见的电源管理芯片&#xff0c;它通常被用于将高压交流输入转为稳定的直流5V输出。芯片型号AH8652是一款支持交流40V-265V输入范围的芯片&#xff0c;采用了SOT23-3三脚封装。该芯片内部集成了650V高压MOS管&#xff0c;能够稳定地将输入电压转…...

windows系统丢失mfc120u.dll的解决方法

1.mfc120u.dll是什么 mfc120u.dll是Windows操作系统中的一个动态链接库&#xff08;Dynamic Link Library&#xff0c;简称DLL&#xff09;文件。它包含了一些用于运行C程序的函数和其他资源。这个特定的DLL文件是Microsoft Foundation Classes&#xff08;MFC&#xff09;库的…...

css 实现电梯导航

实现原理&#xff1a;利用css实现电梯导航很简单&#xff0c;基本原理就是通过a标签绑定跳转目标的id来实现的 html代码&#xff1a; <div class"body"><div class"top" id"top"></div><div class"con1" id"…...

【Spring Boot】Spring Retry减少1000 行代码讲解

文章目录 前言问题介绍解决方案Let’s start hacking!1. 设置 Spring 重试2. 重构代码 总结 前言 本文翻译自国外论坛 medium&#xff0c;原文地址&#xff1a;levelup.gitconnected.com/how-i-delet…&#xff0c;原文作者&#xff1a;Hari Ohm Prasath 使用 Spring Retry 重…...

【数据结构OJ题】相交链表

原题链接&#xff1a;https://leetcode.cn/problems/intersection-of-two-linked-lists/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 看到这道题&#xff0c;很容易想到的方法就是暴力求解&#xff0c;就是将一个链表的每个结点的地址…...

【华为OD机试】最小传输时延I【2023 B卷|200分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 某通信网络中有N个网络结点,用1到N进行标识。网络通过一个有向无环图表示, 其中图的边的值表示结点之间的消息传递时延。 现给定相连节点之间的时延列表times[i]={u,v,w},其中u表示…...

Android13 网络 Adb 默认开启

Android 13 网络 Adb 默认开启 文章目录 Android 13 网络 Adb 默认开启一、前言二、默认adb 代码实现1、修改的目录&#xff1a;2、具体修改&#xff1a;&#xff08;1&#xff09;在XXX_device.mk 添加属性&#xff08;2&#xff09;设置固定端口号&#xff08;3&#xff09;去…...

Git分享-规范/建议/技巧

1. Git多人协作开发流程图 1.1 processOn默认的模板 1.2 改造之后 https://www.processon.com/view/link/64ccaf56a433c931b2f9428a 访问密码&#xff1a;512I ① 总流程图 ② feat分支&#xff08;功能/需求 分支&#xff09;流程 ③ bugfix分支&#xff08;紧急补丁分支&…...

vue3文件下载功能

定义方法&#xff1a; utils.js /**** param url 目标下载接口* param query 查询参数* param fileName 文件名称* returns {*}*/ export function downBlobFile(url: any, query: any, fileName: string) {return request({//url: url,method: get,responseType: blob,param…...

Python调用文心一言的API

最近申请了文心一言的key&#xff0c;然后尝试调用了一下文心一言&#xff0c;这里使用一个简单的方式来调用文心一言&#xff1a; pip install paddle-pipelinesfrom pipelines.nodes import ErnieBotapi_key "your apply key" secret_key "your apply secr…...

【计算机网络八股】计算机网络(一)

目录 计算机网络的各层协议及作用&#xff1f;TCP和UDP的区别&#xff1f;UDP 和 TCP 对应的应用场景是什么&#xff1f;详细介绍一下 TCP 的三次握手机制&#xff1f;为什么需要三次握手&#xff0c;而不是两次&#xff1f;为什么要三次握手&#xff0c;而不是四次&#xff1f…...

记录一次arcgis engine开发版本引入问题

之前基于arcigs 10.1vs2013开发的程序&#xff0c;现在拿出来要改&#xff0c;但是目前版本是arcgis10.7vs2017/vs2019,打开后无论如何替换引用版本&#xff0c;都报错 &#xff08;具体版本对应可以看这&#xff1a;ArcGIS Engine 与 Visual Studio 版本对照表_vs2019对应啥版…...

2023年Java毕业设计怎样选题,有哪些注意事项,300道Java毕业设计题目

文章目录 一、确定个人兴趣和技能二、考虑实际应用价值三、注重创新和独特性四、合理规划时间和资源五、注重实践和测试Java 毕业设计题目参考第一部分第二部分 小结 随着计算机技术的不断发展&#xff0c;Java编程语言已经成为了众多大学计算机专业学生必修的一门课程。而Java…...

算法-滑动窗口-串联所有单词的子串

算法-滑动窗口-串联所有单词的子串 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/substring-with-concatenation-of-all-words/ 1.2 题目描述 2 滑动窗口Hash表 2.1 解题思路 构建一个大小为串联子串的总长的滑动窗口为每个words中的子串创建一个hash表, <子…...

2023年7月京东美妆护肤品小样行业数据分析(京东数据挖掘)

如今&#xff0c;消费者更加谨慎&#xff0c;消费决策也更加理性。在这一消费环境下&#xff0c;美妆护肤市场中&#xff0c;面对动辄几百上千的化妆品&#xff0c;小样或体验装无疑能够降低消费者的试错成本。由此&#xff0c;这门生意也一直备受关注。 并且&#xff0c;小样…...

记录Taro巨坑,找不到sass类型定义文件

问题 taronutuisassts项目里tsconfig.json一直报红报错。 找不到“sass”的类型定义文件。 程序包含该文件是因为: 隐式类型库 “sass” 的入口点 其实正常人想的肯定是装上 types/sass试试。开始我试过了&#xff0c;没用。删了依赖重装也没用。后面在issue中找到答案了 解决…...

CS1988|C#无法在异步方法中使用ref,in,out类型的参数的问题

CS1988|C#无法在异步方法中使用ref,in,out类型的参数 &#x1f300;|场景&#xff1a; BlazorServer的场景中推荐使用异步方法&#xff0c;使用ref,out,in为参数前缀则报错CS1988 原因如下: ref parameters are not supported in async methods because the method may not h…...

ubuntu开机失败——ACPI Error

开机循环进入GNU GRUB 或者 黑屏 1.acpioff 解决办法 1&#xff09;先用下面方法进入系统 2&#xff09;更改grub ref 开机循环进入GNU GRUB 或者 黑屏 有提示ACPI Error错误如图&#xff1a; 解决办法 1&#xff09;先用下面方法进入系统 在GUN GRUB界面&#xff0c;选择ubun…...

搭建开发环境-操作系统篇(一键搭建开发环境)

概述 所谓工欲善其事必先利其器&#xff0c;搭环境往往是开发过程中卡出很多初学者的拦路虎。 对于很多老鸟来说&#xff0c;很多东西都已经习惯成自然&#xff0c;也就没有刻意和初学者说。但对于很多初学者&#xff0c;却是受益良多。 这个系列&#xff0c;先从操作系统开始…...

人工智能AI绘画接入使用文档

人工智能AI绘画接入使用 一、人工智能AI绘画二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、 AI绘画优秀描述例子四、 如何获取appKey和uid1、申请appKey:2、获取appKey和uid 五、重要说明六、AI绘画成果展示 一、人工智能AI绘画 AI作画,用户可以在平台上…...

网站建设 会议主持稿/今日新闻国际最新消息

特别提示&#xff1a;本人博客部分有参考网络其他博客&#xff0c;但均是本人亲手编写过并验证通过。如发现博客有错误&#xff0c;请及时提出以免误导其他人&#xff0c;谢谢&#xff01;欢迎转载&#xff0c;但记得标明文章出处&#xff1a;http://www.cnblogs.com/mao2080/1…...

公司网站建设哪里实惠/今天nba新闻最新消息

版本服务器是用SVN server&#xff08;这个东西是放到版本机服务器上的&#xff09; 版本管理工具是用小乌龟&#xff08;tortoiseSVN&#xff0c;这个是在各个机器上使用&#xff09; 1&#xff0c;昨天下载了SVN server 按照网上教程搭建好 https://www.cnblogs.com/jutop…...

商城网站源码dede/东莞企业网站排名

OpenGL配置&#xff1a; 1.下载OpenGL的相关资料包 http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip2.解压安装包。将glut.h放在C盘的gl目录下&#xff08;可以通过在C盘搜索GL) 3.将glut.lib和glut32.lib放在vs的VC\lib目录下。 4.将glut.dll和glut32.dll…...

紫竹桥网站建设/免费自己建网页

西安比亚迪半导体成立国家企业信用信息公示系统显示&#xff0c;5月27日&#xff0c;西安比亚迪半导体有限公司&#xff08;以下简称“西安比亚迪半导体”&#xff09;在西安注册成立。来源&#xff1a;国家企业信用信息公示系统工商信息显示&#xff0c;西安比亚迪半导体注册资…...

校本教研网站建设方案/优化设计答案四年级上册语文

Numpy数组的索引是一个内容丰富的主题&#xff0c;因为选取数据子集或单个元素的方式有很多。一维数组很简单&#xff0c;跟Python列表的功能差不多 1 In [1]: import numpy as np2 3 In [2]: arr np.arange(10)4 5 In [3]: arr 6 Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, …...

矢量网站动画怎么做/网站上不去首页seo要怎么办

因为qemu内置了gdbserver&#xff0c;所以我们可以用gdb调试qemu虚拟机上执行的代码&#xff0c;而且不受客户机系统限制。 以下内容是我调试 grub 0.97 时的一份笔记。 准备 qemu, gdb,以及一份带grub的虚拟机镜像&#xff0c;一份grub源码。 调试过程 启动虚拟机 $ sudo qemu…...