• redis实现点赞功能。


    1:首先先看以前写的代码。

    1. @PutMapping("/like/{id}")
    2. public Result likeBlog(@PathVariable("id") Long id) {
    3. // 修改点赞数量
    4. blogService.update()
    5. .setSql("liked = liked + 1").eq("id", id).update();
    6. return Result.ok();
    7. }

    分析一下问题:

    (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层

    1. @PutMapping("/like/{id}")
    2. public Result likeBlog(@PathVariable("id") Long id) {
    3. return blogService.likeBlog(id);
    4. }

    service层。 

    1. @Autowired
    2. private IUserService userService;
    3. @Autowired
    4. private StringRedisTemplate stringRedisTemplate;
    5. //点赞业务。
    6. @Override
    7. public Result likeBlog(Long id) {
    8. // 1、获取登录用户
    9. UserDTO user = UserHolder.getUser();
    10. // 2、判断当前登录用户是否已经点赞(redis)
    11. Boolean isMember = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY + id, user.getId());
    12. // 3、如果未点赞,可以点赞
    13. if (BooleanUtil.isFalse(isMember)) {
    14. // 3.1、数据库点赞数 +1
    15. boolean isSuccess = update().setSql("liked = liked + 1").eq("id", user.getId().toString()).update();
    16. if (isSuccess) {
    17. // 3.2、保存用户到 Redis 的 set 集合
    18. stringRedisTemplate.opsForSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
    19. }
    20. // 4、如果已点赞,取消点赞
    21. } else {
    22. // 4.1、数据库点赞数 -1
    23. boolean isSuccess = update().setSql("liked = liked - 1").eq("id", user.getId().toString()).update();
    24. if (isSuccess) {
    25. // 4.2、把用户从 Redis 的 set 集合移除
    26. stringRedisTemplate.opsForSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
    27. }
    28. }
    29. return Result.ok();
    30. }

     4:查询业务实现。

    controller

    1. //首页分页热门
    2. @GetMapping("/hot")
    3. public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
    4. return blogService.queryHotBlog(current);
    5. }
    6. //具体博客。
    7. @GetMapping("/{id}")
    8. public Result queryBlogById(@PathVariable("id") String id) {
    9. return blogService.queryBlogById(id);
    10. }

    service

    1. //首页展示。
    2. @Override
    3. public Result queryHotBlog(Integer current) {
    4. // 根据用户查询
    5. Page page = query()
    6. .orderByDesc("liked")
    7. .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
    8. // 获取当前页数据
    9. List records = page.getRecords();
    10. // 查询用户
    11. records.forEach(blog -> {
    12. this.queryBlogUser(blog);
    13. this.isBlogLiked(blog);
    14. });
    15. return Result.ok(records);
    16. }
    17. //具体id展示。
    18. private void queryBlogUser(Blog blog) {
    19. Long userId = blog.getUserId();
    20. User user = userService.getById(userId);
    21. blog.setName(user.getNickName());
    22. blog.setIcon(user.getIcon());
    23. }
    24. @Override
    25. public Result queryBlogById(String id) {
    26. Blog blog = getById(id);
    27. if (blog == null) {
    28. return Result.fail("笔记不存在!");
    29. }
    30. queryBlogUser(blog);
    31. // 查询 Blog 是否被点赞
    32. isBlogLiked(blog);
    33. return Result.ok(blog);
    34. }
    35. private void isBlogLiked(Blog blog) {
    36. Long userId = blog.getUserId();
    37. String key = RedisConstants.BLOG_LIKED_KEY + blog.getId();
    38. Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
    39. blog.setIsLike(BooleanUtil.isTrue(isMember));
    40. }

  • 相关阅读:
    windows文本绘制 TextOut、DrawText、CreateFont、SetTextColor、SetBkColor、SetBkMode
    使用Pritunl OpenVPN远程连接:实现安全高效的远程访问
    记IIS升级迁移之旅
    .NET Emit 入门教程:第六部分:IL 指令:5:详解 ILGenerator 指令方法:创建实例指令
    localStorage
    C++——多态、虚表、单继承、多继承、覆盖、联编
    Linux 压缩、解压缩命令
    为什么说“分布式架构”才是AR眼镜的未来
    golang 多层map如何增加key
    MyBatis学习:使用resultMap或在SQL语句中给列起别名处理查询结果中列名和JAVA对象属性名不一致的问题
  • 原文地址:https://blog.csdn.net/weixin_51472505/article/details/126481395