此评论样式采用valine 的样式,JavaScript由博主个人独立编写
目前不会公布源码(因为有些安全问题与一些小bug),这篇文章主要如果你想体验这个评论可以返回主页看公告栏。
问题 一张表实现子评论父评论
正文 Maven依赖 
    
    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 29 30 <dependencies >         <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-thymeleaf</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-jdbc</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-web</artifactId >          </dependency >          <dependency >              <groupId > org.mybatis.spring.boot</groupId >              <artifactId > mybatis-spring-boot-starter</artifactId >              <version > 2.1.4</version >          </dependency >          <dependency >              <groupId > mysql</groupId >              <artifactId > mysql-connector-java</artifactId >              <scope > runtime</scope >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-test</artifactId >              <scope > test</scope >          </dependency >      </dependencies >  
 创建数据表 数据库表结构
    
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE  TABLE  `comment` (  `id` BIGINT (20 ) NOT  NULL  AUTO_INCREMENT COMMENT '主键id' ,   `artitle` BIGINT (20 ) NOT  NULL  DEFAULT  '0'  COMMENT '关联的blog主键' , # 根据需求使用,去过你只是单纯的做个人主页留言的话,每个人评论全部设置为1 即可,当然你也可以直接删除   `nick` VARCHAR (50 ) NOT  NULL  DEFAULT  ''  COMMENT '昵称' ,   `mail` VARCHAR (100 ) NOT  NULL  DEFAULT  ''  COMMENT '邮箱' ,   `link` VARCHAR (50 ) NOT  NULL  DEFAULT  ''  COMMENT '网址' ,   `content` VARCHAR (200 ) NOT  NULL  DEFAULT  ''  COMMENT '内容' ,   `commentatorIP` VARCHAR (20 ) NOT  NULL  DEFAULT  ''  COMMENT 'ip地址' ,   `createTime` DATETIME DEFAULT  NULL  COMMENT '评论时间' ,   `isReply` INT (4 ) BIGINT  '0'  COMMENT '是否是回复 0为否 1为是' ,   `commentStatus` BIGINT (4 ) NOT  NULL  DEFAULT  '0'  COMMENT '是否审核通过 0-未审核 1-审核通过' ,   `commentUrl` VARCHAR (100 ) NOT  NULL  COMMENT '评论对应的页面地址' ,   PRIMARY  KEY (`id`) ) ENGINE= INNODB AUTO_INCREMENT= 53  DEFAULT  CHARSET= utf8; 
 关键代码 实体类、Service接口、ApiUtil类(调用QQ头像、Gravatar、QQ昵称等api)、MD5Util类(MD5加密)、PatternUtil类(正则表达式类,判断邮箱、网站地址等)js,css等CommentMapper.xml也将忽略,本文只围绕文章开头的几个问题进行处理,并不展示回复等功能(就insert操作很简单)
CommentMapper.java(接口)
    
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Mapper public  interface  CommentMapper  {         int  count () ;           int  reply (Comment comment) ;            @Select("select * from comment where isReply=0 AND commentStatus=1 ORDER BY createTime DESC")      List<Comment> CommentListf () ;          @Select("select * from comment where isReply!=0 AND commentStatus=1 ORDER BY createTime ")      List<Comment> CommentListz () ; } 
 CommentServiceImpl.java(实现类)
    
    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 29 30 31 32 33 34 35 36 37 38 @Service public  class  CommentServiceImpl  implements  CommentService  {    @Autowired(required=false)      CommentMapper mapper;     @Override       public  int  count ()  {         return  mapper.count();     }     @Override       public  int  reply (Comment comment)  {                  if (comment.getIsReply()==null )comment.setIsReply(0 );         if (comment.getId()!=0 )comment.setIsReply(comment.getId());         comment.setCreateTime(new  Date ());         comment.setCommentStatus(0 );         return  mapper.reply(comment);     }          @Override       public  List<Comment> CommentListf ()  {         return  mapper.CommentListf();     }     @Override       public  List<Comment> CommentListz ()  {         return  mapper.CommentListz();     } } 
 ControllerComment.java(Controller层)
    
    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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 @Controller public  class  ControllerComment  {    @Autowired(required = false)      private  CommentServiceImpl commentService;          private  List<Comment> Mail (List<Comment> list)  throws  IOException, ParseException {         for  (Comment comment: list){                          if (PatternUtil.isQQEmail(comment.getMail())){                                   Integer  qq  =  Integer.valueOf(comment.getMail().substring(0 , comment.getMail().indexOf("@" )));                                  comment.setMail(ApiUtil.getHeadImage(qq));             }else {                                  comment.setMail(ApiUtil.getGravatar(MD5Util.MD5Encode(comment.getMail())));             }         }                  return  list;     }     @RequestMapping("/")      public  String comment (Model mod)  throws  IOException, ParseException {                  mod.addAttribute("count" ,commentService.count());                  List<Comment> listf = commentService.CommentListf();         mod.addAttribute("commentsf" ,Mail(listf));                   List<Comment> listz = commentService.CommentListz();         mod.addAttribute("commentsz" ,Mail(listz));         return  "index" ;     } } 
 最后在template下新建index.html
    
    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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 <!DOCTYPE html > <html  lang ="zh-CN"  xmlns:th ="http://www.thymeleaf.org" > <head >     <meta  charset ="UTF-8" >      <title > Title</title >  </head > <body > <script  src ="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js" > </script > <div  id ="post-comment" >     <div  class ="comment-head" >          <div  class ="comment-headline" >              <i  class ="fas fa-comments fa-fw" > </i >              <span >  评论</span >          </div >      </div >      <div  class ="comment-wrap" >          <div >              <div  class ="vcomment v"  id ="vcomment" >                  <div  class ="vpanel" >                  </div >                  <div  class ="vcount"  style ="display: block; color: #e58a8a;" >                      <span  class ="vnum"  th:text ="${count}" > </span >  评论</div >                  <div  class ="vcards" >                                       <th:block  th:each ="listf:${commentsf}" >                          <div  class ="vcard" >                                                           <img  class ="vimg lazyload"                                    th:src ="${listf.getMail()}"                                   referrerpolicy ="no-referrer" >                             <div  class ="vh" >                                  <div  class ="vhead" >                                      <a  class ="vnick"  rel ="nofollow"  th:href ="${listf.getLink()}"  target ="_blank"  th:text ="${listf.getNick()}" > </a >                                  </div >                                  <div  class ="vmeta" >                                      <span  style ="color: #828282;"  class ="vtime"  th:text ="${#dates.format(listf.getCreateTime(),'yyyy-MM-dd HH:mm')}" > </span >                                      <span  class ="vat"  th:value ="${listf.getId()}" > 回复</span >                                  </div >                                  <div  class ="vcontent"  data-expand ="查看更多..."  th:utext ="${listf.getContent()}" >                                  </div >                                  <div  class ="vreply-wrapper" > </div >                                                                   <th:block  th:each ="listz:${commentsz}" >                                                                       <div  class ="vquote"  th:if ="${listz.getIsReply()}==${listf.getId()}"  >                                          <div  class ="vcard" >                                              <img  class ="vimg lazyload"                                                    th:src ="${listz.getMail()}"                                                   referrerpolicy ="no-referrer" >                                             <div  class ="vh" >                                                  <div  class ="vhead" >                                                     <a  class ="vnick"  th:href ="${listz.getLink()}"  th:text ="${listz.getNick()}" > </a >                                                  </div >                                                  <div  class ="vmeta" >                                                      <span  style ="color: red;"  class ="vtime" th:text ="${#dates.format(listz.getCreateTime(),'yyyy-MM-dd HH:mm')}" > </span >                                                      <span  class ="vat"  th:value ="${listf.getId()}" > 回复</span >                                                  </div >                                                  <div  class ="vcontent"  data-expand ="查看更多..."  th:utext ="${listz.getContent()}" > </div >                                                  <div  class ="vreply-wrapper" > </div >                                              </div >                                          </div >                                      </div >                                  </th:block >                              </div >                          </div >                      </th:block >                  </div >                  <div  class ="vload-top text-center"  style ="display:none;" >                      <i  class ="vspinner"  style ="width:30px;height:30px;" > </i >                  </div >                  <div  class ="vcards" > </div >                  <div  class ="vload-bottom text-center"  style ="display:none;" >                      <i  class ="vspinner"  style ="width:30px;height:30px;" > </i >                  </div >                  <div  class ="vempty"  style ="display: block;" >                      来发评论吧~                 </div >                  <div  class ="vpage txt-center"  style ="display:none" >                      <button  type ="button"  class ="vmore vbtn" > 加载更多...</button >                  </div >              </div >          </div >      </div >  </div > <link  rel ="stylesheet"  href ="/font/comment.css" > <link  rel ="stylesheet"  href ="/css/Comment.css" > <script  src ="/js/article.js" > </script > </body > </html > 
 运行后的效果图
看不懂?很迷?