全栈小白的gravatar头像
全栈小白 2023-02-03 10:39:45
一文学会点赞功能

大家在很多系统中都会看到点赞功能,比如博客点赞、评论点赞等,那么知道这个功能是怎样实现的嘛?

本次案例无源码哈,以小白博客中的某个功能来说,小白博客功能正在完善,在不久的将来会与大家见面

这篇文章将会结合代码来说说其实现思路

首先设计表,评论id和用户id添加了唯一索引,保证单个用户只能点赞一次

create table t_article_comment_like(
    id int auto_increment comment 'id' primary key,
    comment_id  int  not null comment '评论id',
    user_id varchar(50) not null comment '用户id',
    belong_user_id varchar(50) not null comment '所属用户',
    like_time  datetime  null comment '点赞时间',
    constraint t_article_comment_like_comment_id_user_id unique (comment_id, user_id)
) comment '文章评论点赞表';

接着设计两个接口,一个是用户点赞接口、一个是取消点赞接口,如下

一文学会点赞功能

点赞功能,思路是

  1. 根据用户前端传递的commentId(评论id)查询评论库评论是否存在

  2. 如果不存在、直接返回操作失败

  3. 如果存在,根据评论id和用户id查询是否已点赞

  4. 如果已点赞,直接返回,已点赞的评论不能重复点赞

  5. 如果未点赞,将该用户的点赞信息查询评论点赞表,返回点赞成功

代码实现

@Override
    public void likeComment(LikeCommentDTO dto, HttpServletRequest request, BaseResult result) {
        long startTime = System.currentTimeMillis();
        try {
            // 根据评论id查询评论信息是否存在
            Integer commentId = dto.getCommentId();
            ArticleComment comment = articleCommentMapper.selectById(commentId);
            // 不存在,直接报错返回 该评论不存在
            if (ObjectUtils.isEmpty(comment)) {
                result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
                result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg() + ",该评论不存在");
            } else {
                // 从请求头中解析用户信息
                UserSubject userByToken = userService.getUserByToken(request);
                // 查询用户是否已点赞
                LambdaQueryWrapper<ArticleCommentLike> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ArticleCommentLike::getCommentId, commentId)
                        .eq(ArticleCommentLike::getUserId, userByToken.getId());
                Integer count = articleCommentLikeMapper.selectCount(queryWrapper);
                // 如果已点赞,返回已点赞的评论不能重复点赞
                if (count >= 1) {
                    result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
                    result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg() + ",已点赞的评论不能重复点赞");
                } else {
                    // 未点赞,将该用户的点赞信息查询评论点赞表,返回点赞成功
                    ArticleCommentLike articleCommentLike = new ArticleCommentLike();
                    articleCommentLike.setCommentId(commentId);
                    articleCommentLike.setBelongUserId(comment.getCommentFrom());
                    articleCommentLike.setUserId(userByToken.getId());
                    articleCommentLike.setLikeTime(LocalDateTime.now());
                    int insert = articleCommentLikeMapper.insert(articleCommentLike);
                    if (insert != 1) {
                        result.setCode(CurrencyErrorEnum.DATABASE_ERROR.getCode());
                        result.setMsg(CurrencyErrorEnum.DATABASE_ERROR.getMsg());
                    }
                }
            }
        } catch (Exception e) {
            log.error("用户评论点赞失败,{}", e);
            result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
            result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg());
        } finally {
            long endTime = System.currentTimeMillis();
            log.info("【{}】【用户评论点赞接口】【{}ms】 \n入参:{}\n出参:{}", "新增", endTime - startTime, dto, result);
        }
    }

取消点赞功能,思路是

  1. 根据用户前端传递的commentId(评论id)查询评论库评论是否存在

  2. 如果不存在、直接返回操作失败

  3. 如果存在,根据评论id和用户id查询是否已点赞

  4. 如果未点赞,直接返回,该用户还未点赞

  5. 如果已点赞,删除这表点赞信息,返回操作成功

代码实现

@Override
    public void unLikeComment(LikeCommentDTO dto, HttpServletRequest request, BaseResult result) {
        long startTime = System.currentTimeMillis();
        try {
            Integer commentId = dto.getCommentId();
            ArticleComment comment = articleCommentMapper.selectById(commentId);
            if (ObjectUtils.isEmpty(comment)) {
                result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
                result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg() + ",该评论不存在");
            } else {
                UserSubject userByToken = userService.getUserByToken(request);
                LambdaQueryWrapper<ArticleCommentLike> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ArticleCommentLike::getCommentId, commentId)
                        .eq(ArticleCommentLike::getUserId, userByToken.getId());
                List<ArticleCommentLike> commentLikes = articleCommentLikeMapper.selectList(queryWrapper);
                if (commentLikes.size() < 1) {
                    result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
                    result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg() + ",该评论还未点赞");
                } else {
                    ArticleCommentLike articleCommentLike = commentLikes.get(0);
                    articleCommentLikeMapper.deleteById(articleCommentLike.getId());
                }
            }

        } catch (Exception e) {
            log.error("用户评论取消点赞失败,{}", e);
            result.setCode(CurrencyErrorEnum.OPERA_ERROR.getCode());
            result.setMsg(CurrencyErrorEnum.OPERA_ERROR.getMsg());
        } finally {
            long endTime = System.currentTimeMillis();
            log.info("【{}】【用户评论取消点赞接口】【{}ms】 \n入参:{}\n出参:{}", "删除", endTime - startTime, dto, result);
        }
    }

启动项目、小白博客项目中集成了knife4j,我们就在这个平台测试,访问http://127.0.0.1:2022/doc.html

首先登陆

一文学会点赞功能

token有效期为30分钟,在数据库中找了一条评论id为2,带着token请求评论点赞接口

一文学会点赞功能

首次请求

一文学会点赞功能

重复点赞

一文学会点赞功能

取消点赞也是同样哈,就不多测试了

总结一下

对于点赞和取消点赞的表结构设计和代码实现其实so easy

大家有没有发现,小编代码中其实有很多不理解的部分

1、评论点赞接口为什么要根据评论id查评论是否存在呢?用户既然在界面上点,肯定是存在的

2、为什么要在代码中判断用户是否重复点赞,前端控制一下,变个色不就行了

作为后端开发者,接口越严谨越好,虽然前端能帮我们限制用户操作,但是如果不严谨,脱离前端就是个大灾难,总之一句话,自己的事情自己做,不要相信前端。

 


打赏

已有1人打赏

最代码官方的gravatar头像
最近浏览
dapeng0011  LV15 2024年7月16日
haidaozhi  LV7 2023年12月15日
youwuzuichen  LV11 2023年7月28日
wuwutu  LV7 2023年7月18日
哇塞塞哈哈哈  LV8 2023年5月4日
随便取个名字_哈哈  LV27 2023年5月4日
取名字好麻烦  LV5 2023年3月18日
wonderUU  LV5 2023年3月16日
lcy111  LV5 2023年2月28日
80730176  LV7 2023年2月13日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友