点赞功能实现思路

文章介绍了如何在SpringBoot环境中实现一个简单的点赞功能,包括数据库设计、流程分析和代码实现。重点讨论了幂等性的重要性,通过`synchronized`关键字保证同一用户点赞的幂等性以及在事务处理中的应用。同时,提到了前端响应点赞状态的处理方法。
摘要由CSDN通过智能技术生成

引言

点赞功能是一种常见的社交互动功能,通常用于用户对内容或其他用户的喜爱、认可或支持进行表达。它在许多应用和网站中得到广泛应用,能够提升用户参与度,用户通过点赞表达对内容的喜爱、赞赏或认同,从而增加用户与平台的互动和留存。同样也是社交影响力的展示,通过点赞数可以作为一种社交影响力的展示指标。当用户获得大量点赞时,可以增强其在社交网络中的影响力和可见度。这对于内容创作者、个人品牌或企业来说,有助于建立声誉和吸引更多的关注。

在这里我演示一下如何实现一个简单的点赞功能;

环境:

springboot2.3.7

java8

这里我实现的是一个文章点赞功能的实现;

项目准备

首先需要两张数据库表:

article文章表

image-20230624101428156

关键是thumbs点赞数量字段;

article_user_thumb文章用户点赞关系表,用于记录哪个用户点赞了哪个文章:

image-20230624101607092

这里还有一个用户表user,这里只用userId字段,所以就不展示用户表了;

流程分析

点赞功能流程大致如下:

image-20230624102616239

这里需要注意幂等性的保证,否则就会出现一个用户刷赞的情况发生;所以需要用synchronized保证幂等性;

因为数据库操作涉及到两张表的修改,所以需要开启事务,在springboot项目中可以使用@Transactional轻松实现事务处理,但是需要注意该注解和synchronized使用过程中的问题,具体可以看这篇文章:关于@Transactional和synchronized使用的问题

代码实现

controller接口:

@PostMapping("/{articleId}")
public BaseResponse<Integer> 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<ArticleUserThumb> 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;

image-20230624105852578

通过hasThumbs判断是否点赞从而显示不同的点赞图标;

hasThumbs是从后端传来的参数,所以判断是否点赞也是后端判断的,比如在获取文章列表时判断每篇文章是否点赞;

点赞方法:

image-20230624110059941

如果用户点赞,则发送点赞请求,后端执行点赞操作,前端这里为了显示点赞状态需要修改一下hasThumb点赞状态,这里只是前端的修改,为了和后端保证点赞状态同步;

到这功能就差不多实现了:

image-20230624110504533

image-20230624110513727

总结

这就是点赞功能的一个简单实现,但是对于性能没有过多的考虑,因为对于点赞的操作是直接修改数据库的,当点赞请求过多时必然会对数据库造成压力,所以可以考虑缓存的介入等,可以自行尝试;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YXXYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值