模仿qq空间评论以及回复

本篇文章讲解如何模仿qq空间评论以及回复代码实现和表结构的设计

先看需求是怎么样的:

再看评论表结构的设计:

1
2
3
4
5
6
7
8
9
10
11
12
create table t_comment
(
id varchar(32) primary key, #主键Id
customer_id varchar(32) not null, #用户Id
parent_comment_id varchar(32) not null, #父评论Id
content_id varchar(32) not null, #评论对象的Id
type int(11), #评论对象的类型
content varchar(140) null, #评论内容
comment_date varchar(10) null, #评论日期
comment_time varchar(12) null, #评论时间
state int(11) null #评论的状态 0显示或者1不显示
);

在看实体的设计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Comment {
private String id;// id
private String customerId;// 用户id
private String parentCommentId;// 父评论id
private String contentId;// 内容id
private String content;// 评论内容
private String commetDate;// 评论日期
private String commetTime;// 评论时间
private Integer state;// 评论的状态
private Integer type;// 评论类型

//=================================
private List<Comment> replyComment; // 评论回复信息
private Customer customer;// 评论者信息
private Customer replyCustomer; // 回复评论的人

// 省略了getter/setter
}

分析问题的解决方案,我先说说我解决问题的方案:

首先根据我们要评论的对象得Id,查询出评论该对象的所有父评论;

然后根据父评论的Id去查询子评论的信息。

分析完毕后:我们开始写sql:

下面的t_item 为评论对象中的一种类型, 他的类型码为1 所有tco.type = 1

1
2
3
4
5
6
7
8

SELECT tco.* FROM t_comment tco
LEFT JOIN t_item tit ON tco.content_id = tit.id
WHERE tco.parent_comment_id IS NULL
AND tco.type = 1
AND comment.state = 0
AND tit.id = #{itemId}
ORDER BY tco.comment_date DESC, tco.comment_time DESC

以上为查询所有的父评论信息;

然后我们再根据父评论的Id查询子评论的信息:

1
2
3
SELECT tco.* FROM t_comment tco 
WHERE tco.parent_comment_id = #{parentCommentId}
AND comment.state = 0

以上是查询子评论的信息

通过上面的sql,我们只是简单的查询了语句:

我们在看看java中怎么去构建评论的集合

dao的编写:就是把以上的两个sql语句变成两个方法。

根据评论对象的Id查询所有父评论:List\ findParentCommentByItemId(String itemId, int offset, int limit);

根据父评论的Id查询所有子评论:List\ findReplyCommentByCommentId(String parentCommentId, int offset, int limit);

然后我们看service怎么实现:

根据评论对象的Id查询所有评论:List\ findCommentByItemId(String itemId, int offset, int limit);

具体的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
public List<Comment> findCommentByItemId(String itemId, int offset, int limit) {
List<Comment> comments = commentDao.findParentCommentByItemId(itemId, offset, limit);
for(Comment comment : comments){
List<Comment> replys = new ArrayList<Comment>(); // 实例化回复的集合
comment.setReplyComment(replys); // 设置评论的回复集合
String customerId = comment.getCustomerId(); // 获取评论的人的Id
Customer customer = customerService.getCustomerByCustomerId(customerId); // 通过评论人的Id获取评论人的信息
if(customer != null) customer.setPassword(null); // 把评论的人的密码设置为空
comment.setCustomer(customer); // 设置评论的人的信息
buildReplyComment(comment, replys, offset, limit); // 构建评论与回复信息
}
return comments;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 构建评论与回复评论的关系
* @param comment
* @param offset
* @param limit
*/
private void buildReplyComment(Comment comment, List<Comment> replys, int offset, int limit){
List<Comment> replyComments = commentDao.findReplyCommentByCommentId(comment.getId(), offset, limit); // 获取评论的所有回复
replys.addAll(replyComments); // 把所有的回复添加到评论实例化的回复集合中
for(Comment c : replyComments){ // 遍历回复中的回复
String customerId = c.getCustomerId(); // 获取回复人的id
Customer replyCustomer = customerService.getCustomerByCustomerId(customerId); // 获取回复人信息
if(replyCustomer != null) replyCustomer.setPassword(null); // 把回复人的密码设置为空
Customer customer = customerService.getCustomerByCustomerId(comment.getCustomerId()); // 获取评论人的信息
c.setCustomer(customer); // 设置评论人的信息
c.setReplyCustomer(replyCustomer); // 设置回复人的信息
buildReplyComment(c, replys, offset, limit); // 递归调用
}
}

最后看页面的展示:

1
2
3
4
5
6
7
8
9
10
11
12
13

<c:forEach var="comment" items="${itemComments}">
<c:out value="${comment.customer.nickName}"/>:
<span class="ellipsis">${comment.content}</span>
<span class="ellipsis">(<c:out value="${comment.commetDate}" />)</span>
<c:if test="${!empty comment.replyComment}">
<c:forEach var="reply" items="${comment.replyComment}">
${reply.replyCustomer.nickName}回复了${reply.customer.nickName}
<span class="ellipsis">${reply.content}</span>
<span class="ellipsis">(<c:out value="${comment.commetDate}" />)</span>
</c:forEach>
</c:if>
</c:forEach>

样式方面需要调整,大体的功能就这个样子了,

还有不足请指出来,谢谢