JAVA设计评论列表数据格式

Posted 程序猿谢哥哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA设计评论列表数据格式相关的知识,希望对你有一定的参考价值。

需求:

用户可以评论,也可以回复评论,其他用户还可以评论、回复评论。

评论表实体(ArticleComment)

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * 评论表
 *
 * @author create by xiegege
 * @date 2021/6/17 16:00
 * 表中的levelFlag为评论等级,1表示一级,主要是文章的直接评论, 2表示二级,主要是主题评论的回复
 **/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_article_comment")
@ApiModel(value = "ArticleComment对象", description = "评论表")
public class ArticleComment {

    @ApiModelProperty(value = "评论主键")
    @TableId("id")
    private Long id;

    @ApiModelProperty(value = "评论的文章Id")
    @TableField("article_id")
    private Long articleId;

    @ApiModelProperty(value = "父级评论Id")
    @TableField("parent_id")
    private Long parentId;

    @ApiModelProperty(value = "评论内容")
    @TableField("comment_content")
    private String commentContent;

    @ApiModelProperty(value = "评论等级")
    @TableField("level_flag")
    private Integer levelFlag;

    @ApiModelProperty(value = "点赞数")
    @TableField("upvote_count")
    private Integer upvoteCount;

    @ApiModelProperty(value = "是否置顶评论(0否,1是)")
    @TableField("whether_top")
    private Integer whetherTop;

    @ApiModelProperty(value = "用户Id")
    @TableField("user_id")
    private Long userId;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private String createTime;
}

建表sql语句

CREATE TABLE `sys_article_comment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '评论主键',
  `article_id` bigint(20) NOT NULL COMMENT '评论的文章Id',
  `parent_id` bigint(20) NOT NULL COMMENT '父级评论Id',
  `comment_content` varchar(255) NOT NULL COMMENT '评论内容',
  `level_flag` int(10) NOT NULL COMMENT '评论等级:1主评论,2子评论',
  `upvote_count` int(10) NOT NULL DEFAULT '0' COMMENT '评论点赞数量',
  `whether_top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶评论(0否,1是)',
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `index_id` (`article_id`,`parent_id`,`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

我的表设计的很简单,因为本身项目就很简单,而且估计流量也不多,需求没有那么的大,别的话不说,如果你自己有更复杂的需求,可以自己再设计,我只是提供一个思路;

前端需求:
类似于这种:

/**
          张三 评论:你好
                谢哥哥 回复 张三: 你好
                    王五 回复 谢哥哥: 很好很好
                赵六 回复 张三:你好
          田七 评论:辣鸡
                谢哥哥 回复 田七: 你才是辣鸡
**/

抱歉,我以这种简陋的方式大家展示(手动捂脸)~

既然需求搞清楚了,基本就可以操作了,看这个前端需求,和一个数据结构有点像,就是树形结构,具体看下面的图(其实是手打的)

/**
*                                root
*                          /      |     \\
*                         1       2      3
*                     / | | | \\
*                    4  5 6 7  8
**/

所以就直接以树的形式进行组装就行了

评论表数据结构组装VO(CommentNodeTreeVo)

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * 评论表数据结构组装
 *
 * @author create by xiegege
 * @date 2021/6/17 16:10
 **/
@Data
public class CommentNodeTreeVo {

    @ApiModelProperty(value = "评论表id")
    private Long commentId;

    @ApiModelProperty(value = "用户Id")
    private Long userId;

    @ApiModelProperty(value = "用户头像")
    private String avatar;

    @ApiModelProperty(value = "用户昵称")
    private String nickName;

    @ApiModelProperty(value = "评论内容")
    private String commentContent;

    @ApiModelProperty(value = "点赞数")
    private Integer upvoteCount;

    @ApiModelProperty(value = "是否置顶评论(0否,1是)")
    private Integer whetherTop;

    @ApiModelProperty(value = "创建时间")
    private String createTime;

    private List<CommentNodeTreeVo> commentNodeTreeVos;
}

其中commentNodeTreeVos为root的下一层的节点集合;

Controller

import com.xgg.common.result.AjaxResult;
import com.xgg.javacode.model.vo.CommentNodeTreeVo;
import com.xgg.javacode.service.ArticleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xiegege
 * @date 2021/6/17 17:20
 */
@Api(tags = "文章相关api")
@RequestMapping("/article")
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class ArticleController {

    private final ArticleService articleService;

    @ApiOperation(value = "获取评论列表", response = CommentNodeTreeVo.class)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "articleId", dataType = "long", required = true, value = "文章id"),
            @ApiImplicitParam(paramType = "path", name = "pageNo", dataType = "int", required = true, value = "页码"),
            @ApiImplicitParam(paramType = "path", name = "pageSize", dataType = "int", required = true, value = "每页大小")
    })
    @GetMapping("findComment/{articleId}/{pageNo}/{pageSize}")
    public AjaxResult findComment(@PathVariable Long articleId, @PathVariable Integer pageNo, @PathVariable Integer pageSize) {
        return AjaxResult.success(articleService.findComment(articleId, pageNo, pageSize));
    }
}

Service(具体业务实现)

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xgg.common.result.PageInfoResult;
import com.xgg.javacode.mapper.ArticleMapper;
import com.xgg.javacode.model.vo.CommentNodeTreeVo;
import com.xgg.javacode.service.ArticleService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author xiegege
 * @date 2021/6/17 17:25
 */
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class ArticleServiceImpl implements ArticleService {

    private final ArticleMapper articleMapper;

    @Override
    public PageInfoResult<CommentNodeTreeVo> findComment(Long articleId, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<CommentNodeTreeVo> list = articleMapper.findComment(articleId);
        PageInfo<CommentNodeTreeVo> pageInfo = new PageInfo<>(list);
        List<CommentNodeTreeVo> pageInfoList = pageInfo.getList();
        for (CommentNodeTreeVo commentNodeTreeVo : pageInfoList) {
            deepSearch(commentNodeTreeVo);
        }
        return PageInfoResult.getPageInfoResult(pageInfo);
    }

    /**
     * 递归进行求树形节点
     *
     * @param commentNodeTreeVo 评论树
     */
    private void deepSearch(CommentNodeTreeVo commentNodeTreeVo) {
        if (commentNodeTreeVo != null) {
            // 查询子评论集合
            List<CommentNodeTreeVo> commentNodeTreeVos = articleMapper.findChildComment(commentNodeTreeVo.getCommentId());
            if (!CollectionUtils.isEmpty(commentNodeTreeVos)) {
                for (CommentNodeTreeVo vo : commentNodeTreeVos) {
                    commentNodeTreeVo.setCommentNodeTreeVos(commentNodeTreeVos);
                    deepSearch(vo);
                }
            }
        }
    }
}

Mapper.xml(sql语句)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xgg.javacode.mapper.ArticleMapper">

    <sql id="res">
        ac.id comment_id,
        u.user_id,
        u.avatar,
        u.nick_name,
        ac.comment_content,
        ac.upvote_count,
        ac.whether_top,
        DATE_FORMAT(ac.create_time,'%Y-%m-%d %H:%i') create_time
    </sql>

    <select id="findComment" resultType="com.xgg.javacode.model.vo.CommentNodeTreeVo">
        select
        <include refid="res"/>
        from sys_article_comment ac
        left join sys_user u on ac.user_id=u.user_id
        where ac.level_flag=1 and ac.article_id=#{articleId}
        order by ac.whether_top desc,ac.create_time desc
    </select>

    <select id="findChildComment" resultType="com.xgg.javacode.model.vo.CommentNodeTreeVo">
        select
        <include refid="res"/>
        from sys_article_comment ac
        left join sys_user u on ac.user_id=u.user_id
        where ac.level_flag=2 and ac.parent_id=#{commentId}
        order by ac.create_time desc
    </select>
</mapper>

自己简易封装返回的分页结果集(PageInfoResult)

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.PageInfo;
import lombok.Data;

import java.util.List;

/**
 * 分页结果集
 *
 * @author xiegege
 * @date 2020/4/17
 */
@Data
public class PageInfoResult<T> {

    /**
     * 当前页
     */
    private int pageNo;
    /**
     * 当前页的数量
     */
    private int currentPageNum;
    /**
     * 数据总数量
     */
    private long total;
    /**
     * 总页数
     */
    private int totalPages;
    /**
     * 结果集
     */
    private List<T> list;

    public static PageInfoResult getPageInfoResult(PageInfo pageInfo) {
        PageInfoResult result = new PageInfoResult();
        result.setPageNo(pageInfo.getPageNum());
        result.setCurrentPageNum(pageInfo.getSize());
        result.setTotal(pageInfo.getTotal());
        result.setTotalPages(pageInfo.getPages());
        result.setList(pageInfo.getList());
        return result;
    }

    /**
     * 分页数据转换
     * 将mybatis的分页数据转为自定义分页数据
     * @param iPage
     * @return
     */
    public static PageInfoResult convert(IPage iPage) {
        PageInfoResult result = new PageInfoResult();
        result.setPageNo(new Long(iPage.getCurrent()).intValue());
        result.setCurrentPageNum(new Long(iPage.getSize()).intValue());
        result.setTotal(iPage.getTotal());
        result.setTotalPages(new Long(iPage.getPages()).intValue());
        result.setList(iPage.getRecords());
        return result;
    }
}

使用递归进行组装评论树,这样就OK了,结果如下:
在这里插入图片描述

{
  "msg": "操作成功",
  "code": 200,
  "data": {
    "pageNo": 1,
    "currentPageNum": 3,
    "total": 3,
    "totalPages": 1,
    "list": [
      {
        "commentId": 2,
        "userId": 12,
        "avatar": "",
        "nickName": "田七",
        "commentContent": "不错不错",
        "upvoteCount": 0,
        "whetherTop": 1,
        "createTime": "2021-06-18 14:41",
        "commentNodeTreeVos": [
          {
            "commentId": 4,
            "userId": 2,
            "avatar": "",
            "nickName": "张三",
            "commentContent": "啥不错?",
            "upvoteCount": 0,
            "whetherTop": 0,
            "createTime": "2021-06-18 14:42",
            "commentNodeTreeVos": [
              {
                "commentId": 5,
                "userId": 12,
                "avatar": "",
                "nickName": "田七",
                "commentContent": "这篇文章写的不错!",
                "upvoteCount": 0,
                "whetherTop": 0,
                "createTime": "2021-06-18 14:43",
                "commentNodeTreeVos": [
                  {
                    "commentId": 7,
                    "userId": 1,
                    "avatar": "http://xxx.oss-cn-shenzhen.aliyuncs.com/upload/xxx/20210127/4441d54f-1847-4d35-a58d-a2cafc159e74.gif",
                    "nickName": "谢哥哥",
                    "commentContent": "谢谢支持",
                    "upvoteCount": 0,
                    "whetherTop": 0,
                    "createTime": "2021-06-18 16:06",
                    "commentNodeTreeVos": null
                  },
                  {
                    "commentId": 6,
                    "userId": 4,
                    "avatar": "",
                    "nickName": "李四",
                    "commentContent": "是挺不错的",
                    "upvoteCount": 0,
                    "whetherTop": 0,
                    "createTime": "2021-06-18 14:44",
                    "commentNodeTreeVos": null
                  }
                ]
              }
            ]
          }
        Java方法

Java初识方法

java 循环变量

Java毕业设计+现成产品 —>基于java(springboot)汽车信息管理系统(数据库+源码+论文《精品毕设》)实现客户端汽车信息查看发布汽车信息评论收藏后台对用户管理汽车类型管理汽

如何在片段中使用 GetJsonFromUrlTask​​.java

防止组织模式将评论翻译为逐项环境