Redis——实现关注与取关等功能

目录

实现关注与取关

实现共同关注功能

关注推送

Feed流的模式

拉模式

推模式

推拉结合模式

总结

基于推模式实现关注推送功能

Feed流的分页问题

实现关注推送页面的分页查询


实现关注与取关

实现

Controller层

@RestController
@RequestMapping("/follow")
public class FollowController {
    @Resource
    private IFollowService followService;
    @PutMapping("/{id}/{isFollow}")
    public Result follow(@PathVariable("id")Long followUserId,@PathVariable("isFollow") Boolean isFollow){
        return followService.follow(followUserId,isFollow);
    }

    @GetMapping("/or/not/{id}")
    public Result follow(@PathVariable("id")Long followUserId){
        return followService.isFollow(followUserId);
    }
}

 

Service层

    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        Long userId = user.getId();
        //判断是取关还是关注
        if(isFollow){
            //2.关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
            follow.setCreateTime(LocalDateTime.now());
            boolean isSuccess = save(follow);
        }
        else{
            //取关,删除数据
            //sql: delete from tb_follow where user_id = ? and follow_user_id = ?
            remove(new QueryWrapper<Follow>()
                    .eq("user_id",userId)
                    .eq("follow_user_id",followUserId)
            );
        }
        return Result.ok();
    }

    @Override
    public Result isFollow(Long followUserId) {
        //1.获取用户
        UserDTO user = UserHolder.getUser();
        Long userId = user.getId();
        //查询是否关注
        //sql: select * from tb_follow where user_id = ? and follow_user_id
        Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();

        return Result.ok(count>0);
    }


实现共同关注功能

 

修改前面的关注接口,关注的对象不仅仅存入数据库中,还需存入redis中(共同关注功能需要set数据结构完成) 

修改

    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        Long userId = user.getId();
        String key = "follows:"+userId;
        //判断是取关还是关注
        if(isFollow){
            //2.关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
好的,下面是对这段代码的逐行详细解析: --- ### 成员变量注入部分 ```java @Resource private final StringRedisTemplate stringRedisTemplate; @Resource private IUserService userService; ``` 1. **`@Resource`注解** - 这是一个基于名称(byName)的依赖注入机制,默认会按照字段名寻找对应的Bean并完成注入。 - 如果找不到匹配的Bean,则会抛出异常。 2. **`StringRedisTemplate stringRedisTemplate`** - `stringRedisTemplate` 是一个 Redis 操作工具类,专门用于操作字符串类型的键值对。 - 它封装了 Redis 的底层命令,并提供了一些高级功能(如批量操作、事务等),在这里主要用于处理用户关注列表的数据存储和读。 3. **`IUserService userService`** - `userService` 可能是一个服务层接口,负责用户相的业务逻辑交互。 - 虽然在这段代码中未直接使用该变量,但它可能是为了后续扩展或其他方法调用准备的。 --- ### 构造函数初始化 ```java public FollowServiceImpl(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate = stringRedisTemplate; } ``` 1. **构造函数的作用** - 提供了一种通过构造器显式传入 `stringRedisTemplate` 的方式来初始化成员变量。 - 当前存在两种注入方式:一是通过 `@Resource` 注解自动装配;二是通过构造器手动设置。这种方式可以增强程序的灵活性,尤其是在单元测试场景下非常有用。 --- ### 核心业务逻辑方法 #### 方法签名为: ```java @Override public Result follow(Long followUserId, Boolean isFollow) ``` 1. **输入参数** - `followUserId`: 表示目标用户的 ID,即当前用户想要关注关注的目标对象。 - `isFollow`: 布尔型标志位,表示是否执行“关注”动作 (`true`) 或者“关注”动作 (`false`)。 2. **获当前登录用户的ID** ```java Long userId = UserHolder.getUser().getId(); ``` - 使用了一个静态工具类 `UserHolder` 来获当前请求上下文中的用户信息。 - 其中 `.getUser()` 返回的是当前登录用户实体,`.getId()` 则提其唯一标识符(通常为主键 ID)。 3. **构建 Redis 键名** ```java String key = "follows:" + userId; ``` - 创建了一个特定格式的 Redis Key,例如 `"follows:10086"`,其中 `userId` 是动态变化的部分。 - 该 Key 将作为 Redis 中 Set 集合的索引,用于保存某用户的所有已关注用户 ID。 4. **分支判断 —— 关注 vs. 关注** ##### (1)如果选择“关注” ```java if (isFollow) { // 新增一条关注记录到数据库 Follow follow = new Follow(); follow.setUserId(userId); // 设置发起者的用户ID follow.setFollowUserId(followUserId); // 设置被关注者的用户ID boolean isSuccess = save(follow); // 执行持久化操作 if (isSuccess) { // 同步更新到 Redis 的 Set 集合中 stringRedisTemplate.opsForSet().add(key, followUserId.toString()); } } ``` - **创建关注实体** 实例化一个新的 `Follow` 对象,并为其赋值两个键属性:`userId` 和 `followUserId`。 - **保存至数据库** 调用了 `save(Follow)` 方法将这条新纪录插入到数据库表中。如果保存成功,则进一步同步数据到 Redis 缓存。 - **添加到 Redis** 使用 `opsForSet().add(...)` 方法向指定的 Redis Key 添加新的元素(这里是目标用户的 ID)。这一步保证了缓存的一致性。 ##### (2)如果选择“关注” ```java else { // 删除对应的关注记录 boolean isSuccess = remove(new QueryWrapper<Follow>() .eq("user_id", userId).eq("follow_user_id", followUserId)); if (isSuccess) { // 同步删除 Redis 中的相条目 stringRedisTemplate.opsForSet().remove(key, followUserId.toString()); } } ``` - **条件查询删除** 构建了一个基于 MyBatis Plus 的 `QueryWrapper` 查询包装器,过滤条件包括 `user_id=userId` 和 `follow_user_id=followUserId`。然后将其传递给 `remove(QueryWrapper)` 方法尝试删除符合条件的记录。 - **从 Redis 移除** 若删除成功,则通过 `opsForSet().remove(...)` 方法将目标用户 ID 从 Redis 的 Set 集合中移除,同样保持缓存一致性。 5. **返回结果** ```java return Result.ok(); ``` - 最终无论关注还是关注操作都完成了之后,都会返回统一的结果对象 `Result.ok()`,表明此次调用正常结束。 --- ### 总结 这段代码的主要职责在于实现用户的“关注关注”的核心业务流程。它结合了数据库操作和 Redis 缓存两部分内容,确保高性能的同时也维护了两者间的数据一致性。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值