闲来无事,借鉴网上评论系统为自己博客也写了一个。之前用的twikoo,在自己服务器上部署的,但没用到数据库并且评论数据看的也不是很方便虽然根本就没有多少评论。
目前没有实装,只有api接口,实在搞不懂怎么弄前端就放置在那里了。后端用java实现,mysql8,nginx用来反代理。
代码实现
主要思路
每一个评论表里面都存在一个包含其所有子评论的列表,通过这个列表来确定评论的从属关系。每次请求时获取当前页面对应的所有评论内容,经过后端处理好评论从属关系后再发送给前端。
表结构
本次只用了一张表,因为实现挺简单的就没搞复杂化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
@Data @TableName("comment") public class Comment implements Serializable { @TableId private Integer id; private String content; private String userEmail; private String userName; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; private Integer isDelete;
private String blogId; private Integer parentId; private Integer rootParentId;
@TableField(exist = false) private List<Comment> child; }
|
评论ID是主键,没什么特殊含义;
评论内容就不用多解释了吧;
评论作者邮箱用来确定用户身份,同时在别人回复其评论时通知被回复者还没做邮件通知回复。
根据博客ID来确定此评论属于哪个页面下;
父评论ID来确定当前评论是评论的文章还是回复别人的评论,当父评论ID为-1时就代表回复的文章;
List child用来确定评论从属关系。
获取当前页面对应的评论
用的mybatis-plus,继承现有接口即可。
1 2 3 4 5 6 7 8 9 10 11 12
|
<?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.xiaoliu.xcx.mapper.CommentMapper"> <select id="getByBlogId" resultType="com.xiaoliu.xcx.entity.Comment"> select * from comment <where> blog_id = #{blogId} </where> </select> </mapper>
|
这样就从数据库中查询到当前页面下所有评论了,返回所有评论的list列表。
工具类
表结构中的blogId我是根据博客页面url来确定,即数据库中存的blogId字段就是每个页面对应的url。但在前端请求中,太长的页面url很不好用,于是就约定前端把页面url用base64编码后再传回来,后端再次解码即可。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
@Component public class Base64Util {
public String base64Decode(String blogIdBase64){ try { byte[] result = new BASE64Decoder().decodeBuffer(blogIdBase64); return new String(result); }catch (IOException e){ e.printStackTrace(); return null; } } }
|
上面表结构中有一个child评论列表,这个肯定不是从数据库中查出来的,需要自己找到每个评论对应的子评论和父评论。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
@Component public class CommentBeautifyUtil {
public List<Comment> CommentBeautify(List<Comment> commentList){ Map<Integer,Comment> commentMap = new HashMap<>(); List<Comment> result = new ArrayList<>(); for (Comment comment: commentList) { if(comment.getParentId()==-1&&comment.getRootParentId()==-1){ result.add(comment); } commentMap.put(comment.getId(),comment); } for(Comment comment:commentList){ Integer id = comment.getParentId(); if(id!=-1){ Comment parentComment = commentMap.get(id); if (parentComment.getChild()==null){ parentComment.setChild(new ArrayList<>()); } parentComment.getChild().add(comment); } } return result; } }
|
控制层接口
1 2 3 4 5 6
|
@ApiOperation("获取当前页面下所有的评论") @GetMapping("/get/{blogIdBase64}") public List<Comment> getCommentByBlogId(@PathVariable String blogIdBase64){ String blogId = base64Util.base64Decode(blogIdBase64); return commentBeautifyUtil.CommentBeautify(commentService.getCommentByBlogId(blogId)); }
|
首先对前端传回来的数据解码成页面url,再到数据库中查找数据并处理,最后返回给前端数据。
为什么不直接在数据库中存加密后的url而是没加密的url?
虽然这样处理每次都要先对前端传来的数据解密,才能从数据库中查到当前页面的评论,但是相较于直接在数据库中存加密后的url,存加密前的更容易看到这个评论属于哪个页面的,就算以后域名改了直接改数据库中url就可以了。
演示
请求到的json格式就是这样了。