问答社区-关注列表、粉丝列表
需求:
业务层
- 查询某个用户关注的人,支持分页
- 查询某个用户的粉丝,支持分页
表现层
- 处理“查询关注的人”、“查询粉丝”请求
- 编写“查询关注的人”、“查询粉丝”模板
1、followService新增,查询粉丝列表、关注列表的方法,返回list
//查询某用户关注的人 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、controller处理“查询关注的人”、“查询粉丝”请求
//关注列表 @RequestMapping(value = "/followees/{userId}", method = RequestMethod.GET) public String getFollowees(@PathVariable("userId") int userId, Model model, Page page) { User user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("该用户不存在!"); } model.addAttribute("user", user); page.setLimit(7); page.setPath("/followees/" + userId); page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER)); List<Map<String, Object>> followees = followService.findFollowees(userId, page.getOffset(), page.getLimit()); if (followees != null) { for (Map<String, Object> map : followees) { User u = (User) map.get("user"); map.put("hasFollowed", hasFollowed(u.getId())); System.out.println(u.toString()); } } model.addAttribute("users", followees); return "/site/followee"; } //粉丝列表 @RequestMapping(value = "/followers/{userId}", method = RequestMethod.GET) public String getFollowers(@PathVariable("userId") int userId, Model model, Page page) { User user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("该用户不存在!"); } model.addAttribute("user", user); page.setLimit(7); page.setPath("/followers/" + userId); page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId)); List<Map<String, Object>> followers = followService.findFollowers(userId, page.getOffset(), page.getLimit()); if (followers != null) { for (Map<String, Object> map : followers) { User u = (User) map.get("user"); map.put("hasFollowed", hasFollowed(u.getId())); } } model.addAttribute("users", followers); return "/site/follower"; } private boolean hasFollowed(int userId) { if (hostHolder.getUser() == null) { return false; } return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId); }
3、表现层页面
<div class="position-relative"> <!-- 选项 --> <ul class="nav nav-tabs mb-3"> <li class="nav-item"> <a class="nav-link position-relative active" th:href="@{|/followees/${user.id}|}"> <i class="text-info" th:utext="${user.username}">Nowcoder</i> 关注的人</a> </li> <li class="nav-item"> <a class="nav-link position-relative" th:href="@{|/followers/${user.id}|}">关注 <i class="text-info" th:utext="${user.username}">Nowcoder</i> 的人</a> </li> </ul> <a th:href="@{|/user/profile/${user.id}|}" class="text-muted position-absolute rt-0">返回个人主页></a> </div> <!-- 关注列表 --> <ul class="list-unstyled"> <li class="media pb-3 pt-3 mb-3 border-bottom position-relative" th:each="map:${users}"> <a th:href="@{|/user/profile/${map.user.id}|}"> <img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle user-header" alt="用户头像" > </a> <div class="media-body"> <h6 class="mt-0 mb-3"> <span class="text-success" th:utext="${map.user.username}">落基山脉下的闲人</span> <span class="float-right text-muted font-size-12">关注于 <i th:text="${#dates.format(map.followTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-28 14:13:25</i></span> </h6> <div> <input type="hidden" id="entityId" th:value="${map.user.id}"> <button type="button" th:class="|btn ${map.hasFollowed?'btn-secondary':'btn-info'} btn-sm float-right follow-btn|" th:if="${loginUser!=null&&loginUser.id!=map.user.id}" th:text="${map.hasFollowed?'已关注':'关注TA'}">关注TA</button> </div> </div> </li> </ul>
总结:
简单说就是从Redis中把数据拿出来,通过里面的userid查询到每个用户,将用户放到hashmap中,再将返回list集合
当处理前端传过来的请求的时候,先进行判断,用户是否存在,在返回之前再判断是否关注了,接着再传递回模板