目前的点赞功能
同一用户可以给同一篇博客多次点赞,且直接与数据库交互,代码如下:
1 |
|
希望实现的效果
- 一个用户只能给一篇博客点赞一次,再次点赞则取消带你赞
- 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段
Blog
类的isLike
属性)
实现步骤
- 给
Blog
类中添加一个isLike
字段,标示是否已经被当前用户点赞 - 修改点赞功能,利用Redis的set集合判断是否点赞过,是则点赞数+1,否则减一
- 修改根据
id
查询Blog
的业务,判断当前登录用户是否点赞过,赋值给isLike
字段 - 修改分页查询
Blog
的业务,判断当前登录用户是否点赞过,赋值给isLike
字段
新增isLike
字段
因为该字段不在数据库中,所以应该添加注解
注:此处更加优雅的写法应该是创建一个新的BlogVO
1 | /** |
修改点赞功能
点赞功能修改流程如下:
- 获取当前用户
- 判断当前用户是否已经点赞
- 如果未点赞
- 数据库点赞数+1
- 保存用户到Redis的set集合
- 如果已点赞
- 数据库-1
- 把用户从Redis的set中删除
代码实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public Result likeBlog(Long blogId) {
// 获取当前用户
Long userId = UserHolder.getUser().getId();
// 判断是否已点赞
String key = RedisConstants.BLOG_LIKED_KEY + blogId;
Boolean isLiked = redisTemplate.opsForSet().isMember(key, userId.toString());
if (BooleanUtil.isFalse(isLiked)) {
// 数据库+1
boolean success = lambdaUpdate().setSql("liked = liked + 1").eq(Blog::getId, blogId).update();
// 更新Redis
if (success) {
redisTemplate.opsForSet().add(key, userId.toString());
}else {
throw new MySqlException(MessageConstant.LIKE_FAILED);
}
}else {
// 数据库-1
boolean success = lambdaUpdate().setSql("liked = liked - 1").eq(Blog::getId, blogId).update();
// 更新Redis
if (success) {
redisTemplate.opsForSet().remove(key, userId.toString());
}else {
throw new MySqlException(MessageConstant.LIKE_FAILED);
}
}
return Result.ok();
}
修改根据id
查询
只需在查询时,多在Redis中查询一次是否点赞
1 |
|
这么写有一个bug,用户在未登录时,加载首页的博客信息时,也会去查询当前用户是否点赞,但UserHolder.getUser()
返回值为null
,所以此处会抛出NullPointerException
修改如下:
1 | private void setIsLiked(Blog blog) { |
分页查询同理,就不再赘述了