用户关注功能

介绍

本文将介绍如何通过redis,mysql数据库实现用户关注,以及查看共同关注的功能。、

前置准备

创建一个tb_follow表,用于记录关注信息。

以及一个redis数据库。

实现思路

主要实现3个接口:

  • isFollow接口(进入up主页时调用):判断用户是否关注了当前up主,如果已经关注,返回true,否则返回false。
  • follow接口(点击关注按钮时调用):如果已经关注了该up,则取关,反之,关注up。
  • followCommons接口(点击共同关注按钮时调用):查看你和up都关注了哪些用户。

isFollow

controller

接收请求参数id(up主id),调用service中的业务逻辑。

java 复制代码
@GetMapping("/or/not/{id}")  
public Result isFollow(@PathVariable Long id) {  
    return followService.isFollow(id);  
}

service

java 复制代码
@Override  
public Result isFollow(Long id) {  
    Long userId = UserHolder.getUser().getId();  
    long count = query().eq("user_id", userId).eq("follow_user_id", id).count();  
    return Result.ok(count > 0);  
}

业务逻辑

从上下文(threadlocal)中获取当前用户id,根据用户id和up主id在tb_follow中查询数据,返回数据count > 0,如果有数据则为true,否则为false。

follow

controller

接收请求参数id(up主id),isFollow(true代表执行关注,false代表执行取关),调用service中的业务逻辑。

java 复制代码
@PutMapping("{id}/{isFollow}")  
public Result follow(@PathVariable Long id, @PathVariable Boolean isFollow) {  
    return followService.follow(id, isFollow);  
}

service

java 复制代码
@Override  
public Result follow(Long id, Boolean isFollow) {  
    Long userId = UserHolder.getUser().getId();  
    //判断当前用户是否关注  
    String key = "follow:" + userId;  
    if (isFollow) {  
        //关注,新增数据  
        Follow follow = new Follow();  
        follow.setUserId(userId);  
        follow.setFollowUserId(id);  
        boolean isSuccess = save(follow);  
        if (isSuccess) {  
            //把关注用户的id放入redis的set集合中,key:follow:userId value:followUserId  
            stringRedisTemplate.opsForSet().add(key, id.toString());  
        }  
    } else {  
        //取关,删除数据  
        boolean isSuccess = update().eq("user_id", userId).eq("follow_user_id", id).remove();  
        if (isSuccess) {  
            //把关注用户的id从redis的set集合中移除  
            stringRedisTemplate.opsForSet().remove(key, id.toString());  
        }  
    }  
    return Result.ok();  
}

业务逻辑

  1. 从上下文(threadlocal)中获取当前用户id。
  2. 执行关注或取关
    关注:将信息写入follow实体(属性与tb_follow表字段一致),并写入数据库,如果操作成功,再放入redis的set集合中。
    取关:删除数据库信息,如果成功,再移除redis的set集合中的id。

followCommons

controller

接收请求参数id(当前查看up主的id)。

java 复制代码
@GetMapping("/common/{id}")  
public Result followCommons(@PathVariable Long id) {  
    return followService.followCommons(id);  
}

service

java 复制代码
@Override  
public Result followCommons(Long id) {  
    Long userId = UserHolder.getUser().getId();  
    String myKey = "follow:" + userId;  
    String targetKey = "follow:" + id;  
    //求交集  
    Set<String> intersect = stringRedisTemplate.opsForSet().intersect(myKey, targetKey);  
    if (intersect == null || intersect.isEmpty()) {  
        //没有共同关注  
        return Result.ok("没有共同关注");  
    }  
    //解析id集合  
    List<Long> commonIds = intersect.stream().map(Long::valueOf).collect(Collectors.toList());  
    //查询用户  
    List<User> users = userService.listByIds(commonIds);  
    //转换为DTO  
    List<UserDTO> userDTOS = users  
            .stream()  
            .map(user -> BeanUtil.copyProperties(user, UserDTO.class))  
            .collect(Collectors.toList());  
    return Result.ok(userDTOS);  
}

业务逻辑

  1. 获取两者在redis中的key。
  2. 求两者交集。
    交集为空->直接返回结果
    有交集->解析出id集合
  3. 根据id集合查询用户,返回数据。

核心要点:

关注时将id放入redis中的set集合,优点:

查询效率 Redis Set 的 SINTER 命令可以一次求出交集,时间复杂度 O(min(n,m)),非常高效
去重 Set 自动去重,保证关注列表不重复
内存优化 相比数据库查询,Redis 内存操作快几十倍
相关推荐
qwert10372 小时前
Spring Boot从0到1 -day02
java·spring boot·后端
无责任此方_修行中2 小时前
一个 GitHub Issue 标题如何让 4000 台电脑沦陷?
后端·npm·ai编程
SimonKing2 小时前
开源免费!传统项目也可以接入天爱验证码(TAC),坑我来填
java·后端·程序员
猹叉叉(学习版)2 小时前
【ASP.NET CORE】 13. DDD初步实现
笔记·后端·架构·c#·asp.net·.netcore
huabiangaozhi2 小时前
Spring Cloud Gateway 整合Spring Security
java·后端·spring
野犬寒鸦3 小时前
从零起步学习计算机操作系统:进程篇(知识扩展提升)
java·服务器·开发语言·后端·面试
轩情吖3 小时前
MySQL内置函数
android·数据库·c++·后端·mysql·开发·函数
IT_陈寒3 小时前
JavaScript开发者必知的5个高效调试技巧,比console.log强10倍!
前端·人工智能·后端
小箌3 小时前
springboot_02
java·spring boot·后端