好友关注
1 好友关注-关注和取消关注
针对用户的操作:可以对用户进行关注和取消关注功能。
实现思路:
需求:基于该表数据结构,实现两个接口:
- 关注和取关接口
- 判断是否关注的接口
关注是User之间的关系,是博主与粉丝的关系,数据库中有一张follow表来标示。其字段为id -user_id-follow_id=create_time
FollowController
//关注或取消关注
@PutMapping("/{id}/{isFollow}")
public Result follow(@PathVariable("id") Long followUserId, @PathVariable("isFollow") Boolean isFollow) {
return followService.follow(followUserId, isFollow);
}
//判断是否已经关注
@GetMapping("/or/not/{id}")
public Result isFollow(@PathVariable("id") Long followUserId) {
return followService.isFollow(followUserId);
}
FollowService
@Override
public Result isFollow(Long followUserId) {
// 1.获取登录用户
Long userId = UserHolder.getUser().getId();
// 2.查询是否关注 select count(*) from tb_follow where user_id = ? and follow_user_id = ?
Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();
// 3.判断
return Result.ok(count > 0);
}
@Override
public Result follow(Long followUserId, Boolean isFollow) {
// 1.获取登录用户
Long userId = UserHolder.getUser().getId();
// 1.判断到底是关注还是取关
if (isFollow) {
// 2.关注,新增数据
Follow follow = new Follow();
follow.setUserId(userId);
follow.setFollowUserId(followUserId);
boolean isSuccess = save(follow);
} else {
// 3.取关,删除 delete from tb_follow where user_id = ? and follow_user_id = ?
remove(new QueryWrapper<Follow>()
.eq("user_id", userId).eq("follow_user_id", followUserId));
}
return Result.ok();
}
2 好友关注-共同关注
想要去看共同关注的好友,需要首先进入到这个页面,这个页面会发起两个请求
1、去查询用户的详情
2、去查询用户的笔记
以上两个功能和共同关注没有什么关系,大家可以自行将笔记中的代码拷贝到idea中就可以实现这两个功能了,我们的重点在于共同关注功能。
// UserController 根据id查询用户
@GetMapping("/{id}")
public Result queryUserById(@PathVariable("id") Long userId){
// 查询详情
User user = userService.getById(userId);
if (user == null) {
return Result.ok();
}
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) {
// 根据用户查询
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);
}
接下来我们来看看共同关注如何实现:
需求:利用Redis中恰当的数据结构,实现共同关注功能。在博主个人页面展示出当前用户与博主的共同关注呢。
当然是使用我们之前学习过的set集合,在set集合中,有交集并集补集的api,我们可以把两人的关注的人分别放入到一个set集合中,然后再通过api去查看这两个set集合中的交集数据。
我们先来改造当前的关注列表
改造原因是因为我们需要在用户关注了某位用户后,需要将数据放入到set集合中,方便后续进行共同关注,同时当取消关注时,也需要从set集合中进行删除
FollowServiceImpl
@Override
public Result follow(Long followUserId, Boolean isFollow) {
// 1.获取登录用户
Long userId = UserHolder.getUser().getId();
// 1.判断到底是关注还是取关
String followKey= RedisConstants.FOLLOW_KEY+userId;
if (isFollow) {
// 2.关注,新增数据
Follow follow = new Follow();
follow.setUserId(userId);
follow.setFollowUserId(followUserId);
boolean isSuccess = save(follow);
//把用户放入到好友列表中redis
redisTemplate.opsForSet().add(followKey,followUserId);
} else {
// 3.取关,删除 delete from tb_follow where user_id = ? and follow_user_id = ?
remove(new QueryWrapper<Follow>()
.eq("user_id", userId).eq("follow_user_id", followUserId));
//把用户从好友列表中移出redis
redisTemplate.opsForSet().remove(followKey,followUserId);
}
return Result.ok();
}
具体的关注代码:
FollowServiceImpl
@Override
public Result followCommon(int id) {
// 1.获取登录用户
Long userId = UserHolder.getUser().getId();
//2.使用redis的set的求交集的命令查看两个集合里面的共同好友
String myKey = RedisConstants.FOLLOW_KEY+userId;
String commonKey = RedisConstants.FOLLOW_KEY+id;
Set<Long> idSet = redisTemplate.opsForSet().intersect(myKey, commonKey);
if(ObjectUtil.isEmpty(idSet)){
return Result.ok(Collections.emptyList());
}
//3.根据查询出来的用户id生成userDTO。放入Result集合返回。
List<UserDTO> userDTOs = new ArrayList<>(idSet.size());
List<User> users = userService.listByIds(idSet);
if(ObjectUtil.isNotEmpty(users)){
for(User user : users){
userDTOs.add(BeanUtil.copyProperties(user,UserDTO.class));
}
}
return Result.ok(userDTOs);
}
附加:当不使用redis中的set还可以用以下方法
Long loginId = UserHolder.getUserDTO().getId();
//先根据当前用户的用户id查出关注列表
List<Follow> follows1 = query().eq("user_id", loginId).list();
//再根据别的用户的id查出其关注的列表
List<Follow> follows2 = query().eq("user_id", id).list();
//取出其关注的共同人的follow_id
List<String> list1=new ArrayList();
List<String> list2=new ArrayList();
for (Follow follow:follows1){
list1.add(follow.getFollowUserId().toString());
}
for (Follow follow:follows2){
list2.add(follow.getFollowUserId().toString());
}
//流式传输求交集
List<String> collect = list1.stream()
.filter(list2::contains)
.collect(Collectors.toList());
//使用集合的retain求交集
list1.retainAll(list2);//这个时间复杂度为O1 stream时间复杂度为On
List<User> users = userService.query().in("id", collect).list();//或list
List<UserDTO> UserDTOs=new ArrayList<>();
for (User user:users){
//使用工具类隐藏user的关键信息
UserDTOs.add(BeanUtil.copyProperties(user, UserDTO.class));
}
return new ressult.ok(UserDTOs);