点赞
需求
- 同一个用户只能点赞一次,再次点击则取消点赞
- 如果当前用户已经点赞,则点赞按钮高亮显示(判断字段Blog类的isLike是true或false)
实现步骤
- 给Blog类添加isLike属性,表示是否被当前用户点赞(这个问题是难点所在,也和需求1一样的需求)
- 用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1。
- 修改根据id查询blog的业务(以及分页查询blog的业务),判断当前登陆用户是否点赞过,赋值给isLike字段。
判断用户有没有点过赞,实现方案非常多,比如数据库里建一张表,记录blogId和给这个blog点赞的userId,机每点赞,这张表里就会记录一次,下次再来就判断下是否存在记录。但用数据库实现,太重了,首先数据库的性能不太好,而且这种点赞的判断可能会比较多,所以对数据库的压力就会比较大。可以使用轻量级的办法,比如redis。
那如果要判断用户有没有点赞过,其实就是记录一下当前blog被谁点赞过,所以可以在Redis里以blog的id为key,用集合去记录给这个blog点过赞的所有用户id。下次再来时,判断用户id在集合中是否存在。由于一个用户只能点赞一次,所以这个集合中用户id是不能重复,所以可以用set集合。
Blog.java
...
// 由于数据库中没这个字段,所以加 TableField(exist = false)注解
@TableField(exist = false)
private Boolean isLike; // 当前用户是否点赞过
...
BlogController.java
...
@PutMapping("/like/{id}")
public Result likeBlog(@PathVariable("id") Long id) {
return blogService.likeBlog(id);// 点赞功能,参数id是blog的id
}
...
IBlogService.java
public interface IBlogService extends IService<Blog> {
...
Result likeBlog(Long id);
...
}
BlogServiceImpl.java
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
...
@Resource
private StringRedisTemplate stringRedisTemplate;
...
@Override
public Result likeBlog(Long id) {
// 1,获取登陆用户
Long userId = UserHolder.getUser().getId();
// 2,判断当前登陆用户是否已经点过赞
String key = "blog:liked:" + id;// 文章id
Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
// 由于isMember是包装类,所以直接判断可能为空,可以用hutool的工具类(BooleanUtil)判断
if (BooleanUtil.isFalse(isMember)) {
// 3,如果没点过赞,可以点赞
// 3.1 数据库点赞数+1
boolean isSuccess = update().setSql("liked = liked + 1").eq(