commentFunction-My-blog: 这个一个实现了简单低配版的评论区功能的后端程序 (gitee.com)
https://gitee.com/flowers-bloom-is-the-sea/commentFunction-My-blog
视频介绍:
https://www.bilibili.com/video/BV1Kh411N7iy/
2、评论区功能-表的设计+java查询实现+接口测试https://www.bilibili.com/video/BV1Su411t7XG/
技术栈:Springboot+mysql
一、创建的数据表:
CREATE TABLE `blog_comment` (
`blog_id` bigint(20) NOT NULL,
`comment_user_id` bigint(20) NOT NULL,
`comment_detail` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`deep` int(11) NOT NULL,
`answer_id` bigint(20) NOT NULL,
`status` bit(1) NOT NULL DEFAULT b'1',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `uniqe_key_blog_id` (`blog_id`),
KEY `uniqe_key_comment_user_id` (`comment_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
二、核心实现:
1、controller
@GetMapping("/{id}")
@ApiOperation("blogComment信息,获取博客id这篇博客的所有博客的评论信息")
public Result get(@PathVariable("id") Long id){
List<BlogCommentDto> blogComments = blogCommentService.getTreeByBlogId(id);
return Result.ok(blogComments);
}
2、实现类:
@Override//通过博客id获取当前博客的所有评论。评论肯定是确定了的,而且有子评论,情况较为复杂,下面是自己的一个实现
public List<BlogCommentDto> getTreeByBlogId(Long blogId) {
//1、首先获取根评论链表rootBlogComments
List<BlogComment> rootBlogComments = getBlogCommentsByBlogIdWithDeepOrderByAsc(blogId, 0);
//2、再次将首先获取根评论链表rootBlogComments里的BlogComment封装到dto里面,因为BlogComment没有子评论链表属性:nodes
List<BlogCommentDto> rootBlogDtoComments = getBlogCommentDtoListByBlogComments(rootBlogComments);
//3、往根评论链表rootBlogDtoComments添加子评论,递归添加,每次递归则将子评论作为递归函数的根评论
fillRootCommentsByBlogIdWithDeepOrderByAsc(blogId,1,rootBlogDtoComments);
//4、返回结果
return rootBlogDtoComments;
}
//往根节点评论添加子评论
private void fillRootCommentsByBlogIdWithDeepOrderByAsc(Long blogId,int deep,List<BlogCommentDto> rootBlogComments) {
//先获取下一级评论列表
List<BlogComment> sonBlogComments = getBlogCommentsByBlogIdWithDeepOrderByAsc(blogId, deep);
//判断子评论链表是否存在
if (sonBlogComments == null || sonBlogComments.size() == 0) return;
//逐一封装为dto
List<BlogCommentDto> sonCommentDtoList = getBlogCommentDtoListByBlogComments(sonBlogComments);
//根评论字典:作用定位root评论的索引
HashMap<Long,Integer> rootIndexMap = getIndex(rootBlogComments);
//往根评论里添加子评论
for (BlogCommentDto blogCommentDto : sonCommentDtoList) {
//先找到根节点评论到底是哪一个
Long answerId = blogCommentDto.getAnswerId();
//找到rootBlogComments里的定位
int index = rootIndexMap.get(answerId);
//通过rootIndexMap这个根评论字典寻找root.commentId=ansId的根评论
BlogCommentDto rootBlogComment = rootBlogComments.get(index);
List<BlogComment> nodes = rootBlogComment.getNodes();
if (nodes == null) {
nodes = new LinkedList<>();
rootBlogComment.setNodes(nodes);
}
//添加子评论
nodes.add(blogCommentDto);
}
//每次递归则将子评论链表sonCommentDtoList作为递归函数的根评论链表
fillRootCommentsByBlogIdWithDeepOrderByAsc(blogId,deep + 1,sonCommentDtoList);
}
//根评论的定位字典
private HashMap<Long, Integer> getIndex(List<BlogCommentDto> blogComments) {
HashMap<Long, Integer> indexMap = new HashMap<>();
for(int index = 0 ; index < blogComments.size();index++){
indexMap.put(blogComments.get(index).getCommentUserId(),index);
}
return indexMap;
}
private List<BlogComment> getBlogCommentsByBlogIdWithDeepOrderByAsc(Long blogId,int deep){
LambdaQueryWrapper<BlogComment> queryWrapper = new LambdaQueryWrapper<>();//asc升序,从小到大
queryWrapper.eq(BlogComment::getBlogId,blogId).eq(BlogComment::getDeep,deep).orderByAsc(BlogComment::getCreateTime);
return baseMapper.selectList(queryWrapper);
}
//将BlogComments封装成为BlogCommentDto
private List<BlogCommentDto> getBlogCommentDtoListByBlogComments(List<BlogComment> blogComments) {
List<BlogCommentDto> blogCommentDtoList = new ArrayList<>(blogComments.size());
for (BlogComment blogComment :blogComments) {
BlogCommentDto blogCommentDto = new BlogCommentDto();
BeanUtils.copyProperties(blogComment, blogCommentDto);
blogCommentDtoList.add(blogCommentDto);
}
return blogCommentDtoList;
}
三、测试接口:
localhost:8081/blogComment/1
结果:
{
"success": true,
"errorMsg": null,
"data": [
{
"blogId": 1,
"commentUserId": 1,
"commentDetail": "a",
"deep": 0,
"answerId": 0,
"status": true,
"createTime": "2023-06-25T22:13:35",
"updateTime": "2023-06-25T22:13:35",
"nodes": null
},
{
"blogId": 1,
"commentUserId": 2,
"commentDetail": "b",
"deep": 0,
"answerId": 0,
"status": true,
"createTime": "2023-06-25T22:17:00",
"updateTime": "2023-06-25T22:17:00",
"nodes": [
{
"blogId": 1,
"commentUserId": 2,
"commentDetail": "bb",
"deep": 1,
"answerId": 2,
"status": true,
"createTime": "2023-06-25T22:20:22",
"updateTime": "2023-06-25T22:20:22",
"nodes": null
},
{
"blogId": 1,
"commentUserId": 3,
"commentDetail": "cc",
"deep": 1,
"answerId": 2,
"status": true,
"createTime": "2023-06-25T22:21:23",
"updateTime": "2023-06-25T22:21:23",
"nodes": [
{
"blogId": 1,
"commentUserId": 5,
"commentDetail": "ee",
"deep": 2,
"answerId": 3,
"status": true,
"createTime": "2023-06-25T22:22:04",
"updateTime": "2023-06-25T22:22:04",
"nodes": null
}
]
},
{
"blogId": 1,
"commentUserId": 4,
"commentDetail": "dd",
"deep": 1,
"answerId": 2,
"status": true,
"createTime": "2023-06-25T22:21:35",
"updateTime": "2023-06-25T22:21:35",
"nodes": null
}
]
},
{
"blogId": 1,
"commentUserId": 3,
"commentDetail": "c",
"deep": 0,
"answerId": 0,
"status": true,
"createTime": "2023-06-25T22:17:21",
"updateTime": "2023-06-25T22:17:21",
"nodes": null
},
{
"blogId": 1,
"commentUserId": 4,
"commentDetail": "d",
"deep": 0,
"answerId": 0,
"status": true,
"createTime": "2023-06-25T22:17:47",
"updateTime": "2023-06-25T22:17:47",
"nodes": null
},
{
"blogId": 1,
"commentUserId": 5,
"commentDetail": "e",
"deep": 0,
"answerId": 0,
"status": true,
"createTime": "2023-06-25T22:17:57",
"updateTime": "2023-06-25T22:17:57",
"nodes": null
}
],
"total": null
}
四、其他
因为之前没学过评论区的功能,于是自己想着去实现一下,正好自己有思路,于是就来实现一个案例了,当然了这个还是没有进行优化,如果要应用到实际生产环境里,那么还需要各种高并发测试以及缓存功能的添加,可以基于这个程序的基础上进行优化。
我也会继续优化下去,敬请期待吧。