0


基于springboot+Redis的前后端分离项目(七)-【黑马点评】

🎁🎁资源文件分享
链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA?pwd=eh11
提取码:eh11

发布笔记,点赞,点赞排行

达人探店

1、达人探店-发布探店笔记

发布探店笔记

探店笔记类似点评网站的评价,往往是图文结合。对应的表有两个:
tb_blog:探店笔记表,包含笔记中的标题、文字、图片等
tb_blog_comments:其他用户对探店笔记的评价

具体发布流程

在这里插入图片描述
上传接口

@Slf4j
@RestController
@RequestMapping("upload")publicclassUploadController{

    @PostMapping("blog")public Result uploadImage(@RequestParam("file") MultipartFile image){try{// 获取原始文件名称
            String originalFilename = image.getOriginalFilename();// 生成新文件名
            String fileName =createNewFileName(originalFilename);// 保存文件
            image.transferTo(newFile(SystemConstants.IMAGE_UPLOAD_DIR, fileName));// 返回结果
            log.debug("文件上传成功,{}", fileName);return Result.ok(fileName);}catch(IOException e){thrownewRuntimeException("文件上传失败", e);}}}

注意:在操作时,需要修改SystemConstants.IMAGE_UPLOAD_DIR 自己图片所在的地址,在实际开发中图片一般会放在nginx上或者是云存储上。

BlogController

@RestController
@RequestMapping("/blog")publicclassBlogController{

    @Resource
    private IBlogService blogService;

    @PostMapping
    public Result saveBlog(@RequestBody Blog blog){//获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUpdateTime(user.getId());//保存探店博文
        blogService.saveBlog(blog);//返回idreturn Result.ok(blog.getId());}}

2、 达人探店-查看探店笔记

实现查看发布探店笔记的接口
在这里插入图片描述
实现代码:

BlogServiceImpl

@Override
public Result queryBlogById(Long id){// 1.查询blog
    Blog blog =getById(id);if(blog == null){return Result.fail("笔记不存在!");}// 2.查询blog有关的用户queryBlogUser(blog);return Result.ok(blog);}

3、 达人探店-点赞功能

初始代码

@GetMapping("/likes/{id}")public Result queryBlogLikes(@PathVariable("id") Long id){//修改点赞数量
    blogService.update().setSql("liked = liked +1 ").eq("id",id).update();return Result.ok();}

问题分析:这种方式会导致一个用户无限点赞,明显是不合理的

造成这个问题的原因是,我们现在的逻辑,发起请求只是给数据库+1,所以才会出现这个问题

在这里插入图片描述
完善点赞功能

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞
  • 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)。

实现步骤:

  • 给Blog类中添加一个isLike字段,标示是否被当前用户点赞。
  • 修改点赞功能,利用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1。
  • 修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段。
  • 修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段。

为什么采用set集合:

因为我们的数据是不能重复的,当用户操作过之后,无论他怎么操作,都是

具体步骤:

1、在Blog 添加一个字段

@TableField(exist =false)private Boolean isLike;

2、修改代码

 @Override
    public Result likeBlog(Long id){// 1.获取登录用户
        Long userId = UserHolder.getUser().getId();// 2.判断当前登录用户是否已经点赞
        String key = BLOG_LIKED_KEY + 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();//4.2 把用户从Redis的set集合移除if(isSuccess){
                stringRedisTemplate.opsForSet().remove(key,userId.toString());}}

4、 达人探店-点赞排行榜

在探店笔记的详情页面,应该把给该笔记点赞的人显示出来,比如最早点赞的TOP5,形成点赞排行榜:

之前的点赞是放到set集合,但是set集合是不能排序的,所以这个时候,咱们可以采用一个可以排序的set集合,就是咱们的sortedSet
在这里插入图片描述
我们接下来来对比一下这些集合的区别是什么

所有点赞的人,需要是唯一的,所以我们应当使用set或者是sortedSet

其次我们需要排序,就可以直接锁定使用sortedSet啦。
在这里插入图片描述
修改代码

BlogServiceImpl

点赞逻辑代码

@Override
    public Result likeBlog(Long id){// 1.获取登录用户
        Long userId = UserHolder.getUser().getId();// 2.判断当前登录用户是否已经点赞
        String key = BLOG_LIKED_KEY + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());if(score == null){// 3.如果未点赞,可以点赞// 3.1.数据库点赞数 + 1
            boolean isSuccess =update().setSql("liked = liked + 1").eq("id", id).update();// 3.2.保存用户到Redis的set集合  zadd key value scoreif(isSuccess){
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());}}else{// 4.如果已点赞,取消点赞// 4.1.数据库点赞数 -1
            boolean isSuccess =update().setSql("liked = liked - 1").eq("id", id).update();// 4.2.把用户从Redis的set集合移除if(isSuccess){
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());}}return Result.ok();}privatevoidisBlogLiked(Blog blog){// 1.获取登录用户
        UserDTO user = UserHolder.getUser();if(user == null){// 用户未登录,无需查询是否点赞return;}
        Long userId = user.getId();// 2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+ blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);}

点赞列表查询列表

BlogController

@GetMapping("/likes/{id}")public Result queryBlogLikes(@PathVariable("id") Long id){return blogService.queryBlogLikes(id);}

BlogService

@Override
public Result queryBlogLikes(Long id){
    String key = BLOG_LIKED_KEY + id;// 1.查询top5的点赞用户 zrange key 0 4
    Set<String> top5 = stringRedisTemplate.opsForZSet().range(key,0,4);if(top5 == null || top5.isEmpty()){return Result.ok(Collections.emptyList());}// 2.解析出其中的用户id
    List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
    String idStr = StrUtil.join(",", ids);// 3.根据用户id查询用户 WHERE id IN ( 5 , 1 ) ORDER BY FIELD(id, 5, 1)
    List<UserDTO> userDTOS = userService.query().in("id", ids).last("ORDER BY FIELD(id,"+ idStr +")").list().stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());// 4.返回return Result.ok(userDTOS);}

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹

标签: spring boot redis java

本文转载自: https://blog.csdn.net/m0_59230408/article/details/130983708
版权归原作者 失重外太空. 所有, 如有侵权,请联系我们删除。

“基于springboot+Redis的前后端分离项目(七)-【黑马点评】”的评论:

还没有评论