- 点赞实现流程

原始代码存在的问题:一个用户可以无限点赞。这显然是不合理的,所以我们需要对点赞功能进行一个优化,实现一人只能点赞一次。
java
/**
* 点赞或取消点赞博客。
*
* @param id业务id
* @return处理结果
*/
@PutMapping("/like/{id}")
public Result likeBlog(@PathVariable("id") Long id) {
blogService.update()
.setSql("liked=liked+1").eq("id", id).update();
return Result.ok();
}需求:
- 同一个用户只能点赞一次,再次点击则取消点赞
- 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)
实现步骤:
给Blog类中添加一个isLike字段,标示是否被当前用户点赞
修改点赞功能,利用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1
修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段
修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段
代码实现:使用Redis的Set集合存储已点赞用户id,保证点赞唯一性
java
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
@Resource
private IUserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 分页查询热门探店笔记。
*
* 作用:
* 1.根据点赞查询博客;
* 2.获取当前页数据;
* 3.设置每一个热点笔记的用户,以及是否被点赞;
*
* @param current当前页码
* @return处理结果
*/
@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查询探店笔记详情。
*
* 作用:
* 1.查询blog;
* 2.查询blog有关用户;
*
* @param id业务id
* @return处理结果
*/
@Override
public Result queryBlogById(Long id) {
//1.查询blog
Blog blog = getById(id);
if (blog == null) {
return Result.fail("笔记不存在");
}
//2.查询blog有关用户
queryBlogUser(blog);
// # 3.查询blog是否被点赞
isBlogLiked(blog);
return Result.ok(blog);
}
/**
* 判断当前登录用户是否点赞了这篇博客。
*
* 作用:
* 1.获取当前用户;
* 2.判断当前登录用户是否已点赞;
*
* @param blog当前博客对象
* @return无返回值
*/
private void isBlogLiked(Blog blog) {
//1.获取当前用户
Long userId = UserHolder.getUser().getId();
//2.判断当前登录用户是否已点赞
String key = "blog:liked:" + blog.getId();
Boolean isLiked = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
blog.setIsLike(BooleanUtil.isTrue(isLiked));
}
/**
* 点赞或取消点赞博客。
*
* 作用:
* 1.获取当前用户;
* 2.判断当前登录用户是否已点赞;
* 3.如果未点赞,可以点赞;
* 4.数据库点赞数+1;
* 5.保存用户id到Redis的Set集合;
*
* @param id业务id
* @return处理结果
*/
@Override
public Result likeBlog(@PathVariable("id") Long id) {
//1.获取当前用户
Long userId= UserHolder.getUser().getId();
//2.判断当前登录用户是否已点赞
String key="blog:liked:"+id;
Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
if(BooleanUtil.isFalse(isMember)) {
//3.如果未点赞,可以点赞
//3.1.数据库点赞数+1
boolean isSuccess = update().setSql("liked=liked+1").eq("id",id).update();
//3.2.保存用户到Redis的Set集合
if (isSuccess) {
stringRedisTemplate.opsForSet().add(key, userId.toString());
}
} else {
//4.如果已点赞,取消点赞
//4.1.数据库点赞数-1
boolean isSuccess=update().setSql("liked=liked-1").eq("id",id).update();
if(isSuccess){
stringRedisTemplate.opsForSet().remove(key, userId.toString());
}
}
return Result.ok();
}
}- 测试功能 登陆后,点击笔记右下角点赞功能,点赞数+1,已点赞高亮显示。

同一个用户再次点赞同一篇笔记后,点赞数-1,高亮取消,Redis的Set集合中移除该用户id,防止了用户重复点赞。 