springboot+thymeleaf+jpa博客多级评论展示案例
生活随笔
收集整理的這篇文章主要介紹了
springboot+thymeleaf+jpa博客多级评论展示案例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
效果:
- 實體層
- 業務層:
- 控制層:
- 前端:
實體層
省略了get set方法
@Entity @Table(name = "t_comment") public class Comment {@Id@GeneratedValueprivate Long id;private String nickname;private String email;private String content;private String avatar;@Temporal(TemporalType.TIMESTAMP)private Date createTime;@ManyToOneprivate Blog blog;@OneToMany(mappedBy = "parentComment")private List<Comment> replyComments = new ArrayList<>();@ManyToOneprivate Comment parentComment;private boolean adminComment; }業務層:
@Service public class CommentServiceImpl implements CommentService {@Autowiredprivate CommentRepository commentRepository;@Overridepublic List<Comment> listCommentByBlogId(Long blogId) {Sort sort = new Sort("createTime");List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId,sort);return eachComment(comments);}@Transactional@Overridepublic Comment saveComment(Comment comment) {Long parentCommentId = comment.getParentComment().getId();if (parentCommentId != -1) {comment.setParentComment(commentRepository.findOne(parentCommentId));} else {comment.setParentComment(null);}comment.setCreateTime(new Date());return commentRepository.save(comment);}/*** 循環每個頂級的評論節點* @param comments* @return*/private List<Comment> eachComment(List<Comment> comments) {List<Comment> commentsView = new ArrayList<>();for (Comment comment : comments) {Comment c = new Comment();BeanUtils.copyProperties(comment,c);commentsView.add(c);}//合并評論的各層子代到第一級子代集合中combineChildren(commentsView);return commentsView;}/**** @param comments root根節點,blog不為空的對象集合* @return*/private void combineChildren(List<Comment> comments) {for (Comment comment : comments) {List<Comment> replys1 = comment.getReplyComments();for(Comment reply1 : replys1) {//循環迭代,找出子代,存放在tempReplys中recursively(reply1);}//修改頂級節點的reply集合為迭代處理后的集合comment.setReplyComments(tempReplys);//清除臨時存放區tempReplys = new ArrayList<>();}}//存放迭代找出的所有子代的集合private List<Comment> tempReplys = new ArrayList<>();/*** 遞歸迭代,剝洋蔥* @param comment 被迭代的對象* @return*/private void recursively(Comment comment) {tempReplys.add(comment);//頂節點添加到臨時存放集合if (comment.getReplyComments().size()>0) {List<Comment> replys = comment.getReplyComments();for (Comment reply : replys) {tempReplys.add(reply);if (reply.getReplyComments().size()>0) {recursively(reply);}}}} }控制層:
@Controller public class CommentController {@Autowiredprivate CommentService commentService;@Autowiredprivate BlogService blogService;@Value("${comment.avatar}")//comment.avatar: /images/avatar.pngprivate String avatar;@GetMapping("/comments/{blogId}")public String comments(@PathVariable Long blogId, Model model) {model.addAttribute("comments", commentService.listCommentByBlogId(blogId));return "blog :: commentList";//<div th:fragment="commentList">}// <h3 class="ui dividing header">評論</h3> // <div class="comment" th:each="comment : ${comments}"> // <a class="avatar"> // <img src="https://unsplash.it/100/100?image=1005" th:src="@{${comment.avatar}}"> // </a> // <div class="content"> // <a class="author" > // <span th:text="${comment.nickname}">Matt</span>@PostMapping("/comments")public String post(Comment comment, HttpSession session) {Long blogId = comment.getBlog().getId();comment.setBlog(blogService.getBlog(blogId));User user = (User) session.getAttribute("user");if (user != null) {comment.setAvatar(user.getAvatar());comment.setAdminComment(true);} else {comment.setAvatar(avatar);}commentService.saveComment(comment);return "redirect:/comments/" + blogId;} }前端:
<!--留言區域列表--><div id="comment-container" class="ui teal segment"><div th:fragment="commentList"><div class="ui threaded comments" style="max-width: 100%;"><h3 class="ui dividing header">評論</h3><div class="comment" th:each="comment : ${comments}"><a class="avatar"><img src="https://unsplash.it/100/100?image=1005" th:src="@{${comment.avatar}}"></a><div class="content"><a class="author" ><span th:text="${comment.nickname}">Matt</span><div class="ui mini basic teal left pointing label m-padded-mini" th:if="${comment.adminComment}">博主</div></a><div class="metadata"><span class="date" th:text="${#dates.format(comment.createTime,'yyyy-MM-dd HH:mm')}">Today at 5:42PM</span></div><div class="text" th:text="${comment.content}">How artistic!</div><div class="actions"><a class="reply" data-commentid="1" data-commentnickname="Matt" th:attr="data-commentid=${comment.id},data-commentnickname=${comment.nickname}" onclick="reply(this)">回復</a></div></div><div class="comments" th:if="${#arrays.length(comment.replyComments)}>0"><div class="comment" th:each="reply : ${comment.replyComments}"><a class="avatar"><img src="https://unsplash.it/100/100?image=1005" th:src="@{${reply.avatar}}"></a><div class="content"><a class="author" ><span th:text="${reply.nickname}"></span><div class="ui mini basic teal left pointing label m-padded-mini" th:if="${reply.adminComment}"></div> <span th:text="|@ ${reply.parentComment.nickname}|" class="m-teal"></span></a><div class="metadata"><span class="date" th:text="${#dates.format(reply.createTime,'yyyy-MM-dd HH:mm')}"></span></div><div class="text" th:text="${reply.content}">How artistic!</div><div class="actions"><a class="reply" data-commentid="1" data-commentnickname="Matt" th:attr="data-commentid=${reply.id},data-commentnickname=${reply.nickname}" onclick="reply(this)">回復</a></div></div></div></div></div><div id="comment-form" class="ui form"><input type="hidden" name="blog.id" th:value="${blog.id}"><input type="hidden" name="parentComment.id" value="-1"><div class="field"><textarea name="content" placeholder="請輸入評論信息..."></textarea></div><div class="fields"><div class="field m-mobile-wide m-margin-bottom-small"><div class="ui left icon input"><i class="user icon"></i><input type="text" name="nickname" placeholder="姓名" th:value="${session.user}!=null ? ${session.user.nickname}"></div></div><div class="field m-mobile-wide m-margin-bottom-small"><div class="ui left icon input"><i class="mail icon"></i><input type="text" name="email" placeholder="郵箱" th:value="${session.user}!=null ? ${session.user.email}"></div></div><div class="field m-margin-bottom-small m-mobile-wide"><button id="commentpost-btn" type="button" class="ui teal button m-mobile-wide"><i class="edit icon"></i>發布</button></div></div>javascript部分
//評論表單驗證$('.ui.form').form({fields: {title: {identifier: 'content',rules: [{type: 'empty',prompt: '請輸入評論內容'}]},content: {identifier: 'nickname',rules: [{type: 'empty',prompt: '請輸入你的大名'}]},type: {identifier: 'email',rules: [{type: 'email',prompt: '請填寫正確的郵箱地址'}]}}});$(function () {$("#comment-container").load(/*[[@{/comments/{id}(id=${blog.id})}]]*/"comments/6");});$('#commentpost-btn').click(function () {var boo = $('.ui.form').form('validate form');if (boo) {console.log('校驗成功');postData();} else {console.log('校驗失敗');}});function postData() {$("#comment-container").load(/*[[@{/comments}]]*/"",{"parentComment.id" : $("[name='parentComment.id']").val(),"blog.id" : $("[name='blog.id']").val(),"nickname": $("[name='nickname']").val(),"email" : $("[name='email']").val(),"content" : $("[name='content']").val()},function (responseTxt, statusTxt, xhr) { // $(window).scrollTo($('#comment-container'),500);clearContent();});}function clearContent() {$("[name='content']").val('');$("[name='parentComment.id']").val(-1);$("[name='content']").attr("placeholder", "請輸入評論信息...");}function reply(obj) {var commentId = $(obj).data('commentid');var commentNickname = $(obj).data('commentnickname');$("[name='content']").attr("placeholder", "@"+commentNickname).focus();$("[name='parentComment.id']").val(commentId);$(window).scrollTo($('#comment-form'),500);}總結
以上是生活随笔為你收集整理的springboot+thymeleaf+jpa博客多级评论展示案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis+springboot实现购物
- 下一篇: shell读取文件到变量、管道重定向、i