当前位置: 首页 > 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;}
}
http://www.lryc.cn/news/135184.html

相关文章:

  • 【React】生命周期和钩子函数
  • 无涯教程-TensorFlow - 优化器
  • 基于AQS+双向链表实现队列先进先出
  • 无涯教程-Perl - time函数
  • CUDA Bug<三>当__global__函数出现里面所有输出的数组都随机赋值了
  • 甜椒叶病害识别(Python代码,pyTorch框架,深度卷积网络模型,很容易替换为其它模型,带有GUI识别界面)
  • Python爬虫——scrapy_日志信息以及日志级别
  • 微信小程序 echarts 画多个横向柱状图
  • 【二叉树】572. 另一棵树的子树
  • 220V转5V芯片三脚芯片-AH8652
  • windows系统丢失mfc120u.dll的解决方法
  • css 实现电梯导航
  • 【Spring Boot】Spring Retry减少1000 行代码讲解
  • 【数据结构OJ题】相交链表
  • 【华为OD机试】最小传输时延I【2023 B卷|200分】
  • Android13 网络 Adb 默认开启
  • Git分享-规范/建议/技巧
  • vue3文件下载功能
  • Python调用文心一言的API
  • 【计算机网络八股】计算机网络(一)
  • 记录一次arcgis engine开发版本引入问题
  • 2023年Java毕业设计怎样选题,有哪些注意事项,300道Java毕业设计题目
  • 算法-滑动窗口-串联所有单词的子串
  • 2023年7月京东美妆护肤品小样行业数据分析(京东数据挖掘)
  • 记录Taro巨坑,找不到sass类型定义文件
  • CS1988|C#无法在异步方法中使用ref,in,out类型的参数的问题
  • ubuntu开机失败——ACPI Error
  • 搭建开发环境-操作系统篇(一键搭建开发环境)
  • 人工智能AI绘画接入使用文档
  • 如何使用PyQt进行文件操作