本篇文章是关于我的项目的关注模块的开发。
关注模块的开发实现了用户之间的关注功能和关注列表的展示。通过使用相应的服务类处理关注和取消关注操作,并利用用户服务类获取用户信息,实现了关注功能的存储和查询。同时,通过触发关注事件,实现了关注操作的异步处理。在控制器类中,处理了关注和取消关注的请求,并展示了用户关注的人列表和粉丝列表。该模块的开发使得关注功能具备了高效、可靠和可扩展的特性,为用户之间的关联和互动提供了支持。
我们先来写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
的服务类,用于处理关注相关的操作。它通过注入RedisTemplate
和UserService
来处理关注逻辑和用户信息的获取。
该服务类提供了一系列方法来处理关注操作,包括关注用户、取消关注、查询关注数量、查询粉丝数量、查询是否已关注、查询关注的用户列表和查询粉丝列表等功能。
在关注和取消关注的方法中,通过使用SessionCallback
和multi()
方法,实现了将多个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
的控制器类,用于处理关注相关的请求。它通过注入FollowService
、UserService
、HostHolder
和EventProducer
来实现关注功能和获取用户信息。
该控制器类提供了关注和取消关注的请求处理方法,其中:
follow()
方法用于处理关注请求。它获取当前登录用户信息,调用followService
的follow()
方法进行关注操作,并触发关注事件。unfollow()
方法用于处理取消关注请求。它获取当前登录用户信息,调用followService
的unfollow()
方法进行取消关注操作。getFollowees()
方法用于获取用户关注的人列表。它根据用户ID获取用户信息,设置分页信息,调用followService
的findFollowees()
方法获取关注的人列表,并将结果封装到模型中。getFollowers()
方法用于获取用户的粉丝列表。它根据用户ID获取用户信息,设置分页信息,调用followService
的findFollowers()
方法获取粉丝列表,并将结果封装到模型中。