基于Redis的set结构实现点赞功能

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞
  • 查询某篇文章的信息,包括点赞数,以及是否点赞

实现步骤:

  1. 给Blog类中添加一个字段,标示是否被当前用户点赞
  2. 利用Redis的set集合判断是否点赞过
  3. 未点赞过则点赞数+1,并将点赞标识设置为true,并在redis的set集合中保存该信息
  4. 已点赞过则点赞数-1,并将点赞标识设置为false,并在redis的set集合中删除该信息

效果展示

用户发表博客
在这里插入图片描述
用户查看博客

在这里插入图片描述

用户点赞博客
在这里插入图片描述
再次查看博客,点赞数应该加1
在这里插入图片描述
取消点赞
在这里插入图片描述
再次查看博客,点赞数应该减1
在这里插入图片描述

代码实现

bean&vo

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 博客
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog implements Serializable {
    
    

    private Long id;

    private String content;

    private Integer likes;

}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BlogVO {
    
    

    private Long id;

    private String content;

    private Integer likes;

    private Boolean likeFlag = false;

}

核心业务

import cn.hutool.core.bean.BeanUtil;
import com.issa.seckill.bean.Blog;
import com.issa.seckill.common.PathConstant;
import com.issa.seckill.service.BlogService;
import com.issa.seckill.util.RedisUtil;
import com.issa.seckill.vo.BlogVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * 博客发布、查看、点赞
 */
@RestController
@RequestMapping(value = PathConstant.Business.BUSINESS)
@RequiredArgsConstructor
public class BusinessController {
    
    

    private final StringRedisTemplate stringRedisTemplate;

    private final BlogService blogService;

    private final RedisUtil redisUtil;

    /**
     * 点赞/取消点赞
     *
     * @param blog 博客ID
     * @return -
     */
    @PutMapping("/likes")
    public ResponseEntity<Boolean> like(@RequestBody Blog blog, HttpServletRequest request) {
    
    

        // 默认为true,表示已经点了赞
        boolean likeFlag = true;
        String user = request.getHeader("user");

        // 获取文章ID
        Long id = blog.getId();
        String preKey = user + ":" + "likes";

        // 从redis获取该用户是否点赞过
        Boolean member = stringRedisTemplate.opsForSet().isMember(preKey, String.valueOf(id));
        // 如果点赞过,则取消点赞,并在数据库将该文章的点赞-1
        boolean equals = Boolean.TRUE.equals(member);

        Integer likes = blog.getLikes();

        if (likes == null) {
    
    
            likes = blogService.getById(id).getLikes();
        }
        if (equals) {
    
    
            likeFlag = false;
            blog.setLikes(likes - 1);
            boolean update = blogService.updateById(blog);
            if (update) {
    
    
                stringRedisTemplate.opsForSet().remove(preKey, String.valueOf(id));
            }

        } else {
    
    
            // 反之,增加点赞,在数据库+1
            blog.setLikes(likes + 1);
            boolean update = blogService.updateById(blog);
            if (update) {
    
    
                stringRedisTemplate.opsForSet().add(preKey, String.valueOf(id));
            }
        }

//        blogService.update().setSql("likes = likes +1").eq("id", id).update();
        return ResponseEntity.ok(likeFlag);
    }

    /**
     * 获取博客详情
     *
     * @param id 博客ID
     * @return 博客的详细信息:点赞数等
     */
    @GetMapping("/{id}")
    public ResponseEntity<BlogVO> getBlogDetail(@PathVariable Long id, HttpServletRequest request) {
    
    

        String user = request.getHeader("user");
        String preKey = user + ":" + "likes";

        Blog blogDetail = blogService.getById(id);

        BlogVO blogVO = BeanUtil.toBean(blogDetail, BlogVO.class);
        // 从redis获取该用户是否点赞过
        Boolean member = stringRedisTemplate.opsForSet().isMember(preKey, String.valueOf(id));
        boolean equals = Boolean.TRUE.equals(member);
        if (equals) {
    
    
            blogVO.setLikeFlag(true);
        }

        return ResponseEntity.ok(blogVO);

    }

    /**
     * 发表博客
     *
     * @param blog 博客
     * @return 博客ID
     */
    @PostMapping
    public ResponseEntity<Long> pushBlog(@RequestBody Blog blog) {
    
    

        Long id = redisUtil.id("blog");
        blog.setId(id);
        boolean save = blogService.save(blog);
        if (save) {
    
    
            return ResponseEntity.ok(id);
        }

        return ResponseEntity.status(400).build();
    }
}

猜你喜欢

转载自blog.csdn.net/CSDN_SAVIOR/article/details/126540896