1:首先先看以前写的代码。
@PutMapping("/like/{id}")
public Result likeBlog(@PathVariable("id") Long id) {
// 修改点赞数量
blogService.update()
.setSql("liked = liked + 1").eq("id", id).update();
return Result.ok();
}
分析一下问题:
(1):这样的修改直接修改的就是数据库,会给数据库带来极大的压力(修改一次相当于与调用两次接口,也就是操作了两次数据库,一次修改一次查询。)
(2):可以一直进行点赞,也就是达到了刷赞的效果,没有取消点赞的操作。
改进思路
(1):需要有取消点赞的效果,也就是一个item一个用户最多点赞一次。
(2):数据库修改,查询时利用redis进行查询。这样就需要在redis中进行存储item对应的点赞用户,并且需要不可重复(确保用户id唯一),所以采用set集合。
2:进行代码改进。
1:需求分析。
- 同一个用户只能点赞一次,再次点击则取消点赞
- 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段 Blog 类的 isLike 属性)
2:实现步骤:
① 给 Blog 类中添加一个 isLike 字段,标识是否被当前用户点赞
② 修改点赞功能,利用 Redis 的 set 集合判断是否点赞过,未点赞过则点赞数 +1,已点赞过则点赞数 -1.
需要一个集合去记录所有点赞过的用户,同时一个用户只能点赞一次,要求用户 id 不能重复,即集合中元素唯一,而 Redis 中 set 集合满足这种需求。
③ 修改根据 id 查询 Blog 的业务,判断当前登录用户是否点赞过,赋值给 isLike 字段
④ 修改分页查询 Blog 业务,判断当前登录用户是否点赞过,赋值给 isLike 字段
3:点赞业务实现。
controller层。
@PutMapping("/like/{id}")
public Result likeBlog(@PathVariable("id") Long id) {
return blogService.likeBlog(id);
}
service层。
@Autowired
private IUserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
//点赞业务。
@Override
public Result likeBlog(Long id) {
// 1、获取登录用户
UserDTO user = UserHolder.getUser();
// 2、判断当前登录用户是否已经点赞(redis)
Boolean isMember = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY + id, user.getId());
// 3、如果未点赞,可以点赞
if (BooleanUtil.isFalse(isMember)) {
// 3.1、数据库点赞数 +1
boolean isSuccess = update().setSql("liked = liked + 1").eq("id", user.getId().toString()).update();
if (isSuccess) {
// 3.2、保存用户到 Redis 的 set 集合
stringRedisTemplate.opsForSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
}
// 4、如果已点赞,取消点赞
} else {
// 4.1、数据库点赞数 -1
boolean isSuccess = update().setSql("liked = liked - 1").eq("id", user.getId().toString()).update();
if (isSuccess) {
// 4.2、把用户从 Redis 的 set 集合移除
stringRedisTemplate.opsForSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
}
}
return Result.ok();
}
4:查询业务实现。
controller
//首页分页热门
@GetMapping("/hot")
public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
return blogService.queryHotBlog(current);
}
//具体博客。
@GetMapping("/{id}")
public Result queryBlogById(@PathVariable("id") String id) {
return blogService.queryBlogById(id);
}
service
//首页展示。
@Override
public Result queryHotBlog(Integer current) {
// 根据用户查询
Page<Blog> page = query()
.orderByDesc("liked")
.page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
// 获取当前页数据
List<Blog> records = page.getRecords();
// 查询用户
records.forEach(blog -> {
this.queryBlogUser(blog);
this.isBlogLiked(blog);
});
return Result.ok(records);
}
//具体id展示。
private void queryBlogUser(Blog blog) {
Long userId = blog.getUserId();
User user = userService.getById(userId);
blog.setName(user.getNickName());
blog.setIcon(user.getIcon());
}
@Override
public Result queryBlogById(String id) {
Blog blog = getById(id);
if (blog == null) {
return Result.fail("笔记不存在!");
}
queryBlogUser(blog);
// 查询 Blog 是否被点赞
isBlogLiked(blog);
return Result.ok(blog);
}
private void isBlogLiked(Blog blog) {
Long userId = blog.getUserId();
String key = RedisConstants.BLOG_LIKED_KEY + blog.getId();
Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
blog.setIsLike(BooleanUtil.isTrue(isMember));
}
版权声明:本文为weixin_51472505原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。