原创声明:本人所发内容及涉及源码,均为亲手所撸,如总结内容有误,欢迎指出
大家在很多系统中都会看到点赞功能,比如博客点赞、评论点赞等,那么知道这个功能是怎样实现的嘛?
本次案例无源码哈,以小白博客中的某个功能来说,小白博客功能正在完善,在不久的将来会与大家见面
这篇文章将会结合代码来说说其实现思路
首先设计表,评论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 '文章评论点赞表';
接着设计两个接口,一个是用户点赞接口、一个是取消点赞接口,如下
点赞功能,思路是
-
根据用户前端传递的commentId(评论id)查询评论库评论是否存在
-
如果不存在、直接返回操作失败
-
如果存在,根据评论id和用户id查询是否已点赞
-
如果已点赞,直接返回,已点赞的评论不能重复点赞
-
如果未点赞,将该用户的点赞信息查询评论点赞表,返回点赞成功
代码实现
@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); } }
取消点赞功能,思路是
-
根据用户前端传递的commentId(评论id)查询评论库评论是否存在
-
如果不存在、直接返回操作失败
-
如果存在,根据评论id和用户id查询是否已点赞
-
如果未点赞,直接返回,该用户还未点赞
-
如果已点赞,删除这表点赞信息,返回操作成功
代码实现
@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、为什么要在代码中判断用户是否重复点赞,前端控制一下,变个色不就行了
作为后端开发者,接口越严谨越好,虽然前端能帮我们限制用户操作,但是如果不严谨,脱离前端就是个大灾难,总之一句话,自己的事情自己做,不要相信前端。
