Java實(shí)現(xiàn)評(píng)論回復(fù)功能的完整步驟
前言
使用遞歸循環(huán)開(kāi)發(fā)評(píng)論回復(fù)功能,適用于大部分的簡(jiǎn)單單體應(yīng)用
評(píng)論功能或許是大多數(shù)的單體應(yīng)用之中會(huì)用到的功能,我們會(huì)在自己所開(kāi)發(fā)的項(xiàng)目之中進(jìn)行集成該功能
大多數(shù)時(shí)候我們會(huì)將評(píng)論功能劃分成以下幾種:
- 單一型
- 嵌套型
- 兩層型
一、分類方式
1、單一型
單一型評(píng)論方式就是日常論壇之中的蓋樓的方式
用戶只能根據(jù)所在的文章或者問(wèn)題進(jìn)行單一回復(fù),評(píng)論之間沒(méi)有互動(dòng)
類似于問(wèn)答形式。提出問(wèn)題,然后回答,一對(duì)多關(guān)系。這些回答之間沒(méi)有任何聯(lián)系

2、嵌套型
嵌套型評(píng)論方式會(huì)對(duì)有回復(fù)的評(píng)論進(jìn)行遞歸,會(huì)造成后端性能不佳,而且對(duì)于前端的展示也不是很友好

3、兩層型
兩層型評(píng)論方式就是除了一級(jí)評(píng)論之外,無(wú)論是對(duì)于該評(píng)論的回復(fù)還是對(duì)于回復(fù)的回復(fù)都統(tǒng)一在第二層

二、實(shí)現(xiàn)原理
就以最常見(jiàn)的博客來(lái)說(shuō),不同的分類方式實(shí)現(xiàn)原理不一樣
1、單一型
我們只需要在評(píng)論的數(shù)據(jù)表格中添加博客id即可,查詢出相對(duì)應(yīng)的數(shù)據(jù)直接進(jìn)行展示即可
create table `comment` ( `id` int(11) not null auto_increment comment '主鍵id', `nickname` varchar(255) default null comment '評(píng)論者昵稱', `avatar` varchar(255) comment '評(píng)論頭像', `content` varchar(255) default null comment '評(píng)論的內(nèi)容', `blog_id` int(11) default null comment '評(píng)論的博客id', primary key (`id`) ) comment '評(píng)論表';
在業(yè)務(wù)之中根據(jù)博客id查詢出來(lái),傳遞給前端展示出來(lái)即可
select * from comment where blog_id=#{blog_id}
2、嵌套型
嵌套型的評(píng)論方式所需要的數(shù)據(jù)結(jié)構(gòu)是樹(shù)狀型的,評(píng)論多起來(lái)的話層級(jí)結(jié)構(gòu)會(huì)變得很復(fù)雜,對(duì)于性能消耗也是很巨大,【不推薦】
實(shí)現(xiàn)原理為我們會(huì)在評(píng)論表之中添加一個(gè)【parent_id】字段,定義評(píng)論和回復(fù)為父子級(jí)的關(guān)系,評(píng)論為父級(jí),回復(fù)為子級(jí),默認(rèn)為【-1】,表示為沒(méi)有父級(jí),
create table `comment` ( `id` int(11) not null auto_increment comment '主鍵id', `nickname` varchar(255) default null comment '評(píng)論者昵稱', `avatar` varchar(255) comment '評(píng)論頭像', `content` varchar(255) default null comment '評(píng)論的內(nèi)容', `blog_id` int(11) default null comment '評(píng)論的博客id', `parent_id` int(11) default '-1' comment '父級(jí)評(píng)論id', primary key (`id`) ) comment '評(píng)論表';
需要使用遞歸和鏈表進(jìn)行循環(huán)遍歷插入回復(fù)
設(shè)計(jì)如下:
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 = "評(píng)論")
@TableField("comment")
private String comment;
@ApiModelProperty(value = "博客id ")
@TableField("blog_id")
private Integer blogId;
@ApiModelProperty(value = "回復(fù)評(píng)論id")
@TableField("parent_id")
private Integer parentId;
DTO設(shè)計(jì)
ContentDTO.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "評(píng)論模型")
@JsonIgnoreProperties(value = { "handler" })
public class ContentDTO {
private int id;
private String nickname;
private String content;
private List<ContentDTO> children;
}
使用mybatis做為持久層框架,編寫sql查詢語(yǔ)句進(jìn)行嵌套查詢,
<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>
結(jié)果如下:
[
{
"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": []
}
]
}
]
}
]
結(jié)果會(huì)造成多重嵌套,不是很友好
3、兩層型
比單一型多了互動(dòng)的功能,比嵌套型更加簡(jiǎn)潔,方便操作管理
設(shè)計(jì)和嵌套型保持一致,只需要在查詢出來(lái)數(shù)據(jù)之后對(duì)數(shù)據(jù)進(jìn)行處理即可
將嵌套型轉(zhuǎn)為兩層型結(jié)構(gòu)
處理每個(gè)父級(jí)評(píng)論的子級(jí)及其嵌套子級(jí)
public List<CommentDTO> findParent(List<CommentDTO> comments) {
for (CommentDTO comment : comments) {
// 防止checkForComodification(),而建立一個(gè)新集合
ArrayList<CommentDTO> fatherChildren = new ArrayList<>();
// 遞歸處理子級(jí)的回復(fù),即回復(fù)內(nèi)有回復(fù)
findChildren(comment, fatherChildren);
// 將遞歸處理后的集合放回父級(jí)的孩子中
comment.setChildren(fatherChildren);
}
return comments;
}
public void findChildren(CommentDTO parent, List<CommentDTO> fatherChildren) {
// 找出直接子級(jí)
List<CommentDTO> comments = parent.getChildren();
// 遍歷直接子級(jí)的子級(jí)
for (CommentDTO comment : comments) {
// 若非空,則還有子級(jí),遞歸
if (!comment.getChildren().isEmpty()) {
findChildren(comment, fatherChildren);
}
// 已經(jīng)到了最底層的嵌套關(guān)系,將該回復(fù)放入新建立的集合
fatherChildren.add(comment);
// 容易忽略的地方:將相對(duì)底層的子級(jí)放入新建立的集合之后
// 則表示解除了嵌套關(guān)系,對(duì)應(yīng)的其父級(jí)的子級(jí)應(yīng)該設(shè)為空
comment.setChildren(new ArrayList<>());
}
}
}
最后的結(jié)果如下:
[
{
"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": []
}
]
}
]
絕大多數(shù)時(shí)候我們都會(huì)去使用兩層型的評(píng)論方式做評(píng)論
總結(jié)
到此這篇關(guān)于Java實(shí)現(xiàn)評(píng)論回復(fù)功能的文章就介紹到這了,更多相關(guān)Java實(shí)現(xiàn)評(píng)論回復(fù)功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用SpringMVC編寫一個(gè)HelloWorld的詳細(xì)過(guò)程
SpringMVC是Spring的一個(gè)后續(xù)產(chǎn)品,是Spring的一個(gè)子項(xiàng)目<BR>SpringMVC?是?Spring?為表述層開(kāi)發(fā)提供的一整套完備的解決方案,本文我們將用SpringMVC編寫一個(gè)HelloWorld,文中有詳細(xì)的編寫過(guò)程,需要的朋友可以參考下2023-08-08
JAVA實(shí)現(xiàn)的簡(jiǎn)單萬(wàn)年歷代碼
這篇文章主要介紹了JAVA實(shí)現(xiàn)的簡(jiǎn)單萬(wàn)年歷代碼,涉及Java日期操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
java文件重命名(文件批量重命名)實(shí)例程序代碼分享
這篇文章主要介紹了java文件重命名的程序代碼,大家參考使用吧2013-12-12
Java中volatile關(guān)鍵字的作用與用法詳解
volatile關(guān)鍵字雖然從字面上理解起來(lái)比較簡(jiǎn)單,但是要用好不是一件容易的事情。這篇文章主要介紹了Java中volatile關(guān)鍵字的作用與用法詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09
通過(guò)實(shí)例了解java TransferQueue
這篇文章主要介紹了TransferQueue實(shí)例,下面小編和大家一起來(lái)學(xué)習(xí)一下2019-05-05
Spring FactoriesLoader機(jī)制實(shí)例詳解
這篇文章主要介紹了Spring FactoriesLoader機(jī)制實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
SpringBoot整合POI實(shí)現(xiàn)Excel文件讀寫操作
EasyExcel是一個(gè)基于Java的、快速、簡(jiǎn)潔、解決大文件內(nèi)存溢出的Excel處理工具,這篇文章主要介紹了SpringBoot整合POI實(shí)現(xiàn)Excel文件讀寫操作,首先準(zhǔn)備環(huán)境進(jìn)行一系列操作,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10
解決運(yùn)行jar包出錯(cuò):ClassNotFoundException問(wèn)題
這篇文章主要介紹了解決運(yùn)行jar包出錯(cuò):ClassNotFoundException問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java查詢MongoDB數(shù)據(jù)庫(kù)案例大全
這篇文章主要給大家介紹了關(guān)于Java查詢MongoDB數(shù)據(jù)庫(kù)的一些相關(guān)案例,Java可以使用MongoDB的官方Java驅(qū)動(dòng)程序來(lái)連接和操作MongoDB數(shù)據(jù)庫(kù),需要的朋友可以參考下2023-07-07

