多级评论的实现,评论回复功能(两层型)

news2024/11/16 9:23:42

前言:

技术栈:springboot + mysql + mybatis

比着写一遍,你也一定会实现多级评论的功能,简单易上手!

1.效果

整体的结构只有两层,但是确实现了评论回复功能

[

    {

        "id": 2,

        "userId": 2,

        "blogId": 1,

        "parentId": 0,

        "toUser": 0,

        "content": "我是二号一级评论",

        "liked": 1,

        "createTime": "2024-08-16 08:02:11",

        "isLike": true,

        "children": [

            {

                "id": 6,

                "userId": 3,

                "blogId": 1,

                "parentId": 2,

                "toUser": 1,

                "content": "好",

                "liked": 0,

                "createTime": "2024-08-16 09:37:26",

                "isLike": true,

                "children": null,

                "nickName": "用户3",

                "icon": "用户3的头像",

                "pnickName": "用户1",

                "picon": "用户1的头像"

            },

            {

                "id": 5,

                "userId": 1,

                "blogId": 1,

                "parentId": 2,

                "toUser": 2,

                "content": "我是用户1,我评论了二号一级评论",

                "liked": 0,

                "createTime": "2024-08-16 09:25:16",

                "isLike": true,

                "children": null,

                "nickName": "用户1",

                "icon": "用户1的头像",

                "pnickName": "用户2",

                "picon": "用户2的头像"

            }

        ],

        "nickName": "用户2",

        "icon": "用户2的头像",

        "pnickName": null,

        "picon": null

    },

    {

        "id": 1,

        "userId": 1,

        "blogId": 1,

        "parentId": 0,

        "toUser": 0,

        "content": "我是一号一级评论",

        "liked": 0,

        "createTime": "2024-08-16 08:02:10",

        "isLike": true,

        "children": [

            {

                "id": 4,

                "userId": 2,

                "blogId": 1,

                "parentId": 1,

                "toUser": 3,

                "content": "我是用户2,我回复了用户3发表的评论,我们都是一号一级评论的子评论",

                "liked": 1,

                "createTime": "2024-08-16 08:02:11",

                "isLike": true,

                "children": null,

                "nickName": "用户2",

                "icon": "用户2的头像",

                "pnickName": "用户3",

                "picon": "用户3的头像"

            },

            {

                "id": 3,

                "userId": 3,

                "blogId": 1,

                "parentId": 1,

                "toUser": 1,

                "content": "我是用户3,我评论了一号一级评论",

                "liked": 1,

                "createTime": "2024-08-16 08:02:10",

                "isLike": true,

                "children": null,

                "nickName": "用户3",

                "icon": "用户3的头像",

                "pnickName": "用户1",

                "picon": "用户1的头像"

            }

        ],

        "nickName": "用户1",

        "icon": "用户1的头像",

        "pnickName": null,

        "picon": null

    }

]

2. sql脚本

1.评论表

-- ----------------------------
-- Table structure for tb_blog_comments
-- ----------------------------
DROP TABLE IF EXISTS `tb_blog_comments`;
CREATE TABLE `tb_blog_comments`  (
  `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` bigint UNSIGNED NOT NULL DEFAULT 1 COMMENT '发表评论的用户id',
  `blog_id` bigint UNSIGNED NOT NULL DEFAULT 1 COMMENT '文章的id',
  `parent_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联一级评论的id,一级评论的为0',
  `to_user` bigint UNSIGNED NOT NULL COMMENT '给哪个用户的回复',
  `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '回复的内容',
  `liked` int UNSIGNED NULL DEFAULT 0 COMMENT '点赞数',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = COMPACT;

-- ----------------------------
-- Records of tb_blog_comments
-- ----------------------------
INSERT INTO `tb_blog_comments` VALUES (1, 1, 1, 0, 0, '我是一号一级评论', 0, '2024-08-16 08:02:10');
INSERT INTO `tb_blog_comments` VALUES (2, 2, 1, 0, 0, '我是二号一级评论', 1, '2024-08-16 08:02:11');
INSERT INTO `tb_blog_comments` VALUES (3, 3, 1, 1, 1, '我是用户3,我评论了一号一级评论', 1, '2024-08-16 08:02:10');
INSERT INTO `tb_blog_comments` VALUES (4, 2, 1, 1, 3, '我是用户2,我回复了用户3发表的评论,我们都是一号一级评论的子评论', 1, '2024-08-16 08:02:11');
INSERT INTO `tb_blog_comments` VALUES (5, 1, 1, 2, 2, '我是用户1,我评论了二号一级评论', 0, '2024-08-16 09:25:16');
INSERT INTO `tb_blog_comments` VALUES (6, 3, 1, 2, 1, '好', 0, '2024-08-16 09:37:26');

SET FOREIGN_KEY_CHECKS = 1;

 2.用户表

 

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_comment_like
-- ----------------------------
DROP TABLE IF EXISTS `tb_comment_like`;
CREATE TABLE `tb_comment_like`  (
  `user_id` bigint NOT NULL COMMENT '用户的id',
  `comment_id` bigint NOT NULL COMMENT '评论的id'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '评论点赞表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_comment_like
-- ----------------------------
INSERT INTO `tb_comment_like` VALUES (1, 2);
INSERT INTO `tb_comment_like` VALUES (1, 3);
INSERT INTO `tb_comment_like` VALUES (1, 4);

SET FOREIGN_KEY_CHECKS = 1;

 3.用户点赞表

 

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `id` int NOT NULL COMMENT 'id',
  `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像',
  `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '用户1的头像', '用户1');
INSERT INTO `tb_user` VALUES (2, '用户2的头像', '用户2');
INSERT INTO `tb_user` VALUES (3, '用户3的头像', '用户3');

SET FOREIGN_KEY_CHECKS = 1;

 3.代码实现功能

1.依赖:

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!-- MyBatis-Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

2. application.yaml配置:

server:
  port: 80
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
    username: root
    password: '123456'
mybatis:
  mapper-locations: classpath:/mapper/*.xml

3. 实体类:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_blog_comments")
public class BlogComments implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 用户id
     */
    private Long userId;

    /**
     * 探店id
     */
    private Long blogId;

    /**
     * 关联的1级评论id,如果是一级评论,则值为0
     */
    private Long parentId;

    /**
     * 回复的评论id
     */
    private Long toUser;

    /**
     * 回复的内容
     */
    private String content;

    /**
     * 点赞数
     */
    private Integer liked;


    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;


    /**
     * 是否点赞
     */
    @TableField(exist = false)
    private Boolean isLike;

    /**
     * 子评论
     */
    @TableField(exist = false)
    List<BlogComments> children;

    /**
     * 评论者的昵称
     */
    @TableField(exist = false)
    private String nickName;

    /** 评论者的头像 */
    @TableField(exist = false)
    private String icon;

    /** 评论者的上级昵称 */
    @TableField(exist = false)
    private String pNickName;

    /** 评论者的的上级头像 */
    @TableField(exist = false)
    private String pIcon;
}

4.controlller层:

@RestController
public class CommentController {

    @Resource
    private CommentServiceImpl commentServiceimpl;

    @GetMapping("/getComment/{blogId}")
    public List<BlogComments> getAllComments(@PathVariable Integer blogId) {
        return commentServiceimpl.getAllComments(blogId);
    }
}

5.service层:

这里简写,不要接口,直接上实现类

@Service
public class CommentServiceImpl {

    @Resource
    private CommentMapper commentMapper;

    //前提:将多级评论看成两级去实现,整个评论体系相当于就两层
    public List<BlogComments> getAllComments(Integer blogId) {
        //1.查询全部评论
        List<BlogComments> blogComments = commentMapper.getAllComments(blogId);
        //2.查询一级评论
        List<BlogComments> rootComments = blogComments.stream().filter(blogComments1 -> blogComments1.getParentId() == 0).collect(Collectors.toList());
        //3.遍历一级评论,获得全部的子评论(下面的全部都是子评论)
        for (BlogComments rootComment : rootComments) {
            List<BlogComments> comments = blogComments.stream()
                    .filter(blogComment -> blogComment.getParentId().equals(rootComment.getId()))
                    .collect(Collectors.toList());
            //现在子评论中的pIcon和pNickName为空,要为他们设置信息
            comments.forEach(comment -> {
                Optional<BlogComments> pComment
                        = blogComments
                        .stream()
                        .filter(blogComment -> comment.getToUser().equals(blogComment.getUserId())).findFirst();
                pComment.ifPresent(v -> {
                    comment.setPNickName(v.getNickName());
                    comment.setPIcon(v.getIcon());
                });
                // 判断是否点赞
                isBlogCommentLiked(comment);
            });
            rootComment.setChildren(comments);
            // 判断是否点赞
            isBlogCommentLiked(rootComment);
        }
        //返回一级评论,因为一级评论的孩子就是剩下的所有评论
        return rootComments;
    }

    private void isBlogCommentLiked(BlogComments comment) {
        //1.获取当前登录用户的id,这里假设id为1
        Long userId = 1L;
        //2.判断是否点赞,数据库判断
        Integer result = commentMapper.isBlogCommentLiked(userId, comment.getId());
        //数据中存在,就是用户已经点赞,将状态设置为true,默认是false
        if (result != null) {
            comment.setIsLike(true);
        }
    }

}

6.mapper层:

@Mapper
public interface CommentMapper {
    
    List<BlogComments> getAllComments(@Param("blogId") Integer blogId);
    
    Integer isBlogCommentLiked(@Param("userId") Long userId, @Param("commentId") Long commentId);
    
}

7.mapper.xml:

  <select id="getAllComments" resultType="com.liusaidh.morecomment.BlogComments">
        SELECT bl.*,
               u.icon,
               u.nick_name
        FROM `tb_blog_comments` bl
                 left join tb_user u
                           on u.id = bl.user_id
        where bl.blog_id = #{blogId}
        order by bl.id desc
    </select>

    <select id="isBlogCommentLiked" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM tb_comment_like WHERE user_id = #{userId} AND comment_id = #{commentId}
    </select>

以上就是评论回复功能的一种实现,欢迎大佬们的留言!

原文链接请点击这里!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2053109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

让JMeter测试数据生成更容易

让JMeter测试数据生成更容易 背景&#xff1a; 在软件测试过程中&#xff0c;为了确保系统的稳定性和可靠性&#xff0c;需要对各种场景进行全面的测试。而不同的场景往往需要各种各样的测试数据&#xff0c;这些数据需要具有一定的真实性和多样性&#xff0c;以模拟实际使用…

零基础小白实现C#调用halcon dll的过程,并测试程序证明C#halcon联合开发成功

本篇将介绍零基础小白实现C#调用halcon dll的过程&#xff0c;同时这其中涉及到很多知识&#xff0c;务必将HDevelop和VisualStudio安装成功。下面我将详细阐述C#调用halcon dll的过程&#xff0c;你的点赞和评论是我一直前行的动力。 1. C#调用Halcon DLL的过程 要在C#中调用…

选择TPM管理咨询公司,这几点是关键!

在这个日新月异的商业时代&#xff0c;企业的竞争力不仅体现在产品和服务上&#xff0c;更在于其内部管理的精细化与高效化。TPM作为提升企业综合生产效率的利器&#xff0c;正逐步成为众多企业转型升级的必然选择。然而&#xff0c;如何在众多TPM管理咨询公司中慧眼识珠&#…

嘉盛:股指、国债及商品期货分析

股指展望中证全指在2024年下半年可能迎来约20%的上涨空间。尽管市场估值较低&#xff0c;风险溢价仍维持在高位&#xff0c;这提升了指数的配置性价比。预计无风险利率将继续维持在较低水平&#xff0c;对中证全指估值产生积极影响。盈利方面&#xff0c;预计下半年中证全指EPS…

【广东】邀您共赴纷享销客生态伙伴大会

在数字化浪潮的驱动下&#xff0c;CRM行业正迎来前所未有的创新机遇。作为CRM领域的引领者&#xff0c;纷享销客特别举办“纷享销客2024生态伙伴大会&#xff08;广东站&#xff09;”。我们诚挚邀请各位生态伙伴莅临现场&#xff0c;共同探讨SaaS CRM行业的最新趋势&#xff0…

haproxy负载均衡+mysql读写分离

haproxy负载均衡 [roothaproxy01 ~]# yum -y install ntpdate [roothaproxy01 ~]# yum -y install ntp [roothaproxy01 ~]# systemctl start ntpd 安装haproxy [roothaproxy01 ~]# yum -y install ntpdate 配置文件的地址 [roothaproxy01 ~]# rpm -ql haproxy [roothap…

美摄科技携手蔚来汽车,共创用户出行新体验!

7月27日&#xff0c;蔚来举办了以 AI 为主线的 “NIO IN 2024 蔚来创新科技日”&#xff0c;此次活动展示了蔚来在智能电动汽车领域最新探索与成果&#xff0c;为中国乃至全球的智能汽车行业树立了新的标杆。当晚&#xff0c;央视《主播说联播》以“中国智能车在全球竞争的另一…

MIT6.s081 2021 Lab Multithreading

Uthread: switching between threads 思路 xv6 已经实现了进程的切换机制&#xff0c;本实验要求参考进程的切换&#xff0c;实现一个用户态线程的切换。 要实现线程切换&#xff0c;必然涉及上下文&#xff0c;即寄存器的保存和恢复&#xff0c;那么需要保存哪些寄存器&…

建筑工程项目管理系统-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

建筑工地安全检查

在现代化的建筑工地中&#xff0c;安全始终是至关重要的核心问题。随着科技的不断进步&#xff0c;凡尔码建筑工地安全系统应运而生&#xff0c;灵活根据施工现场管理要求搭建建筑工地安全系统各个模块&#xff0c;为施工安全带来了全新的保障。 如何注册建筑工地安全系统后台…

自动打电话软件给企业带来了什么?

使用机器人外呼系统肯定都是想要给自己企业带来好处和解决问题的&#xff0c;想让自己的企业有所改变&#xff0c;有更好的发展&#xff0c;所以才会选择使用机器人外呼系统。而它也确实没让大家失望&#xff0c;使用了机器人外呼系统之后确实有许多企业发生了很大改变和进步&a…

鲁棒性目标检测 TOP2 方案分享

关联比赛: ACM MM2021 安全AI挑战者计划第七期&#xff1a;鲁棒性标识检测 ACM MM2021 鲁棒性目标检测比赛 TOP 2 方案 ​ 赛题背景 在商品知识产权领域&#xff0c;知识产权体现为在线商品的设计和品牌。不幸的是&#xff0c;在每一天&#xff0c;存在着非法商户通过一些…

一文学会本地部署可视化应用JSONCrack并配置公网地址实现远程协作

文章目录 前言1. Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 前言 本文主要介绍如何在Linux环境使用Docker安装数据可视化工具JSONCrack&#xff0c;并结合cpolar内网穿透工具实现团队在…

[Python学习日记-9] Python中的运算符

简介 计算机可以进行的运算有很多种&#xff0c;但可不只加减乘除这么简单&#xff0c;运算按种类可分为算数运算、比较运算、逻辑运算、赋值运算、成员运算、身份运算、位运算&#xff0c;而本篇我们暂只介绍算数运算、比较运算、逻辑运算、赋值运算 算数运算 一、运算符描述…

猫头虎分享:Python库 Pillow 的简介、安装、用法详解入门教程

猫头虎分享&#xff1a;Python库 Pillow 的简介、安装、用法详解入门教程 &#x1f4da; 大家好&#xff0c;今天猫头虎要和大家分享一款非常实用的 Python 图像处理库——Pillow。 &#x1f4a1; Pillow 是 Python 中非常流行的图像处理库&#xff0c;基于已经停止维护的 PI…

CE修改器步骤9学习教程

一、打开教程&#xff0c;因为我的电脑是64位的&#xff0c;所以打开这个&#xff08;x86_64&#xff09; 二、 跳转到步骤9&#xff0c;并让ce读取其内存 三、使用之前教程学到的知识&#xff0c;找到四个角色的健康值地址&#xff08;找到即可&#xff0c;不必找基址&#xf…

【STM32 FreeRTOS】Tickless低功耗模式

STM32低功耗模式 STM32 提供了 3 种低功耗模式&#xff0c;以达到不同层次的降低功耗的目的 睡眠模式&#xff08;内核停止工作&#xff0c;外设仍在运行&#xff09;停止模式&#xff08;所有时钟都停止&#xff09;待机模式&#xff08; 1.8 V 内核电源关闭&#xff09; Fr…

Qt-认识Qt(1)

目录 QT是做什么的&#xff1f; 什么是QT GUI开发的各种技术方案 QT支持的平台 Qt的版本和优点 开发工具概述 Qt是做什么的&#xff1f; Qt是用来干嘛的&#xff1f; 什么是Qt Qt是⼀个跨平台的C图形用户界⾯应用程序框架。它为应用程序开发者提供了建立艺术级图形界⾯所…

SSH远程管理/TCP Wrappers访问控制

文章目录 SSH远程管理/TCP Wrappers访问控制SSH(Secure Shell)协议OpenSSH配置信息服务监听选项用户登录控制登录验证方式 常用目录---ssh 远程安全登录---scp 远程安全复制---sftp FTP上下载 配置密钥对验证环境配置ECDSA算法RSA算法RSA算法实操在centos7 IP:20.0.0.51操作一、…

【嵌入式linux开发】智能家居入门5:老版ONENET,多协议接入(QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派)

智能家居入门5&#xff08;QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派&#xff09; 前言一、QT界面设计二、云平台产品创建与连接三、下位机端QT代码总览&#xff1a;四、微信小程序端代码总览五、板端测试 前言 前四篇智能家居相关文章都是使用STM32作为主控&#xf…