【SpringBoot搭建個人博客】- 博客詳情頁面顯示(十一)

博客地址:ONESTARの客棧

源碼領取方式一:

  • 掃一掃文末二維碼,關注公衆號【編程日刊】,後臺回覆【博客】,即可領取源碼

源碼領取方式二:

歡迎給star以鼓勵(^_−)☆


博客詳情頁面包括文章內容和評論部分,本文將從文章內容顯示和評論功能來講述SpringBoot搭建個人博客的詳情頁面顯示,由於博客詳情和分類功能都是獨立的,這裏將評論單獨用一個類來編寫接口,查詢博客詳情就直接放在首頁的控制器進行處理

分析:

問:博客詳情頁面是包含文章內容和評論部分,要如何處理

答:在跳轉博客詳情頁面的時候,可以返回連個model,一個是文章詳情內容,一個是評論列表

問:文章詳情內容如何處理,需要哪些接口?評論如何處理,又需要哪些接口?

答:文章詳情內容定義getDetailedBlog博客詳情接口,需要定義一個查詢實體類來封裝一下查詢內容,並把分類信息也包含進來;評論功能則需要定義listCommentByBlogId查詢評論列表接口、saveComment新增保存接口、deleteComment刪除接口

一、文章內容顯示

分析:

問:在博客詳情頁面中,文章顯示格式要如何處理,文章訪問數量如何處理,評論數量又該如何處理?

答:這些都在getDetailedBlog接口實現類中實現

  • 文章顯示格式:使用開源的Markdown編輯器:Editor,調用工具類方法來增加擴展
  • 訪問數量:在持久層接口定義方法updateViews來更新文章訪問數量,點擊文章後數值自增
  • 評論數量:在持久層接口定義方法getCommentCountById來根據博客id查詢出評論數量

1. 博客詳情實體類

博客詳情除了顯示博客信息外,還需要顯示分類信息,所以還要創建分類名稱屬性,在queryvo包下創建DetailedBlog博客詳情實體類,代碼如下(省去get、set、toString方法):

package com.star.queryvo;

import java.util.Date;

/**
 * @Description: 博客詳情實體類
 * @Date: Created in 10:10 2020/6/19
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
public class DetailedBlog {

    //博客信息
    private Long id;
    private String firstPicture;
    private String flag;
    private String title;
    private String content;
    private Integer views;
    private Integer commentCount;
    private Date updateTime;
    private boolean commentabled;
    private boolean shareStatement;
    private boolean appreciation;
    private String nickname;
    private String avatar;

    //分類名稱
    private String typeName;
    
}

2. Markdown編輯器工具類

  • 添加依賴Editor相關依賴

在pom.xml中添加

<dependency>
    <groupId>com.atlassian.commonmark</groupId>
    <artifactId>commonmark</artifactId>
    <version>0.10.0</version>
</dependency>

<dependency>
    <groupId>com.atlassian.commonmark</groupId>
    <artifactId>commonmark-ext-heading-anchor</artifactId>
    <version>0.10.0</version>
</dependency>

<dependency>
    <groupId>com.atlassian.commonmark</groupId>
    <artifactId>commonmark-ext-gfm-tables</artifactId>
    <version>0.10.0</version>
</dependency>
  • 添加MarkdownUtils工具類

在util工具包下添加MarkdownUtils工具類:

package com.star.util;

import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
import org.commonmark.node.Link;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.AttributeProvider;
import org.commonmark.renderer.html.AttributeProviderContext;
import org.commonmark.renderer.html.AttributeProviderFactory;
import org.commonmark.renderer.html.HtmlRenderer;

import java.util.*;

/**
 * @Description: Markdown編輯器
 * @Author: ONESTAR
 * @Date: Created in 13:24 2020/4/5
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
public class MarkdownUtils {

    /**
     * markdown格式轉換成HTML格式
     * @param markdown
     * @return
     */
    public static String markdownToHtml(String markdown) {
        Parser parser = Parser.builder().build();
        Node document = parser.parse(markdown);
        HtmlRenderer renderer = HtmlRenderer.builder().build();
        return renderer.render(document);
    }

    /**
     * 增加擴展[標題錨點,表格生成]
     * Markdown轉換成HTML
     * @param markdown
     * @return
     */
    public static String markdownToHtmlExtensions(String markdown) {
        //h標題生成id
        Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
        //轉換table的HTML
        List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
        Parser parser = Parser.builder()
                .extensions(tableExtension)
                .build();
        Node document = parser.parse(markdown);
        HtmlRenderer renderer = HtmlRenderer.builder()
                .extensions(headingAnchorExtensions)
                .extensions(tableExtension)
                .attributeProviderFactory(new AttributeProviderFactory() {
                    public AttributeProvider create(AttributeProviderContext context) {
                        return new CustomAttributeProvider();
                    }
                })
                .build();
        return renderer.render(document);
    }

    /**
     * 處理標籤的屬性
     */
    static class CustomAttributeProvider implements AttributeProvider {
        @Override
        public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
            //改變a標籤的target屬性爲_blank
            if (node instanceof Link) {
                attributes.put("target", "_blank");
            }
            if (node instanceof TableBlock) {
                attributes.put("class", "ui celled table");
            }
        }
    }

    public static void main(String[] args) {
        String table = "| hello | hi   | 哈哈哈   |\n" +
                "| ----- | ---- | ----- |\n" +
                "| 斯維爾多  | 士大夫  | f啊    |\n" +
                "| 阿什頓發  | 非固定杆 | 撒阿什頓發 |\n" +
                "\n";
        String a = "[ONESTAR](https://onestar.newstar.net.cn/)";
        System.out.println(markdownToHtmlExtensions(a));
    }

}

3. 持久層接口

文章內容顯示是從首頁點擊文章標題或圖片,然後跳轉到博客詳情頁面的,所以這裏就將代碼放在博客業務這一塊

在BlogDao接口中添加查詢博客詳情、文章訪問更新、查詢評論數量接口

//查詢博客詳情
DetailedBlog getDetailedBlog(Long id);

//文章訪問更新
int updateViews(Long id);

//根據博客id查詢出評論數量
int getCommentCountById(Long id);

4. mapper

根據持久層接口,編寫如下SQL:查詢博客詳情、文章訪問更新、查詢評論數量,這裏需要對博客詳情進行封裝

<resultMap id="detailedBlog" type="com.star.queryvo.DetailedBlog">
    <id property="id" column="bid"/>
    <result property="firstPicture" column="first_picture"/>
    <result property="flag" column="flag"/>
    <result property="title" column="title"/>
    <result property="content" column="content"/>
    <result property="typeName" column="name"/>
    <result property="views" column="views"/>
    <result property="commentCount" column="comment_count"/>
    <result property="updateTime" column="update_time"/>
    <result property="commentabled" column="commentabled"/>
    <result property="shareStatement" column="share_statement"/>
    <result property="appreciation" column="appreciation"/>
    <result property="nickname" column="nickname"/>
    <result property="avatar" column="avatar"/>
</resultMap>

<!--博客詳情查詢-->
<select id="getDetailedBlog" resultMap="detailedBlog">
    select b.id bid,b.first_picture,b.flag,b.title,b.content,b.views,b.comment_count,b.update_time,b.commentabled,b.share_statement,b.appreciation, u.nickname,u.avatar,t.name
    from myblog.t_blog b,myblog.t_user u, myblog.t_type t
    where b.user_id = u.id and b.type_id = t.id and b.id = #{id}
</select>

<!--文章訪問自增-->
<update id="updateViews" parameterType="com.star.entity.Blog">
    update myblog.t_blog b set b.views = b.views+1 where b.id = #{id}
</update>

<!--查詢出文章評論數量並更新-->
<update id="getCommentCountById" parameterType="com.star.entity.Blog">
    update myblog.t_blog b set b.comment_count = (
    select count(*) from myblog.t_comment c where c.blog_id = #{id} and b.id = #{id}
    ) WHERE b.id = #{id}
</update>

5. 持久層

  • 持久層接口

在BlogService接口中添加查詢博客詳情方法:

//查詢博客詳情
DetailedBlog getDetailedBlog(Long id);
  • 接口實現

次接口實現主要是設置文章顯示格式,文章訪問自增和文章評論的統計,在BlogServiceImpl類中添加實現方法,如下:

@Override
public DetailedBlog getDetailedBlog(Long id) {
    DetailedBlog detailedBlog = blogDao.getDetailedBlog(id);
    if (detailedBlog == null) {
        throw new NotFoundException("該博客不存在");
    }
    String content = detailedBlog.getContent();
    detailedBlog.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
    //文章訪問數量自增
    blogDao.updateViews(id);
    //文章評論數量更新
    blogDao.getCommentCountById(id);
    return detailedBlog;
}

6. 控制器

在IndexController類中添加方法,調用業務層接口:

//跳轉博客詳情頁面
@GetMapping("/blog/{id}")
public String blog(@PathVariable Long id, Model model) {
    DetailedBlog detailedBlog = blogService.getDetailedBlog(id);
    model.addAttribute("blog", detailedBlog);
    
    
    return "blog";
}

二、評論功能

由於評論稍微複雜些,這裏將評論單獨放一個業務層

分析:

問:評論業務層需要哪些接口?

答:評論直接在前端頁面上進行操作,沒有後臺管理,只是區分的管理員和普通用戶,管理員可以對評論進行刪除,因此需要查詢評論列表(listCommentByBlogId)、添加保存評論(saveComment)、刪除評論(deleteComment)接口

問:業務層這些接口夠了,但持久層光這些夠了嗎?需要哪些SQL,需要哪些持久層接口呢?

答:持久層接口肯定是不夠的,主要是查詢評論列表的時候,需要將評論和回覆加以區分,根據評論功能來看,有父評論、子評論(回覆),並且父子評論在前端顯示的位置有不同,這裏細說一下查詢:

  • 根據id爲“-1”和博客id查詢出所有父評論(父級評論id爲‘-1’)
  • 根據父評論的id查詢出一級子回覆
  • 根據子回覆的id循環迭代查詢出所有子集回覆
  • 將查詢出來的子回覆放到一個集合中

所以查詢評論信息需要:查詢父級評論(findByBlogIdParentIdNull)、查詢一級回覆(findByBlogIdParentIdNotNull)、查詢二級回覆(findByBlogIdAndReplayId)

1. 持久層接口

在dao包下創建CommentDao接口,添加如下接口:

package com.star.dao;

import com.star.entity.Comment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Description: 評論持久層接口
 * @Date: Created in 9:21 2020/6/23
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Mapper
@Repository
public interface CommentDao {

    //查詢父級評論
    List<Comment> findByBlogIdParentIdNull(@Param("blogId") Long blogId, @Param("blogParentId") Long blogParentId);

    //查詢一級回覆
    List<Comment> findByBlogIdParentIdNotNull(@Param("blogId") Long blogId, @Param("id") Long id);

    //查詢二級回覆
    List<Comment> findByBlogIdAndReplayId(@Param("blogId") Long blogId,@Param("childId") Long childId);

    //添加一個評論
    int saveComment(Comment comment);

    //刪除評論
    void deleteComment(Long id);

}

2.mapper

在mapper目錄下創建CommentDao.xml文件,添加如下:

<?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.star.dao.CommentDao">

    <!--添加評論-->
    <insert id="saveComment" parameterType="com.star.entity.Comment">
        insert into myblog.t_comment (nickname,email,content,avatar,create_time,blog_id,parent_comment_id,admin_comment)
        values (#{nickname},#{email},#{content},#{avatar},#{createTime},#{blogId},#{parentCommentId},#{adminComment});
    </insert>

    <!--查詢父級評論-->
    <select id="findByBlogIdParentIdNull" resultType="com.star.entity.Comment">
        select *
        from myblog.t_comment c
        where c.blog_id = #{blogId} and c.parent_comment_id = #{blogParentId}
        order by c.create_time desc
    </select>

    <!--查詢一級子評論-->
    <select id="findByBlogIdParentIdNotNull" resultType="com.star.entity.Comment">
        select *
        from myblog.t_comment c
        where c.blog_id = #{blogId} and c.parent_comment_id = #{id}
        order by c.create_time desc
    </select>

    <!--查詢二級子評論-->
    <select id="findByBlogIdAndReplayId" resultType="com.star.entity.Comment">
        select *
        from myblog.t_comment c
        where c.blog_id = #{blogId} and c.parent_comment_id = #{childId}
        order by c.create_time desc
    </select>

    <!--刪除評論-->
    <delete id="deleteComment" >
        delete from myblog.t_comment where id = #{id}
    </delete>

</mapper>

講解:

添加刪除:直接使用insert和delete即可進行添加和刪除

查詢:

  • findByBlogIdParentIdNull:根據id爲“-1”和博客id查詢出所有父評論(父級評論id爲‘-1’)
  • findByBlogIdParentIdNotNull:根據父評論的id查詢出一級子回覆
  • findByBlogIdAndReplayId:根據子回覆的id循環迭代查詢出所有子集回覆

3. 業務層

  • 業務層接口:

在service包下創建CommentService接口,如下:

package com.star.service;

import com.star.entity.Comment;

import java.util.List;

/**
 * @Description: 評論業務層接口
 * @Date: Created in 10:22 2020/6/23
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
public interface CommentService {

    //根據博客id查詢評論信息
    List<Comment> listCommentByBlogId(Long blogId);

    //添加保存評論
    int saveComment(Comment comment);

    //刪除評論
    void deleteComment(Comment comment,Long id);

}
  • 接口實現:

在Impl包下創建接口實現類:CommentServiceImpl,功能都在這個接口中實現

package com.star.service.Impl;

import com.star.dao.BlogDao;
import com.star.dao.CommentDao;
import com.star.entity.Comment;
import com.star.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description: 博客評論業務層接口實現類
 * @Date: Created in 10:23 2020/6/23
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private BlogDao blogDao;

    //存放迭代找出的所有子代的集合
    private List<Comment> tempReplys = new ArrayList<>();

    /**
     * @Description: 查詢評論
     * @Auther: ONESTAR
     * @Date: 10:42 2020/6/23
     * @Param: blogId:博客id
     * @Return: 評論消息
     */
    @Override
    public List<Comment> listCommentByBlogId(Long blogId) {
        //查詢出父節點
        List<Comment> comments = commentDao.findByBlogIdParentIdNull(blogId, Long.parseLong("-1"));
        for(Comment comment : comments){
            Long id = comment.getId();
            String parentNickname1 = comment.getNickname();
            List<Comment> childComments = commentDao.findByBlogIdParentIdNotNull(blogId,id);
            //查詢出子評論
            combineChildren(blogId, childComments, parentNickname1);
            comment.setReplyComments(tempReplys);
            tempReplys = new ArrayList<>();
        }
        return comments;
    }

    /**
     * @Description: 查詢出子評論
     * @Auther: ONESTAR
     * @Date: 10:43 2020/6/23
     * @Param: childComments:所有子評論
     * @Param: parentNickname1:父評論姓名
     * @Return:
     */
    private void combineChildren(Long blogId, List<Comment> childComments, String parentNickname1) {
        //判斷是否有一級子評論
        if(childComments.size() > 0){
            //循環找出子評論的id
            for(Comment childComment : childComments){
                String parentNickname = childComment.getNickname();
                childComment.setParentNickname(parentNickname1);
                tempReplys.add(childComment);
                Long childId = childComment.getId();
                //查詢出子二級評論
                recursively(blogId, childId, parentNickname);
            }
        }
    }

    /**
     * @Description: 循環迭代找出子集回覆
     * @Auther: ONESTAR
     * @Date: 10:44 2020/6/23
     * @Param: chileId:子評論id
     * @Param: parentNickname1:子評論姓名
     * @Return:
     */
    private void recursively(Long blogId, Long childId, String parentNickname1) {
        //根據子一級評論的id找到子二級評論
        List<Comment> replayComments = commentDao.findByBlogIdAndReplayId(blogId,childId);

        if(replayComments.size() > 0){
            for(Comment replayComment : replayComments){
                String parentNickname = replayComment.getNickname();
                replayComment.setParentNickname(parentNickname1);
                Long replayId = replayComment.getId();
                tempReplys.add(replayComment);
                recursively(blogId,replayId,parentNickname);
            }
        }
    }

    //新增評論
    @Override
    public int saveComment(Comment comment) {
        comment.setCreateTime(new Date());
        int comments = commentDao.saveComment(comment);
        //文章評論計數
        blogDao.getCommentCountById(comment.getBlogId());
        return comments;
    }

    //刪除評論
    @Override
    public void deleteComment(Comment comment,Long id) {
        commentDao.deleteComment(id);
        blogDao.getCommentCountById(comment.getBlogId());
    }
}

4. 控制器

  • 添加圖片配置 在評論中,需要顯示頭像,這裏直接在配置文件裏面進行配置,在application.yml中添加如下配置(這裏直接把後面留言的顯示圖片也一起添加了):
comment.avatar: /images/avatar.png
message.avatar: /images/avatar.png

在controller包下創建CommentController類,如下:

package com.star.controller;

import com.star.entity.Comment;
import com.star.entity.User;
import com.star.queryvo.DetailedBlog;
import com.star.service.BlogService;
import com.star.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * @Description: 評論控制器
 * @Date: Created in 10:25 2020/6/23
 * @Author: ONESTAR
 * @QQ羣: 530311074
 * @URL: https://onestar.newstar.net.cn/
 */
@Controller
public class CommentController {

    @Autowired
    private CommentService commentService;

    @Autowired
    private BlogService blogService;

    @Value("${comment.avatar}")
    private String avatar;

    //查詢評論列表
    @GetMapping("/comments/{blogId}")
    public String comments(@PathVariable Long blogId, Model model) {
        List<Comment> comments = commentService.listCommentByBlogId(blogId);
        model.addAttribute("comments", comments);
        return "blog :: commentList";
    }

    //新增評論
    @PostMapping("/comments")
    public String post(Comment comment, HttpSession session, Model model) {
        Long blogId = comment.getBlogId();
        User user = (User) session.getAttribute("user");
        if (user != null) {
            comment.setAvatar(user.getAvatar());
            comment.setAdminComment(true);
        } else {
            //設置頭像
            comment.setAvatar(avatar);
        }

        if (comment.getParentComment().getId() != null) {
            comment.setParentCommentId(comment.getParentComment().getId());
        }
        commentService.saveComment(comment);
        List<Comment> comments = commentService.listCommentByBlogId(blogId);
        model.addAttribute("comments", comments);
        return "blog :: commentList";
    }

    //刪除評論
    @GetMapping("/comment/{blogId}/{id}/delete")
    public String delete(@PathVariable Long blogId, @PathVariable Long id, Comment comment, RedirectAttributes attributes, Model model){
        commentService.deleteComment(comment,id);
        DetailedBlog detailedBlog = blogService.getDetailedBlog(blogId);
        List<Comment> comments = commentService.listCommentByBlogId(blogId);
        model.addAttribute("blog", detailedBlog);
        model.addAttribute("comments", comments);
        return "blog";
    }

}

講解:

查詢評論列表:調用接口查詢評論信息列表,局部刷新評論信息

新增評論:對評論進行判斷,區分遊客和管理員

刪除評論:將博客id和評論id參數傳入,判斷刪除的是哪一條評論,這裏沒有做迭代刪除子評論,若刪除了含有回覆的評論,根據之前的查詢來看,在前端回覆也不會查詢出來,但回覆並沒有刪除,依然在數據庫裏面,刪除的只是父評論

5. 前後端交互

給出部分前端代碼,僅供參考,瞭解更多可以查看整個項目源碼:https://github.com/oneStarLR/myblog-mybatis

提交評論

  • HTML
<input type="hidden" name="blogId" 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>
  • JS
$('#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(),
        "blogId" : $("[name='blogId']").val(),
        "nickname": $("[name='nickname']").val(),
        "email"   : $("[name='email']").val(),
        "content" : $("[name='content']").val()
    },function (responseTxt, statusTxt, xhr) {
        $(window).scrollTo($('#goto'),500);
        clearContent();
    });
}

評論列表

<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>
            <a class="delete" href="#" th:href="@{/comment/{param1}/{param2}/delete(param1=${comment.blogId},param2=${comment.id})}" onclick="return confirm('確定要刪除該評論嗎?三思啊! 刪了可就沒了!')" th:if="${session.user}">刪除</a>
            <!--<a class="delete" href="#" th:href="@{/comment/{id}/delete(id=${comment.id})}" onclick="return confirm('確定要刪除該評論嗎?三思啊! 刪了可就沒了!')" th:if="${session.user}">刪除</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>
                &nbsp;<span th:text="|@ ${reply.parentNickname}|" class="m-teal">@ 小白</span>
              </a>
              <div class="metadata">
                <span class="date" th:text="${#dates.format(reply.createTime,'yyyy-MM-dd HH:mm')}">Today at 5:42PM</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>
                <a class="delete" href="#" th:href="@{/comment/{param1}/{param2}/delete(param1=${reply.blogId},param2=${reply.id})}" onclick="return confirm('確定要刪除該評論嗎?三思啊! 刪了可就沒了!')" th:if="${session.user}">刪除</a>
                <!--<a class="delete" href="#" th:href="@{/comment/{id}/delete(id=${reply.id})}" onclick="return confirm('確定要刪除該評論嗎?三思啊! 刪了可就沒了!')" th:if="${session.user}">刪除</a>-->
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

三、運行訪問

運行項目,訪問 http://localhost:8080/, 點擊一片文章,可以查看文章信息,並能進行評論,登錄後可以對評論進行刪除

至此,Springboot搭建個人博客詳情頁面顯示開發完成,由於留言功能和評論功能基本一樣,之前也寫過一篇有關評論的博客(SpringBoot和Mybatis實現評論樓中樓功能(一張表搞定)),所以這裏就不講留言功能的開發了,還有不懂的夥伴可以問我,也可以加羣討論,下一篇就直接講述分類、時間軸、音樂盒、友人帳、照片牆關於我頁面的顯示,比較簡單,直接在一篇文章中講完

【點關注,不迷路,歡迎持續關注本站】


image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章