文章目录
1. 关注与取关
1.1 需求分析
1.2 代码实现
首先我们实现关注和取关功能,再实现是否关注功能。
如何实现关注和取关功能呢?我们在页面点击关注按钮,页面会发送ajax请求将要关注或者取关的信息传递到服务端,关注传递的是true,取关传递的是false。同时,页面还将博主的id传递过来。接下来,我们只需要判断是关注还是取关,关注就将当前登录的用户信息保存到follow表,并将用户的信息保存到Set集合中,取关就只需要将Set集合和follow表中的数据删除即可。
为什么要将用户信息放入Set集合呢?因为我们接下去会开发共同关注功能,需要使用,因此提前设置,当然,我这是已经完成全部功能反过来写博客,当初第一次实现也没加入Set集合,后面需要再改也行。
followController.java
@PutMapping("/{id}/{isFollow}")
public Result follow(@PathVariable("id") Long followUserId,@PathVariable("isFollow") Boolean isFollow){
return followService.follow(followUserId,isFollow);
}
Service
//关注取关操作,followUserId是博主id
@Override
public Result follow(Long followUserId, Boolean isFollow) {
//1. 获取登录用户id
Long userId = UserHolder.getUser().getId();
String key = "follows:"+userId;
//2. 判断是否关注
if(isFollow){
//3. 关注,新增
Follow follow = new Follow();
follow.setUserId(userId);
follow.setFollowUserId(followUserId);
follow.setCreateTime(LocalDateTime.now());
boolean success = this.save(follow);
if(success){
//把用户关注的博主id放入redis的set集合,方便我们做共同关注的业务
redisTemplate.opsForSet().add(key,followUserId.toString());
}
}else {
//4. 取关,删除 delete from tb_follow where user_id = ? and follow_user_id=?
boolean success = remove(new QueryWrapper<Follow>().eq("user_id", userId)
.eq("follow_user_id", followUserId));
if(success){
redisTemplate.opsForSet().remove(key,followUserId.toString());
}
}
return Result.ok();
}
1.3 功能完善
接下来我们完成是否关注功能的开发,业务逻辑很简单,根据当前用户id和博主id查数据库,看看是否有相关数据,有就说明关注,反之则没关注
controller
@GetMapping("/or/not/{id}")
public Result isFollow(@PathVariable("id") Long followUserId){
return followService.isFollow(followUserId);
}
service
//是否关注
@Override
public Result isFollow(Long followUserId) {
//1. 获取登录用户id
Long userId = UserHolder.getUser().getId();
//查询是否关注 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();
//大于0就是true
return Result.ok(count>0);
}
2. 共同关注
2.1 需求分析
2.2 代码实现
分析一波,如何实现共同关注功能呢?还记得我们在实现关注与取关功能中将用户id作为key,将其关注的博主作为值添加到Set集合中嘛,这时,我们就可以将当前登录用户的id作为key查询出其关注的博主,再获取当前用户想查询某个博主的关注列表,两个集合取交集,不就可以查询出共同关注了吗。
如何获取交集呢?在redis基础操作中,我们讲到两个集合取交集是不是有一个intersect方法,调用该方法传递两个key就可以获取出交集。
controller
@GetMapping("/common/{id}")
public Result followCommons(@PathVariable("id") Long id){
return followService.followCommons(id);
}
sercice
@Override
public Result followCommons(Long id) {
//1. 获取当前用户id
Long userId = UserHolder.getUser().getId();
String key = "follows:"+userId;
String key2 = "follows:"+id;
//2. 求当前用户与查询用户的交集
Set<String> idSet = redisTemplate.opsForSet().intersect(key, key2);
//无交集返回空
if(idSet==null||idSet.isEmpty()){
return Result.ok(Collections.emptyList());
}
//3. 查询出的id为字符串,解析出id
List<Long> idList = idSet.stream().map(Long::valueOf).collect(Collectors.toList());
//4. 根据id查询用户,转成dto对象
List<UserDTO> userDTOS = userService.listByIds(idList)
.stream()
.map(user -> BeanUtil.copyProperties(user, UserDTO.class))
.collect(Collectors.toList());
//5. 返回dto对象
return Result.ok(userDTOS);
}
3. 关注推送
3.1 关注推送介绍
3.2 Feed流的实现方式
3.3 代码实现
@Override
public Result saveBlog(Blog blog) {
//1. 获取当前用户
UserDTO user = UserHolder.getUser();
//2. 新增博客信息
Long userId = user.getId();
blog.setUserId(userId);
boolean success = this.save(blog);
//3. 添加不成功就不推送
if(!success){
return Result.fail("添加博客失败");
}
//4 查询博主的所有粉丝
LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Follow::getFollowUserId,userId);
List<Follow> followList = followService.list(queryWrapper);
//5. 添加成功,推送
//5.1 获取粉丝id
for (Follow follow : followList) {
Long userId1 = follow.getId();
//5.2 推送
String key = FEED_KEY+ userId1;
stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());
}
//6. 返回博客id
return Result.ok(blog.getId());
}