好友关注功能(共同关注与关注推送)

好友关注

1.关注和取关

/**
 * 关注或取关
 * @param followUserId
 * @param isFollow true:关注, false:取关
 * @return
 */
@Override
public Result follow(Long followUserId, Boolean isFollow) {
    // 1.得到当前用户id
    Long userId = UserHolder.getUser().getId();
    if(userId == null) {
        return Result.fail("未登录!");
    }
    // 判断关注或取关
    if(isFollow){
        // 2.关注,新增数据
        Follow follow = new Follow();
        follow.setUserId(userId);
        follow.setFollowUserId(followUserId);
        save(follow);
    }else{
        // 3.取关,删除数据
        remove(new QueryWrapper<Follow>()
                .eq("user_id", userId).eq("follow_user_id", followUserId));
    }
    return Result.ok();
}

/**
 * 判断是否关注
 * @param followUserId
 * @return
 */
@Override
public Result isFollow(Long followUserId) {
    // 1.获取当前用户id
    Long userId = UserHolder.getUser().getId();
    // 2.查询是否关注
    Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();
    // 3.判断
    boolean isFollow = count != null && count > 0;
    return Result.ok(isFollow);
}

2.共同关注

@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IUserService userService;
    /**
     * 关注或取关
     * @param followUserId
     * @param isFollow true:关注, false:取关
     * @return
     */
    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        // 1.得到当前用户id
        Long userId = UserHolder.getUser().getId();
        if(userId == null) {
            return Result.fail("未登录!");
        }
        // Redis中set的key
        String key = "follows:" + userId;
        // 判断关注或取关
        if(isFollow){
            // 2.关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
            boolean isSuccess = save(follow);
            if(isSuccess){
                // 把关注用户的id,放入Redis的set中 sadd key followedUserId
                stringRedisTemplate.opsForSet().add(key, followUserId.toString());
            }
        }else{
            // 3.取关,删除数据
            boolean isSuccess = remove(new QueryWrapper<Follow>()
                    .eq("user_id", userId).eq("follow_user_id", followUserId));
            if(isSuccess){
                // 把关注用户的id,在Redis的set中移除 srem key followedUserId
                stringRedisTemplate.opsForSet().remove(key, followUserId.toString());
            }
        }
        return Result.ok();
    }

    /**
     * 判断是否关注
     * @param followUserId
     * @return
     */
    @Override
    public Result isFollow(Long followUserId) {
        // 1.获取当前用户id
        Long userId = UserHolder.getUser().getId();
        // 2.查询是否关注
        // 2.1.先查Redis中的set
        String key = "follows:" + userId;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, followUserId.toString());
        if(isMember){
            return Result.ok(true);
        }
        // 2.2.后查DB
        Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();
        // 3.判断
        boolean isFollow = count != null && count > 0;
        if(isFollow){
            stringRedisTemplate.opsForSet().add(key, followUserId.toString());
        }
        return Result.ok(isFollow);
    }

    /**
     * 查询共同关注
     * @param id
     * @return
     */
    @Override
    public Result common(Long id) {
        // 1.获取当前用户id
        Long userId = UserHolder.getUser().getId();
        // 2.获取当前用户Redis中set的key
        String key1 = "follows:" + userId;
        // 3.获取目标用户Redis中set的key
        String key2 = "follows:" + id;
        // 4.查询共同集合
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key1, key2);
        if(intersect == null || intersect.isEmpty()){
            // 无交集
            return Result.ok(Collections.emptyList());
        }
        // 5.解析id集合
        List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        // 6.查询用户
        List<UserDTO> userDTOS = userService.listByIds(ids)
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        // 7.返回交集
        return Result.ok(userDTOS);
    }
}

3.关注推送

  1. 实现方式

  1. 分页问题

推送到粉丝收件箱
/**
 * 发布博客
 * @param blog
 * @return
 */
@Override
public Result saveBlog(Blog blog) {
    // 1.获取登录用户
    UserDTO user = UserHolder.getUser();
    blog.setUserId(user.getId());
    // 2.保存探店博文
    boolean isSave = save(blog);
    if(!isSave){
        return Result.fail("新增博文失败!");
    }
    // 3.查询博文作者的所有粉丝
    List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
    // 4.推送博文id给所有粉丝
    for (Follow follow : follows) {
        // 4.1.获取粉丝id
        Long userId = follow.getUserId();
        // 4.2.推送
        String key = "feed:" + userId;
        stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
    }
    // 5.返回博文id
    return Result.ok(blog.getId());
}

滚动分页查询收件箱

@Data
public class ScrollResult {
    // 分页结果列表
    private List<?> list;
    // 下次查询的最大时间戳
    private Long minTime;
    // 与上次查询最小值一样的个数
    private Integer offset;
}
/**
 * 查询关注用户的博客
 * @param max
 * @param offset
 * @return
 */
@GetMapping("/of/follow")
public Result queryBlogOfFollow(
        @RequestParam("lastId") Long max,
        @RequestParam(value = "offset", defaultValue = "0") Integer offset){
    return blogService.queryBlogOfFollow(max, offset);
}
/**
 * 查询关注用户的博客
 * @param max
 * @param offset
 * @return
 */
@Override
public Result queryBlogOfFollow(Long max, Integer offset) {
    // 1.获取当前用户
    Long userId = UserHolder.getUser().getId();
    // 2.查询当前用户的信箱 ZREVRANGEBYSCORE z1 Max Min LIMIT offset count
    String key = FEED_KEY + userId;
    Set<ZSetOperations.TypedTuple<String>> typedTuples =
            stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 2);
    // 非空判断
    if(typedTuples == null || typedTuples.isEmpty()){
        return Result.ok();
    }
    // 3.解析数据:BlogId, minTime, offset
    long minTime = 0;
    int nextOffset = 1;
    List<Long> ids = new ArrayList<>(typedTuples.size());
    for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
        // 3.1.获取id,加入集合
        ids.add(Long.valueOf(tuple.getValue()));
        // 3.2.获取分数,并统计下次查询的offset
        long time = tuple.getScore().longValue();
        if(time == minTime){
            nextOffset ++;
        }else{
            minTime = time;
            nextOffset = 1;
        }
    }
    // 4.根据id查询Blog(不能使用listByIds,'in'问题)
    String idStr = StrUtil.join(",", ids);
    List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id, " + idStr + ")").list()
            .stream().map(blog -> {
                queryBlogUser(blog);
                isBlogLiked(blog);
                return blog;
            })
            .collect(Collectors.toList());
    // 5.封装返回
    ScrollResult r = new ScrollResult();
    r.setList(blogs);
    r.setOffset(nextOffset);
    r.setMinTime(minTime);
    return Result.ok(r);
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值