实现关注、取消关注

  • value的数据类型时zset,有序集合,按照关注的时间排序
followee:userId:entityType -> zset(entityId,now) 某个用户关注的实体(实体包括帖子、评论、用户),按照实体分别存
follower:entityType:entityId -> zset(userId,now) 某个实体拥有的粉丝(实体包括帖子、评论、用户)
  • 这个功能时异步请求

1、RedisKeyUtil

    private static final String PREFIX_FOLLOWEE = "followee";private static final String PREFIX_FOLLOWER = "follower";// 某个用户关注的实体(实体包括帖子、用户)// followee:userId:entityType -> zset(entityId,now)public static String getFolloweeKey(int userId, int entityType) {return PREFIX_FOLLOWEE + SPLIT + userId + SPLIT + entityType;}// 某个实体拥有的粉丝(实体包括帖子、用户)// follower:entityType:entityId -> zset(userId,now)public static String getFollowerKey(int entityType, int entityId) {return PREFIX_FOLLOWER + SPLIT + entityType + SPLIT + entityId;}

2、FollowService

@Service
public class FollowService {@Autowiredprivate RedisTemplate redisTemplate;public void follow(int userId, int entityType, int entityId) {redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations operations) throws DataAccessException {// 某个用户关注的实体String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);// 某个实体拥有的粉丝String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);operations.multi();operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());return operations.exec();}});}public void unfollow(int userId, int entityType, int entityId) {redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations operations) throws DataAccessException {String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);operations.multi();operations.opsForZSet().remove(followeeKey, entityId);operations.opsForZSet().remove(followerKey, userId);return operations.exec();}});}// 查询关注的实体的数量public long findFolloweeCount(int userId, int entityType) {String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);return redisTemplate.opsForZSet().zCard(followeeKey);}// 查询实体的粉丝的数量public long findFollowerCount(int entityType, int entityId){String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);return redisTemplate.opsForZSet().zCard(followerKey);}// 查询当前用户是否已关注该实体(该用户对这类实体的id有一个清单zset)public boolean hasFollowed(int userId, int entityType, int entityId) {String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;}}

3、profile.js

$(function(){$(".follow-btn").click(follow);
});function follow() {var btn = this;if($(btn).hasClass("btn-info")) {// 关注TA$.post(CONTEXT_PATH + "/follow",{"entityType":3,"entityId":$(btn).prev().val()},function(data) {data = $.parseJSON(data);if(data.code == 0) {window.location.reload();} else {alert(data.msg);}});// $(btn).text("已关注").removeClass("btn-info").addClass("btn-secondary");} else {// 取消关注$.post(CONTEXT_PATH + "/unfollow",{"entityType":3,"entityId":$(btn).prev().val()},function(data) {data = $.parseJSON(data);if(data.code == 0) {window.location.reload();} else {alert(data.msg);}});//$(btn).text("关注TA").removeClass("btn-secondary").addClass("btn-info");}
}

关注列表和粉丝列表

1、FollowService

    // 查询某用户关注的人public List<Map<String, Object>> findFollowees(int userId, int offset, int limit) {String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);if (targetIds == null) {return null;}List<Map<String, Object>> list = new ArrayList<>();for (Integer targetId : targetIds) {Map<String, Object> map = new HashMap<>();User user = userService.findUserById(targetId);map.put("user", user);Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);map.put("followTime", new Date(score.longValue()));list.add(map);}return list;}// 查询某用户的粉丝public List<Map<String, Object>> findFollowers(int userId, int offset, int limit) {String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit + 1);if (targetIds == null) {return null;}List<Map<String, Object>> list = new ArrayList<>();for (Integer targetId : targetIds) {Map<String, Object> map = new HashMap<>();User user = userService.findUserById(targetId);map.put("user", user);Double score = redisTemplate.opsForZSet().score(followerKey, targetId);map.put("followTime", new Date(score.longValue()));list.add(map);}return list;}

2、FollowController

    @RequestMapping(path = "/followees/{userId}", method = RequestMethod.GET)public String getFollowees(@PathVariable("userId") int userId, Page page, Model model) {User user = userService.findUserById(userId);if (user == null) {throw new RuntimeException("该用户不存在!");}model.addAttribute("user", user);page.setLimit(5);page.setPath("/followees/" + userId);page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER));List<Map<String, Object>> userList = followService.findFollowees(userId, page.getOffset(), page.getLimit());if (userList != null) {for (Map<String, Object> map : userList) {User u = (User) map.get("user");map.put("hasFollowed", hasFollowed(u.getId()));}}model.addAttribute("users", userList);// 里面存了user、followTime、hasFollowedreturn "/site/followee";}@RequestMapping(path = "/followers/{userId}", method = RequestMethod.GET)public String getFollowers(@PathVariable("userId") int userId, Page page, Model model) {User user = userService.findUserById(userId);if (user == null) {throw new RuntimeException("该用户不存在!");}model.addAttribute("user", user);page.setLimit(5);page.setPath("/followers/" + userId);page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId));List<Map<String, Object>> userList = followService.findFollowers(userId, page.getOffset(), page.getLimit());if (userList != null) {for (Map<String, Object> map : userList) {User u = (User) map.get("user");map.put("hasFollowed", hasFollowed(u.getId()));}}model.addAttribute("users", userList);return "/site/follower";}private boolean hasFollowed(int userId) {if (hostHolder.getUser() == null) {return false;}return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);}

11、Redis实现关注、取消关注以及关注和粉丝列表相关推荐

  1. 4.3 关注、取消关注和关注、粉丝列表

    文章目录 设计Redis的key和Value 开发关注.取关的业务 开发Controller,接受关注取关请求 修改主页的js 增加获取关注,粉丝数量,是否关注的业务 主页的Controller 修改 ...

  2. 微信公众平台开发教程Java版(六) 事件处理(菜单点击/关注/取消关注)

    前言: 事件处理是非常重要的,这一章讲讲常见的事件处理 1.关注/取消关注 2.菜单点击 事件类型介绍: 在微信中有事件请求是消息请求中的一种.请求类型为:event 而event事件类型又分多种事件 ...

  3. 菜单点击/关注/取消关注

    事件处理是非常重要的,这一章讲讲常见的事件处理 1.关注/取消关注 2.菜单点击 事件类型介绍: 在微信中有事件请求是消息请求中的一种.请求类型为:event 而event事件类型又分多种事件类型,具 ...

  4. 不同于其他写脚本的同类文章,使用软件取消赞和关注收藏

    取消某音关注喜欢点赞 在网上找了一堆的教程还下了不知道怎么回事的软件,不是求打赏加群,就是无脑限速,真受不了,于是想了个主意让手机完成几个固定动作就可以完成这些操作 吐槽完了,然后我开始说方法 1.我 ...

  5. 微信公众号关注/取消关注事件推送开发记录

    一.奉上官方文档 关注/取消关注事件 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/offiaccount/Message_Managem ...

  6. 根据微信公众号关注/取消关注事件,获取用户信息

    第一步:微信公众平台->基本配置->服务器配置->配置接收地址 第二步:接收微信服务器推送过来的事件 微信文档地址: 关注/取消关注事件 用户在关注与取消关注公众号时,微信会把这个事 ...

  7. 电商 关注 取消关注 人数+-

    case R.id.iv_focus_on: //关注.取消关注 if (TextUtils.isEmpty(token)) {//判断用户是否登录 未登录 去登录 Intent loginInten ...

  8. 微信公众号监听 关注/取消关注事件 消息接收与响应处理(比较细微)

    从官方文档可以看出,他做到了简简单单,但没有做到明明白白. 那么接下来我首先说下文中的url,很多人都不知道这个url,其实他就是 当这些正准备好之后,直接上代码 //微信推送事件 url@Reque ...

  9. Redis基于Set如何实现用户关注模型?

    为每个用户定义一个set,存储该用户关注的用户集合,集合存储用户的唯一标识id,有了用户的关注人信息后可以做以下几个操作: 相互关注:用集合里自己关注的人的id,去查找该用户的关注人集合,看自己是否在 ...

最新文章

  1. java 继承 意义_Java中继承,类的高级概念的知识点
  2. python 內建数据类型
  3. DataFactory连接MySQL数据库
  4. NYOJ 595 乱七八糟
  5. Spring 3.1缓存和@CacheEvict
  6. iPhone降价后销量惊人 库克本周将再度访华
  7. C# 获取COM控件注册状态,注册以及反注册COM控件
  8. 使用Python和Numpy进行波士顿房价预测任务(二)【深度学习入门_学习笔记】
  9. ffmpeg支持的扩展库有哪些
  10. 它!5 年代替狂卷的 CNN!
  11. C语言自学笔记(16)
  12. 常用软件自动安装,软件批量安装包升级版
  13. WHAT、HOW、WHY
  14. 菜鸟供应链实时数仓的架构演进及应用场景
  15. css的white-space属性:normal,nowrap,pre,pre-line和pre-wrap的区别?
  16. jsp_02JSP隐含对象
  17. 如何成为一名合格的数据产品经理?
  18. SAP-PP MRP再计划/重新计划
  19. MySQL/oracle服务器误删文件的恢复过程
  20. 文件传输协议——FTP概述

热门文章

  1. YOLOv5在无人机/遥感场景下做旋转目标检测时进行的适应性改建详解(踩坑记录)...
  2. t420i升级固态硬盘提升_系统迁移教程:升级SSD后笔记本性能提升两倍?浦科特M9P PLUS 1TB_固态硬盘...
  3. 正益工场推出移动政务新媒体平台
  4. 用matlab雷达基数据,matlab探地雷达数据处理软件
  5. 推荐3个iOS苹果手机上的epub小说阅读器
  6. python 版工作流设计
  7. IT 运维服务规范 | 资料
  8. IT基础环境运维服务
  9. pytest单元测试框架基本操作
  10. 【虚拟机】在Windows11上下载安装VMware虚拟机以及Ubuntu(Linux)详细操作