仿牛客网项目---关注模块的实现

本篇文章是关于我的项目的关注模块的开发。

关注模块的开发实现了用户之间的关注功能和关注列表的展示。通过使用相应的服务类处理关注和取消关注操作,并利用用户服务类获取用户信息,实现了关注功能的存储和查询。同时,通过触发关注事件,实现了关注操作的异步处理。在控制器类中,处理了关注和取消关注的请求,并展示了用户关注的人列表和粉丝列表。该模块的开发使得关注功能具备了高效、可靠和可扩展的特性,为用户之间的关联和互动提供了支持。

我们先来写RedisKeyUtil这个文件。

上篇文章其实已经写过这个了,里面也写了关注的数据放在Redis中,这里就不再赘述。

然后写service层。

@Service
public class FollowService implements CommunityConstant {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate UserService userService;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);}// 查询当前用户是否已关注该实体public boolean hasFollowed(int userId, int entityType, int entityId) {String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;}// 查询某用户关注的人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;}}

这段代码是一个名为FollowService的服务类,用于处理关注相关的操作。它通过注入RedisTemplateUserService来处理关注逻辑和用户信息的获取。

该服务类提供了一系列方法来处理关注操作,包括关注用户、取消关注、查询关注数量、查询粉丝数量、查询是否已关注、查询关注的用户列表和查询粉丝列表等功能。

在关注和取消关注的方法中,通过使用SessionCallbackmulti()方法,实现了将多个Redis操作放入一个事务中,保证了操作的原子性。

在查询关注的用户列表和粉丝列表的方法中,通过使用opsForZSet().reverseRange()方法,从Redis的有序集合中按照分数逆序查询指定范围的元素,并将结果封装成Map对象,包含用户信息和关注时间。

整个服务类通过使用RedisTemplate提供的方法,操作Redis中的数据,实现了关注功能的存储和查询。

该服务类的设计使得关注模块的操作实现了高效、可靠和可扩展的特性,同时通过依赖注入的方式,提高了代码的灵活性和可维护性。

最后写controller层。

@Controller
public class FollowController implements CommunityConstant {@Autowiredprivate FollowService followService;@Autowiredprivate HostHolder hostHolder;@Autowiredprivate UserService userService;@Autowiredprivate EventProducer eventProducer;@RequestMapping(path = "/follow", method = RequestMethod.POST)@ResponseBodypublic String follow(int entityType, int entityId) {User user = hostHolder.getUser();followService.follow(user.getId(), entityType, entityId);// 触发关注事件Event event = new Event().setTopic(TOPIC_FOLLOW).setUserId(hostHolder.getUser().getId()).setEntityType(entityType).setEntityId(entityId).setEntityUserId(entityId);eventProducer.fireEvent(event);return CommunityUtil.getJSONString(0, "已关注!");}@RequestMapping(path = "/unfollow", method = RequestMethod.POST)@ResponseBodypublic String unfollow(int entityType, int entityId) {User user = hostHolder.getUser();followService.unfollow(user.getId(), entityType, entityId);return CommunityUtil.getJSONString(0, "已取消关注!");}@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);return "/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);}}

上面这段代码是一个名为FollowController的控制器类,用于处理关注相关的请求。它通过注入FollowServiceUserServiceHostHolderEventProducer来实现关注功能和获取用户信息。

该控制器类提供了关注和取消关注的请求处理方法,其中:

  • follow()方法用于处理关注请求。它获取当前登录用户信息,调用followServicefollow()方法进行关注操作,并触发关注事件。
  • unfollow()方法用于处理取消关注请求。它获取当前登录用户信息,调用followServiceunfollow()方法进行取消关注操作。
  • getFollowees()方法用于获取用户关注的人列表。它根据用户ID获取用户信息,设置分页信息,调用followServicefindFollowees()方法获取关注的人列表,并将结果封装到模型中。
  • getFollowers()方法用于获取用户的粉丝列表。它根据用户ID获取用户信息,设置分页信息,调用followServicefindFollowers()方法获取粉丝列表,并将结果封装到模型中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软考】设计模式之访问者模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. java示例5.1 喂动物5.1.1 抽象访问者5.1.2 具体访问者5.1.3 抽象元素5.1.4 具体元素5.1.5 对象结构5.1.6 客户端类5.1.7 结果示例 5.2 超市销售系统5.2.1 业务场景5.2.2 业务需求类图5.2.3 抽象访问者5.2.4 具体访问者5.2.5 抽象元素…

前端面试拼图-原理源码

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1. JS内存泄漏如何检测&#xff1f;场景有哪些? 1.1 垃圾回收 GC 垃圾回收是一种自动管理内存的机制&#xff0c;它负责在运行时跟踪内存的分配和使用情况&#xff0c;并在不再需要的对象…

理解CAE

用于自监督表示学习的上下文自动编码器 摘要 我们提出了一种新的掩模图像建模(MIM)方法&#xff0c;上下文自编码器(CAE)&#xff0c;用于自监督表示预训练。我们通过在编码的表示空间中进行预测来预训练编码器。预训练任务包括两个任务:掩模表示预测—预测掩模块的表示&…

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

C及C++每日练习(2)

1.选择&#xff1a; 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A.%-30.4e B.%4.30e C.%-30.4f D.%-4.30 在上一篇文章中&#xff0c;提到了…

变老特效哪个app可以拍?深入探索变老效果的应用

随着科技的进步和智能手机的普及&#xff0c;各种摄影应用如雨后春笋般涌现&#xff0c;为我们提供了前所未有的创意拍摄体验。其中&#xff0c;变老特效因其独特的魅力&#xff0c;吸引了众多用户的关注。这种特效能够让我们在短时间内看到自己老去的模样&#xff0c;既有趣又…

JavaWeb HTTP 请求头、请求体、响应头、响应体、响应状态码

J2EE&#xff08;Java 2 Platform Enterprise Edition&#xff09;是指“Java 2企业版”&#xff0c;B/S模式开发Web应用就是J2EE最核心的功能。 Web是全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏览器访问的网站。 在日常的生活中&#xff0c;经常会使用…

强大的ps 命令 -o 自定义输出内容选项

强大的ps 命令 -o 自定义输出内容选项 1、ps命令介绍和作用2、问题描述 1、ps命令介绍和作用 ps 是一个 Unix 和类 Unix 操作系统中常用的命令&#xff0c;用于显示当前运行的进程信息。ps 命令的作用包括&#xff1a; 查看进程信息&#xff1a; ps 命令可以列出当前系统中正…

数据结构之顺序表及其实现!

目录 ​编辑 1. 顺序表的概念及结构 2. 接口的实现 2.1 顺序表的初始化 2.2 检查顺序表容量是否已满 2.3 顺序表的尾插 ​编辑 2.4 顺序表的尾删 2.5 顺序表的头插 2.6 顺序表的头删 2.7 顺序表在pos位置插入 2.8 顺序表在pos位置删除 2.9 顺序表的查找 2.10 顺…

考研数学——高数:多元函数微分法及其应用

因为复习阶段全篇很细节的写下来一来比较费时间&#xff0c;二容易导致为了记笔记而记。 接下来的内容只会保留上课中比较有意义的地方&#xff0c;以及有自己助于理解的想法 全微分 助记&#xff1a; 证明是否可微&#xff0c;首先判断两个偏导数是否存在&#xff0c;不存在则…

中文版国产Figma简单好上手

在过去的两年里&#xff0c;国内外协同办公室发展迅速。一方面&#xff0c;它是由突如其来的疫情推动的&#xff0c;另一方面&#xff0c;它是科学技术不断进步的必然结果。在市场的推动下&#xff0c;市场上出现了越来越多的协同办公软件&#xff0c;使工作场所的工作更加高效…

插入排序和归并排序

插入排序&#xff0c;Insertion Sort. 给出伪代码 for i 1,2,...,n-1Insert A[i] into Sorted array A[0:i-1]by swaping down to the correct position. 冒泡排序 冒泡排序就是一种插入排序算法。 i ← 1 while i < length(A)j ← iwhile j > 0 and A[j-1] > A…

CorelDRAW2024专业级图形设计矢量图形设计软件

CorelDRAW2024是一款功能强大的矢量图形设计软件&#xff0c;适用于专业级图形设计作品的设计师和创作者。它提供了智能对象、布局、插图和模板等功能&#xff0c;可以帮助用户快速创建高质量的设计作品。 这款软件的用户界面直观且易于使用&#xff0c;允许用户快速访问和管理…

184基于matlab的相关向量机(RVM)回归和分类算法

基于matlab的相关向量机&#xff08;RVM&#xff09;回归和分类算法。该算法基于贝叶斯稀疏核⽅法&#xff0c;避免了支持向量机&#xff08;SVM&#xff09;的主要局限性。RVM关键是为每个权参数 都引入一个单独的超参数 &#xff0c;而不是一个共享超参数。程序已调通&#x…

力扣hot100:42.接雨水(双指针/动态规划/贪心)

什么时候能用双指针&#xff1f; &#xff08;1&#xff09;对撞指针&#xff1a; ①两数和问题中可以使用双指针&#xff0c;先将两数和升序排序&#xff0c;可以发现规律&#xff0c;如果当前两数和大于target&#xff0c;则右指针向左走。 ②接雨水问题中&#xff0c;左边最…

【Web】浅聊JDBC的SPI机制是怎么实现的——DriverManager

目录 前言 分析 前言 【Web】浅浅地聊JDBC java.sql.Driver的SPI后门-CSDN博客 上篇文章我们做到了知其然&#xff0c;知道了JDBC有SPI机制&#xff0c;并且可以利用其Driver后门 这篇文章希望可以做到知其所以然&#xff0c;对JDBC的SPI机制的来源做到心里有数 分析 先是…

Python 弱引用全解析:深入探讨对象引用机制!

目录 前言 弱引用的概述 弱引用的原理 使用 WeakRef 类创建弱引用 使用 WeakValueDictionary 类创建弱引用字典 实际应用场景 1. 解决循环引用问题 2. 对象缓存 总结 前言 在Python编程中&#xff0c;弱引用&#xff08;Weak Reference&#xff09;是一种特殊的引用方式…

(文末送书)《低代码平台开发实践:基于React》

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&am…

PCM会重塑汽车OTA格局吗(2)

目录 1.概述 2. PCM技术视角下的OTA 3.小结 1.概述 上一篇文章&#xff0c;我们着重讲解了OTA的概述内容&#xff0c;和意法半导体推出的跨域融合MCU的四大特征&#xff0c;其中就包含了OTA技术。 他们针对OTA做了比较创新的设计&#xff0c;在总的可用memory容量不变情况…

2024最新Android开发面试解答,学海无涯

一个程序员&#xff0c;如果不想35 岁被淘汰&#xff0c;请把它当成一种信仰&#xff01; 25岁&#xff0c;一个北漂程序员&#xff0c;入职三年&#xff0c;Android中级工程师&#xff0c;月薪15k&#xff0c;965的工作经常干成996&#xff0c;比起老家的同龄人&#xff0c;我…