好友關注
數據模型
數據庫中的tb_follow
記錄博主與粉絲的關系
tb_follow
表對應的實體類
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_follow")
public class Follow implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 用戶id*/private Long userId;/*** 關聯的用戶id*/private Long followUserId;/*** 創建時間*/private LocalDateTime createTime;
}
是否關注/關注/取關
需求: 在探店圖文的詳情頁面中,可以查看用戶是否關注了筆記博主,用戶也可以手動關注/取消關注
發布筆記的作者
第一步: 在FollowController
層中編寫判斷是否關注
和關注/取關
的兩個方法
@RestController
@RequestMapping("/follow")
public class FollowController {@Resourceprivate IFollowService followService;// 判斷當前用戶是否關注了筆記博主,參數是發布筆記的博主Id@GetMapping("/or/not/{id}")public Result isFollow(@PathVariable("id") Long followUserId) {return followService.isFollow(followUserId);}// 實現取關/關注,參數是發布筆記的博主Id以及是否關注(true表示關注,false表示取關)@PutMapping("/{id}/{isFollow}")public Result follow(@PathVariable("id") Long followUserId, @PathVariable("isFollow") Boolean isFellow) {return followService.follow(followUserId,isFellow);}
}
第二步: 在FellowServiceImp
中來編寫具體的業務邏輯
判斷當前用戶是否關注了筆記博主
: 將請求參數攜帶的發布筆記的博主Id和當前登陸的用戶Id
作為條件去數據庫中查詢是否有對應的記錄關注和取消關注
: 請求參數中的true(關注)/fasle(取關)
,關注是將用戶和博主的關聯信息保存到數據庫,取關即將他們的關聯信息從數據庫移除,避免堆積數據
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {@Overridepublic Result isFollow(Long followUserId) {// 獲取當前登錄的用戶IdLong userId = UserHolder.getUser().getId();LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();// 查詢tb_follow表判斷當前用戶是否關注了該筆記的博主queryWrapper.eq(Follow::getUserId, userId).eq(Follow::getFollowUserId, followUserId);// 沒必要查詢出具體數據,只需要判斷數據存不存在即可//select count(*) from tb_follow where user_id = ? and follow_user_id = ?int count = this.count(queryWrapper);return Result.ok(count > 0);}@Overridepublic Result follow(Long followUserId, Boolean isFellow) {// 獲取當前登錄的用戶IdLong userId = UserHolder.getUser().getId();// 判斷用戶是要關注還是取關,true表示關注,false表示取關if (isFellow) {// 關注則將用戶和筆記博主的關聯信息保存到數據庫Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);save(follow);} else {// 取關則將用戶和博主的關聯信息從數據庫中移除,避免數據庫中堆積大量數據//delete from tb_follow where user_id = ? and follow_user_id = ?LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Follow::getUserId, userId).eq(Follow::getFollowUserId, followUserId);remove(queryWrapper);}return Result.ok();}
}
共同關注
需求:當我們點擊博主用戶頭像時進入到詳情頁,可以查看到博主發布的筆記
以及用戶和博主的好友共同關注列表
第一步: 在UserController
中編寫查詢博主信息
的方法
@GetMapping("/{id}")
public Result queryUserById(@PathVariable("id") Long userId) {// 查詢詳情User user = userService.getById(userId);if (user == null) {// 查不到返回空return Result.ok();}// 查到則轉為userDTO對象UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);// 返回查詢到的數據return Result.ok(userDTO);
}
第二步: 在BlogController
中編寫分頁查詢博主發布的所有筆記
的方法
// 根據博主id查詢博主的探店筆記
@GetMapping("/of/user")
public Result queryBlogByUserId(@RequestParam(value = "current", defaultValue = "1") Integer current, @RequestParam("id") Long id) {LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();// 根據博主id查詢用戶信息queryWrapper.eq(Blog::getUserId, id);Page<Blog> pageInfo = new Page<>(current, SystemConstants.MAX_PAGE_SIZE);blogService.page(pageInfo, queryWrapper);// 獲取查詢到的所有用戶信息List<Blog> records = pageInfo.getRecords();return Result.ok(records);
}// 根據博主id查詢博主的探店筆記
@GetMapping("/of/user")
public Result queryBlogByUserId(@RequestParam(value = "current", defaultValue = "1") Integer current,@RequestParam("id") Long id) {// 根據博主id查詢用戶信息Page<Blog> page = blogService.query().eq("user_id", id).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));// 獲取查詢到的所有用戶信息List<Blog> records = page.getRecords();return Result.ok(records);
}
第三步: 修改關注/取關
的邏輯,以follows:userId
作為Set集合的Key,存放當前用戶關注的所有博主Id
關注/取關
: 將關注的博主Id放到當前登陸用戶關注的Set集合中,取關就是將關注的博主Id從當前登陸用戶的Set集合中移除共同關注
:通過SINTER key1 key2
查詢登陸用戶的Set集合和其關注博主的Set集合中元素的交集
@Resource
private StringRedisTemplate stringRedisTemplate;
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {@Overridepublic Result follow(Long followUserId, Boolean isFellow) {// 獲取當前登錄的用戶IdLong userId = UserHolder.getUser().getId();String key = "follows:" + userId;// 判斷用戶是要關注還是取關,true表示關注,false表示取關if (isFellow) {// 關注則將用戶和筆記博主的關聯信息保存到數據庫Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);boolean iSsuccess = save(follow);// 如果更新成功則將關聯信息也寫入Redis,key是當前的用戶id,value就是關注的博主idif (iSsuccess) {stringRedisTemplate.opsForSet().add(key, followUserId.toString());}} else {// 取關則將用戶和博主的關聯信息從數據庫中移除,避免數據庫中堆積大量數據//delete from tb_follow where user_id = ? and follow_user_id = ?LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Follow::getUserId, userId).eq(Follow::getFollowUserId, followUserId);boolean iSsuccess = remove(queryWrapper);// 如果取關成功則將關聯的博主Id從當前登陸用戶的set集合中移除if (iSsuccess){stringRedisTemplate.opsForSet().remove(key,followUserId.toString());}}return Result.ok();}
}
第四步: 編寫控制器方法,查看登陸用戶和其關注博主的好友共同關注列表
@GetMapping("/common/{id}")
public Result followCommons(@PathVariable Long id){return followService.followCommons(id);
}
@Resource
private IUserService userService;
@Override
public Result followCommons(Long id) {// 獲取當前登陸用戶的idLong userId = UserHolder.getUser().getId();// // 獲取當前登陸對應的set集合的keyString key1 = "follows:" + userId;// 獲取當前登陸用戶關注博主所對應的set集合的keyString key2 = "follows:" + id;// 對當前登陸用戶和其關注博主的Set集合取交集Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key1, key2);// 無交集就返回個空的List集合if (intersect == null || intersect.isEmpty()) {return Result.ok(Collections.emptyList());}// 將String類型的用戶id轉化為Long類型的用戶id然后使用List集合收集List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());// 根據ids集合中的用戶id去數據庫中查詢登陸用戶和博主共同關注的用戶信息并封裝成UserDto對象,最后存入List集合中返回List<UserDTO> userDTOS = userService.listByIds(ids).stream().map(user ->BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(userDTOS);
}