最近刷微博,看抖音发现最有趣的就是看评论了,然后想着自己的项目正好差一个评论模块,所以自己就写了一个点赞评论模块,好了,废话不多说,直接进入主题。
项目地址:点击访问 欢迎各位fork,star
1.先从前端入手,看看前端需要哪些数据(这里以csdn博客评论为列),以博客为例,一篇博客下面可能会有多条评论。每条评论其实分为两种,一种是直接对博客的评论,称之为父评论;另一种是对已有评论的评论(博主回复),称为子评论。点赞就比较好区分了,无论是父评论还是子评论或者博客评论,点赞只要关联被评论对象的唯一标识和点赞用户的id就可以了。一篇博客可以有多条评论,一条父评论,可以有多条子评论。所以博客与评论的关系为一对多,父评论与子评论的关系也是一对多,一个点赞对应一个点赞对象,所以点赞与点赞的对象为一对一,由此则可以设置数据库表。
由此可以得出,评论分为两种:一种为父评论,另一种为子评论。则:
一条父评论至少拥有的属性为:评论的唯一标识,评论对象的id,评论者的id,评论者名字,评论者的头像,评论的内容,评论的点赞数,评论发布的时间
一条子评论至少拥有的属性为:父评论的唯一标识,评论者的id,评论者名字,评论者的头像,,被评论者的id,被评论者名字,被评论者的头像,评论的内容,评论的点赞数,评论发布的时间
一条评论的点赞至少拥有的属性为:被评论对象的唯一标识,用户的唯一标识,点赞状态
由此就可以设计数据库表了。
父评论表(comments_root):
id | 主键 |
---|---|
type | 评论的类型,评论博客,评论下载资源等 |
owner_id | 评论对象的id |
from_id | 评论者的id |
from_name | 评论者的名字 |
from_avatar | 评论者的头像链接 |
like_num | 评论的点赞数 |
content | 评论的内容 |
comment_id | 评论的唯一标识 |
create_time | 评论的发布时间 |
子评论表(comments_reply):
id | 用来关联父评论的主键id |
---|---|
comment_id | 子评论的唯一标识 |
from_id | 评论者的id |
from_name | 评论者的名字 |
from_avatar | 评论者的头像链接 |
to_id | 被评论者的id |
to_name | 被评论者的名字 |
to_avatar | 被评论者的头像链接 |
like_num | 评论的点赞数 |
content | 评论的内容 |
create_time | 评论的发布时间 |
点赞表(liked)
id | 主键 |
---|---|
obj_id | 对应对象的id,可以是文章id或者评论id等 |
user_id | 点赞者的id |
like_status | 点赞的状态,1标识已赞,0标识取消赞 |
(1)创建springboot项目,然后在项目根目录下的 pom.xml 文件中添加如下依赖:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.5.RELEASE
com.tl666
comments
0.0.1-SNAPSHOT
comments
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.1
mysql
mysql-connector-java
5.1.18
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.apache.commons
commons-lang3
3.4
org.springframework.boot
spring-boot-maven-plugin
src/main/java
**/*.xml
true
(2)编辑配置文件application.yml或application.properties中添加配置,博主用的是yml格式的配置文件,它格式比较清晰,application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1/comments?characterEncoding=utf-8&useSSL=false
mybatis:
configuration:
mapUnderscoreToCamelCase: true #开启mabatis的驼峰命名法
(3)然后在springboot中写好对应的实体类即可
(4)然后写数据持久化层CommentsMapper.java
package com.tl666.comments.mapper;
import com.tl666.comments.pojo.CommentsRoot;
import com.tl666.comments.pojo.CommentsReply;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CommentsMapper {
/**
* 获取该文章或资源下的所有评论
* @param ownerId 文章或资源id
* @return
*/
// @Select("select * from comments_info where owner_id = #{ownerId}")
List findByOwnerId(String ownerId);
/**
* 添加子评论或回复评论
* @param commentsReply
* @return
*/
@Insert("insert into comments_reply (id,comment_id,from_id,from_name,from_avatar,to_id,to_name,to_avatar,like_num,content,create_time) " +
"values(#{id},#{commentId},#{fromId},#{fromName},#{fromAvatar},#{toId},#{toName},#{toAvatar},#{likeNum},#{content},#{createTime})")
boolean addSonComments(CommentsReply commentsReply);
/**
* 添加父评论
* @param commentsRoot
* @return
*/
// @Insert("insert into comments_root (id,comment_id,owner_id,type,from_id,from_name,from_avatar,like_num,content,create_time) " +
// "values(#{id},#{commentId},#{ownerId},#{type},#{fromId},#{fromName},#{fromAvatar},#{likeNum},#{content},#{createTime})")
boolean addRootComments(CommentsRoot commentsRoot);
}
对应的mybatis的xml文件CommentsMapper .xml如下
select LAST_INSERT_ID();
insert into comments_root (id,comment_id,owner_id,type,from_id,from_name,from_avatar,like_num,content,create_time)
values(#{id},#{commentId},#{ownerId},#{type},#{fromId},#{fromName},#{fromAvatar},#{likeNum},#{content},#{createTime})
(5)控制层的核心代码如下
/**
* 添加父评论 直接对标文章,资源等下面的评论
* @param commentsRoot
* @return
*/
@PostMapping("addRootComments")
public ResultDT addRootComments(CommentsRoot commentsRoot) {
log.info("1" + commentsRoot.toString());
if (commentsRoot.getContent().length() != 0) {
commentsRoot.setCommentId(UUID.randomUUID().toString().replaceAll("-", ""));//设置评论唯一标识
commentsRoot.setCreateTime(new Date());//设置添加评论时间
log.info("2" + commentsRoot);
boolean b = commentService.addRootCommentsService(commentsRoot); //调用service方法来完成评论的存储
log.info("3" + commentsRoot.toString());
if (b) {
return ResultDTUtils.success(commentsRoot);
}
}
//评论内容为空 返回错误信息
return ResultDTUtils.error(ResultDTUtils.COMMENT_ERROR, "addError");
}
/**
* 添加子评论,对应父评论
* @param commentsReply
* @return
*/
@PostMapping("addSonComments")
public ResultDT addSonComments(CommentsReply commentsReply) {
log.info("1" + commentsReply.toString());
if (commentsReply.getContent().length() != 0) {
commentsReply.setCommentId(UUID.randomUUID().toString().replaceAll("-", ""));//设置评论唯一标识
commentsReply.setCreateTime(new Date());
log.info("2" + commentsReply);
boolean b = commentService.addSonCommentsService(commentsReply);
log.info("3" + commentsReply.toString());
if (b) {
return ResultDTUtils.success(commentsReply);
}
}
return ResultDTUtils.error(ResultDTUtils.COMMENT_ERROR, "addError");
}
/**
* 根据资源ID来回去该资源的所有评论
* @param request
* @return
*/
@GetMapping("getListByOwnerId")
public ResultDT getListByOwnerId(HttpServletRequest request) {
String ownerId = request.getParameter("owner_id");
log.info(ownerId);
List byOwnerIdService = commentService.findByOwnerIdService(ownerId);
log.info(byOwnerIdService.toString());
return ResultDTUtils.success(byOwnerIdService);
}
(6)评论效果如下图所示:
点击回复输入框会出现回复的对象的名字
从后端获取的评论数据
好了本期的内容就到这里了,由于这个项目是临时起意写的,或许有一些地方不足,但是博主正在努力更新完善功能,本项目已经放到Github上面去了,欢迎各位fork,star。
项目地址:点击访问
我们下期再见!嘿嘿