点赞功能实现思路 |
您所在的位置:网站首页 › 有赞学堂 › 点赞功能实现思路 |
引言
点赞功能是一种常见的社交互动功能,通常用于用户对内容或其他用户的喜爱、认可或支持进行表达。它在许多应用和网站中得到广泛应用,能够提升用户参与度,用户通过点赞表达对内容的喜爱、赞赏或认同,从而增加用户与平台的互动和留存。同样也是社交影响力的展示,通过点赞数可以作为一种社交影响力的展示指标。当用户获得大量点赞时,可以增强其在社交网络中的影响力和可见度。这对于内容创作者、个人品牌或企业来说,有助于建立声誉和吸引更多的关注。 在这里我演示一下如何实现一个简单的点赞功能; 环境: springboot2.3.7 java8 这里我实现的是一个文章点赞功能的实现; 项目准备首先需要两张数据库表: article文章表 关键是thumbs点赞数量字段; article_user_thumb文章用户点赞关系表,用于记录哪个用户点赞了哪个文章: 这里还有一个用户表user,这里只用userId字段,所以就不展示用户表了; 流程分析点赞功能流程大致如下: ![]() 这里需要注意幂等性的保证,否则就会出现一个用户刷赞的情况发生;所以需要用synchronized保证幂等性; 因为数据库操作涉及到两张表的修改,所以需要开启事务,在springboot项目中可以使用@Transactional轻松实现事务处理,但是需要注意该注解和synchronized使用过程中的问题,具体可以看这篇文章:关于@Transactional和synchronized使用的问题 代码实现controller接口: @PostMapping("/{articleId}") public BaseResponse postArticleThumbs(@PathVariable Long articleId) { if (articleId == null) { throw new BusinessException(StatusCode.PARAMS_ERROR); } // 判断该文章是否存在 Article article = articleService.getById(articleId); if (article == null) { throw new BusinessException(StatusCode.PARAMS_ERROR, "文章不存在"); } // 获取当前点赞用户信息 UserVo currentUser = userSupport.getCurrentUser(); if (currentUser == null) { throw new BusinessException(StatusCode.NO_AUTH); } long userId = currentUser.getId(); // 获取当前登录用户的id int res; // 这里需要注意synchronized和@Transactional注解问题 synchronized (String.valueOf(userId).intern()) { // 保证同一个用户的点赞是串行执行的,保证幂等性 res = articleUserThumbService.postArticleThumbs(articleId, userId); } return ResultUtils.success(res); }service实现类: @Override @Transactional(rollbackFor = Exception.class) public int postArticleThumbs(Long articleId, long userId) { if (articleId == null) { throw new BusinessException(StatusCode.PARAMS_ERROR); } // 点赞对象实体 ArticleUserThumb articleUserThumb = new ArticleUserThumb(); articleUserThumb.setArticleId(articleId); articleUserThumb.setUserId(userId); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(articleUserThumb); int result; // 操作结果 // 判断当前用户是否已经点赞,点赞了则取消,没有点赞则点赞 int count = articleUserThumbMapper.selectCount(queryWrapper); if (count > 0) { // 取消点赞 result = articleUserThumbMapper.delete(queryWrapper); if (result > 0) { // 删除成功 boolean res = articleService.update() .eq("id", articleId) .gt("thumbs", 0) // 确保点赞数是大于0的才能-1 .setSql("thumbs = thumbs - 1") .update(); return res ? -1 : 0; } else { throw new BusinessException(StatusCode.SYSTEM_ERROR); } } else { // 点赞 result = articleUserThumbMapper.insert(articleUserThumb); if (result > 0) { // 新增成功 boolean res = articleService.update() .eq("id", articleId) .setSql("thumbs = thumbs + 1") .update(); return res ? 1 : 0; } else { throw new BusinessException(StatusCode.SYSTEM_ERROR); } } }这里的难点就是:为什么需要synchronized保证幂等性和synchronized与@Transactional为什么要这样分开写,搞清楚这两点这部分代码就很好明白了; 后端的功能大致就是这样,下面我简单演示一下前端的实现: 前端代码后端点赞执行成功后,前端要有对应的相应结果,我的方法是设置一个hasThumb字段,前端通过该字段判断是否已经点赞; 前端用的组件库是ant design vue; 通过hasThumbs判断是否点赞从而显示不同的点赞图标; hasThumbs是从后端传来的参数,所以判断是否点赞也是后端判断的,比如在获取文章列表时判断每篇文章是否点赞; 点赞方法: 如果用户点赞,则发送点赞请求,后端执行点赞操作,前端这里为了显示点赞状态需要修改一下hasThumb点赞状态,这里只是前端的修改,为了和后端保证点赞状态同步; 到这功能就差不多实现了: 这就是点赞功能的一个简单实现,但是对于性能没有过多的考虑,因为对于点赞的操作是直接修改数据库的,当点赞请求过多时必然会对数据库造成压力,所以可以考虑缓存的介入等,可以自行尝试; |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |