针对用户的操作:可以对用户进行关注和取消关注功能。
实现思路:
需求:基于该表数据结构,实现两个接口:
关注和取关接口:用于数据库记录是否对该博主进行关注
判断是否关注的接口:用于前端进行高亮显示
关注是User之间的关系,是博主与粉丝的关系,数据库中有一张tb_follow表来标示:
数据库存入一张关注表,用于记录的存储。
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);
- }
-
- // 关注和取关service
- @Override
- public Result follow(Long followUserId, Boolean isFollow) {
- // 1.获取登录用户
- Long userId = UserHolder.getUser().getId();
- String key = "follows:" + userId;
- // 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
() - .eq("user_id", userId).eq("follow_user_id", followUserId));
-
- }
- return Result.ok();
- }
想要去看共同关注的好友,需要首先进入到这个页面,这个页面会发起两个请求
1、去查询用户的详情
2、去查询用户的笔记
- // 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
page = blogService.query() - .eq("user_id", id).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
- // 获取当前页数据
- List
records = page.getRecords(); - return Result.ok(records);
- }
接下来我们来看看共同关注如何实现:
需求:利用Redis中恰当的数据结构,实现共同关注功能。在博主个人页面展示出当前用户与博主的共同关注呢。
当然是使用我们之前学习过的set集合咯,在set集合中,有交集并集补集的api,我们可以把两人的关注的人分别放入到一个set集合中,然后再通过api去查看这两个set集合中的交集数据。
我们先来改造当前的关注列表
改造原因是因为我们需要在用户关注了某位用户后,需要将数据放入到set集合中,方便后续进行共同关注,同时当取消关注时,也需要从set集合中进行删除,主要是增添了一些Redis记录
FollowServiceImpl
- @Override
- public Result follow(Long followUserId, Boolean isFollow) {
- // 1.获取登录用户
- Long userId = UserHolder.getUser().getId();
- String key = "follows:" + userId;
- // 1.判断到底是关注还是取关
- if (isFollow) {
- // 2.关注,新增数据
- Follow follow = new Follow();
- follow.setUserId(userId);
- follow.setFollowUserId(followUserId);
- boolean isSuccess = save(follow);
- if (isSuccess) {
- // 把关注用户的id,放入redis的set集合 sadd userId followerUserId
- stringRedisTemplate.opsForSet().add(key, followUserId.toString());
- }
- } else {
- // 3.取关,删除 delete from tb_follow where user_id = ? and follow_user_id = ?
- boolean isSuccess = remove(new QueryWrapper
() - .eq("user_id", userId).eq("follow_user_id", followUserId));
- if (isSuccess) {
- // 把关注用户的id从Redis集合中移除
- stringRedisTemplate.opsForSet().remove(key, followUserId.toString());
- }
- }
- return Result.ok();
- }
具体的关注代码:
FollowServiceImpl
- @Override
- public Result followCommons(Long id) {
- // 1.获取当前用户
- Long userId = UserHolder.getUser().getId();
- String key = "follows:" + userId;
- // 2.求交集
- String key2 = "follows:" + id;
- Set
intersect = stringRedisTemplate.opsForSet().intersect(key, key2); - if (intersect == null || intersect.isEmpty()) {
- // 无交集
- return Result.ok(Collections.emptyList());
- }
- // 3.解析id集合
- List
ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList()); - // 4.查询用户
- List
users = userService.listByIds(ids) - .stream()
- .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
- .collect(Collectors.toList());
- return Result.ok(users);
- }
分析逻辑:
首先我们写了两个实现,
一个是关注与取关:通过对数据库的follow表的查询,来表示关注者和被关注的关系。
另一个是进行follow表的查询,用于前端进行高亮展示。
其次,我们通过redis进行共同关注
【第一步】我们先改写了关注和取关的逻辑,主要是增添了redis的Set数据结构添加和删除。
【第二步】利用Set的交集实现共同关注的功能。
【反思】
我们写的共同关注业务能使Redis和数据库一致嘛?显然在Redis不发生突然宕机的前提是会保证Redis和数据库的一致性。
原因:我们是在改写数据库的同时也改写了Redis。