Java实现评论回复功能的完整步骤
作者:☜好脾气先生✔ 发布时间:2023-08-23 20:42:45
前言
使用递归循环开发评论回复功能,适用于大部分的简单单体应用
评论功能或许是大多数的单体应用之中会用到的功能,我们会在自己所开发的项目之中进行集成该功能
大多数时候我们会将评论功能划分成以下几种:
单一型
嵌套型
两层型
一、分类方式
1、单一型
单一型评论方式就是日常论坛之中的盖楼的方式
用户只能根据所在的文章或者问题进行单一回复,评论之间没有互动
类似于问答形式。提出问题,然后回答,一对多关系。这些回答之间没有任何联系
2、嵌套型
嵌套型评论方式会对有回复的评论进行递归,会造成后端性能不佳,而且对于前端的展示也不是很友好
3、两层型
两层型评论方式就是除了一级评论之外,无论是对于该评论的回复还是对于回复的回复都统一在第二层
二、实现原理
就以最常见的博客来说,不同的分类方式实现原理不一样
1、单一型
我们只需要在评论的数据表格中添加博客id即可,查询出相对应的数据直接进行展示即可
create table `comment` (
`id` int(11) not null auto_increment comment '主键id',
`nickname` varchar(255) default null comment '评论者昵称',
`avatar` varchar(255) comment '评论头像',
`content` varchar(255) default null comment '评论的内容',
`blog_id` int(11) default null comment '评论的博客id',
primary key (`id`)
) comment '评论表';
在业务之中根据博客id查询出来,传递给前端展示出来即可
select * from comment where blog_id=#{blog_id}
2、嵌套型
嵌套型的评论方式所需要的数据结构是树状型的,评论多起来的话层级结构会变得很复杂,对于性能消耗也是很巨大,【不推荐】
实现原理为我们会在评论表之中添加一个【parent_id】字段,定义评论和回复为父子级的关系,评论为父级,回复为子级,默认为【-1】,表示为没有父级,
create table `comment` (
`id` int(11) not null auto_increment comment '主键id',
`nickname` varchar(255) default null comment '评论者昵称',
`avatar` varchar(255) comment '评论头像',
`content` varchar(255) default null comment '评论的内容',
`blog_id` int(11) default null comment '评论的博客id',
`parent_id` int(11) default '-1' comment '父级评论id',
primary key (`id`)
) comment '评论表';
需要使用递归和链表进行循环遍历插入回复
设计如下:
Content.java
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Integer id;
@ApiModelProperty(value = "用户昵称")
@TableField("nickname")
private String nickname;
@ApiModelProperty(value = "头像")
@TableField("avatar")
private String avatar;
@ApiModelProperty(value = "评论")
@TableField("comment")
private String comment;
@ApiModelProperty(value = "博客id ")
@TableField("blog_id")
private Integer blogId;
@ApiModelProperty(value = "回复评论id")
@TableField("parent_id")
private Integer parentId;
DTO设计
ContentDTO.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "评论模型")
@JsonIgnoreProperties(value = { "handler" })
public class ContentDTO {
private int id;
private String nickname;
private String content;
private List<ContentDTO> children;
}
使用mybatis做为持久层框架,编写sql查询语句进行嵌套查询,
<resultMap id="commentDTOMap" type="com.zukxu.items.comment.entity.ContentDTO">
<id property="id" column="comment_id"></id>
<result property="nickname" column="nickname"></result>
<result property="content" column="content"></result>
<association property="children"
select="com.zukxu.items.comment.mapper.ContentMapper.selectCommentById" column="{blogId=blog_id,parentId=comment_id}"
fetchType="lazy">
</association>
</resultMap>
<select id="selectCommentById" resultMap="commentDTOMap">
SELECT comment_id,nickname,content,blog_id,parent_id FROM blog WHERE blog_id = #{blogId} AND parent_id = #{parentId}
</select>
结果如下:
[
{
"id": "1309302063977304065",
"nickname": "1",
"content": "这次该可以了吧",
"children": [
{
"id": "1309319425866698753",
"nickname": "1",
"content": "好了?",
"children": []
}
]
},
{
"id": "1309341283121154994",
"nickname": "4",
"content": "为什么呢",
"children": [
{
"id": "1309373849414787073",
"nickname": "1",
"content": "好了?",
"children": []
},
{
"id": "1309308402422091778",
"nickname": "1",
"content": "可以了吧",
"children": []
},
{
"id": "1309373675783184385",
"nickname": "1",
"content": "好了?",
"children": [
{
"id": "1309373886580514817",
"nickname": "1",
"content": "???",
"children": []
}
]
}
]
}
]
结果会造成多重嵌套,不是很友好
3、两层型
比单一型多了互动的功能,比嵌套型更加简洁,方便操作管理
设计和嵌套型保持一致,只需要在查询出来数据之后对数据进行处理即可
将嵌套型转为两层型结构
处理每个父级评论的子级及其嵌套子级
public List<CommentDTO> findParent(List<CommentDTO> comments) {
for (CommentDTO comment : comments) {
// 防止checkForComodification(),而建立一个新集合
ArrayList<CommentDTO> fatherChildren = new ArrayList<>();
// 递归处理子级的回复,即回复内有回复
findChildren(comment, fatherChildren);
// 将递归处理后的集合放回父级的孩子中
comment.setChildren(fatherChildren);
}
return comments;
}
public void findChildren(CommentDTO parent, List<CommentDTO> fatherChildren) {
// 找出直接子级
List<CommentDTO> comments = parent.getChildren();
// 遍历直接子级的子级
for (CommentDTO comment : comments) {
// 若非空,则还有子级,递归
if (!comment.getChildren().isEmpty()) {
findChildren(comment, fatherChildren);
}
// 已经到了最底层的嵌套关系,将该回复放入新建立的集合
fatherChildren.add(comment);
// 容易忽略的地方:将相对底层的子级放入新建立的集合之后
// 则表示解除了嵌套关系,对应的其父级的子级应该设为空
comment.setChildren(new ArrayList<>());
}
}
}
最后的结果如下:
[
{
"id": "1309302063977304065",
"userId": "1",
"comment": "这次该可以了吧",
"children": [
{
"id": "1309319425866698753",
"userId": "1",
"comment": "好了?",
"children": []
}
]
},
{
"id": "1309341283121154994",
"userId": "4",
"comment": "为什么呢",
"children": [
{
"id": "1309373849414787073",
"userId": "1",
"comment": "好了?",
"children": []
},
{
"id": "1309308402422091778",
"userId": "1",
"comment": "可以了吧",
"children": []
},
{
"id": "1309373886580514817",
"userId": "1",
"comment": "???",
"children": []
},
{
"id": "1309373675783184385",
"userId": "1",
"comment": "好了?",
"children": []
}
]
}
]
绝大多数时候我们都会去使用两层型的评论方式做评论
来源:https://www.cnblogs.com/zukxu/p/13919501.html
猜你喜欢
- NumberFormat.getInstance()方法返回NumberFormat的一个实例(实际上是NumberFormat具体的一个子
- 建造者模式概述建造者模式(Builder Pattern)属于创建型模式。它是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同
- UI 妹纸又给了个图叫我做,我一看是这样的:我们首先把这个控件划分成 几个部分:1.底下部分的直线 :2.左右两边的半圆
- 骑缝章是用于往来业务合同,以确保合同真实、有效的印章加盖方法,是一种防范风险的重要方式。在Java程序中,可以通过使用工具来辅助加盖这种骑缝
- 具体不做详细介绍了,结合案例给大家做剖析,具体如下:条件“或”运算符 (||) 执行 bool 操作数的逻辑“或”运算,但仅在必要时才计算第
- 一、Flutter代码的启动起点我们在多数的业务场景下,使用的都是FlutterActivity、FlutterFragment。在在背后,
- 前言嗯。最近工程上遇到一个byte数组转换为int的问题,解决过程中遇到了几个坑,经过各种查资料终于还是解决了。撒花。Java的位运算以及b
- 一、饿汉式单例类public class Singleton { privat
- 本文介绍通过Java程序批量替换PDF中的指定文本内容。程序环境准备如下:程序使用环境如图,需要注意的是,本文使用了免费版的PDF jar工
- 1.选择一个WebService接口作测试假设 WebService url 为 http://ws.webxml.com.cn/WebSe
- 一、什么是IO流输入流和输出流。输入流:数据从数据源(文件)到程序(内存)的路径输出流:数据从程序(内存)到数据源(文件)的路径二、常用的文
- 1.关于JSR-303JSR-303规范(Bean Validation规范)提供了对 Java EE 和 Java SE 中的 Java
- 本文实例讲述了Java Swing实现简单的体重指数(BMI)计算器功能。分享给大家供大家参考,具体如下:BMI,Body Mass Ind
- 年纪大了,以前做过的东西过阵子还是会忘,今天使用jenkins持续集成工具时用到了eclipse上传新maven工程至svn,上传完毕后改了
- 一、注解是什么Java 注解用于为 Java 代码提供元数据,看完这句话也许你还是一脸懵逼,用人话说就是注解不直接影响你的代码执行,仅提供信
- 1、使用排序2、原理事实上Collections.sort方法底层就是调用的array.sort方法,而且不论是Collections.so
- Android 消息机制1.概述Android应用启动时,会默认有一个主线程(UI线程),在这个线程中会关联一个消息队列(MessageQu
- 从远端服务器获取变更数据的主要模式有两种:推(push)和拉(pull)。Push 模式简单来说就是服务端主动将数据变更信息推送给客户端,这
- 概述:@ResponseBody @RequestMapping(value="/download/{fileName:[a-zA
- 系统: lc android4.4 在做前后摄像头录像的时候,发现会出现花屏的时候,但不是必现,可能会在某一次重启之后会出现,而且出现之后会