前言:
技术栈: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>
以上就是评论回复功能的一种实现,欢迎大佬们的留言!
原文链接请点击这里!