SpringBoot整合MarkDown(一步一步實現,詳細篇)

一、準備工作,先創建一個文章表,用於存放書寫的文章

1、建表SQL:

CREATE TABLE `article` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'int文章的唯一ID',
`author` varchar(50) NOT NULL COMMENT '作者',
`title` varchar(100) NOT NULL COMMENT '標題',
`content` longtext NOT NULL COMMENT '文章的內容',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

2、EasyCode自動生成代碼(可將除了實體類外所有生成的代碼刪除,我下面會給出必要的代碼)

3、ArticleDao接口下添加四個方法

@Mapper
public interface ArticleDao {
    //查詢所有的文章
    List<Article> queryArticles();
    //新增一個文章
    int addArticle(Article article);
    //根據文章id查詢文章
    Article getArticleById(int id);
    //根據文章id刪除文章
    int deleteArticleById(int id);
}

4、對應的mapper文件

<?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.kk.dao.ArticleDao">

    <resultMap type="com.kk.entity.Article" id="ArticleMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="author" column="author" jdbcType="VARCHAR"/>
        <result property="title" column="title" jdbcType="VARCHAR"/>
        <result property="content" column="content" jdbcType="VARCHAR"/>
    </resultMap>

    <!--根據id查詢單個文章-->
    <select id="getArticleById" resultMap="ArticleMap">
        select
          id, author, title, content
        from bookstore.article
        where id = #{id}
    </select>


    <!--查詢所有文章-->
    <select id="queryArticles" resultMap="ArticleMap">
        select
          id, author, title, content
        from bookstore.article
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if test="author != null and author != ''">
                and author = #{author}
            </if>
            <if test="title != null and title != ''">
                and title = #{title}
            </if>
            <if test="content != null and content != ''">
                and content = #{content}
            </if>
        </where>
    </select>

    <!--添加文章-->
    <insert id="addArticle" keyProperty="id" useGeneratedKeys="true">
        insert into bookstore.article(author, title, content)
        values (#{author}, #{title}, #{content})
    </insert>


    <!--通過id刪除文章-->
    <delete id="deleteArticleById">
        delete from bookstore.article where id = #{id}
    </delete>

</mapper>

5、同樣ArticleService接口實現對應的方法

public interface ArticleService {
    //查詢所有的文章
    List<Article> queryArticles();
    //新增一個文章
    int addArticle(Article article);
    //根據文章id查詢文章
    Article getArticleById(int id);
    //根據文章id刪除文章
    int deleteArticleById(int id);
}

6、ArticleServiceImpl實現

@Service("articleService")
public class ArticleServiceImpl implements ArticleService {
    @Resource
    private ArticleDao articleDao;
    @Override
    public List<Article> queryArticles() {
        return articleDao.queryArticles();
    }
    @Override
    public int addArticle(Article article) {
        return articleDao.addArticle(article);
    }
    @Override
    public Article getArticleById(int id) {
        return articleDao.getArticleById(id);
    }
    @Override
    public int deleteArticleById(int id) {
        return articleDao.deleteArticleById(id);
    }
}

7、ArticleController

@Controller
@RequestMapping("article")
public class ArticleController {
    
    @Resource
    private ArticleService articleService;

    /**
     * 添加文章
     * @param article
     * @return
     */
    @PostMapping("/addArticle")
    public String addArticle(Article article) {
        articleService.addArticle(article);
        return "editor/editormd";
    }

}

二、到官網下載MarkDown的資源包

MarkDown官網

在項目resources/static目錄下創建一個editormd目錄、resources/templates下創建一個editor目錄(因爲隨着項目的擴展,大量的css和js資源混雜,所以建議每個功能模塊的靜態資源都建一個專門的目錄存放,然後改寫js和css等資源的路徑的時候,記得加上目錄名)

在templates的editor目錄下新建一個editormd.html文件(作爲編輯頁面),將資源包的simple.html內容拷貝進去,然後先將下面提到的兩個css和兩個js靜態資源,在資源包中找到之後,導入static的editormd目錄下,然後用th命名空間改寫editormd.html文件的js和css的引入,還要導入整個資源包下的lib包導入plugins包,。

<link rel="stylesheet" th:href="@{/editormd/css/style.css}" />
<link rel="stylesheet" th:href="@{/editormd/css/editormd.css}"/>

<script th:src="@{/editormd/js/jquery.min.js}"></script>
<script th:src="@{/editormd/js/editormd.min.js}"></script>

還要改寫editormd.html中的function內容的path

$(function() {
    testEditor = editormd("test-editormd", {
        width: "90%",
        height: 640,
        syncScrolling: "single",
        path: "../editormd/lib/"
    });
});

editormd.html

<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="utf-8" />
        <title>Simple example - Editor.md examples</title>
        <link rel="stylesheet" th:href="@{/editormd/css/style.css}"/>
        <link rel="stylesheet" th:href="@{/editormd/css/editormd.css}"/>
        <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
    </head>
    <body>
        <div id="layout">
            <header>
                <h1>Simple example</h1>
            </header>
            <div id="test-editormd">
                <textarea style="display:none;"></textarea>
            </div>
        </div>
        <script th:src="@{/editormd/js/jquery.min.js}"></script>
        <script th:src="@{/editormd/js/editormd.min.js}"></script>
        <script type="text/javascript">
			var testEditor;
            $(function() {
                testEditor = editormd("test-editormd", {
                    width: "90%",
                    height: 640,
                    syncScrolling: "single",
                    emoji: true,
                    path: "../editormd/lib/"
                });
            });
        </script>
    </body>
</html>

然後添加一個controller跳轉過去,訪問http://localhost:8080/article/toEditor啓動測試一波

@GetMapping("/toEditor")
    public String toEditor(){
    return "editormd/editormd";
}

調試發現,還需要這些靜態資源

一個個解決

先到資源包找到loading.gif加入到resources/static/editormd目錄中images目錄下

再把字體包fonts整個導入到resources/static/editormd下

目錄結構如圖

再測試,此時已無缺失的靜態資源

然後一個功能一個功能測試過來,

只有上傳圖片功能沒有起作用

接下來實現圖片上傳功能

先到function中追加圖片上傳的配置

$(function() {
    testEditor = editormd("test-editormd", {
        width: "90%",
        height: 640,
        syncScrolling: "single",
        path: "../editormd/lib/",
        //圖片上傳
        imageUpload : true,
        imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
        imageUploadURL : "/file/upload"
    });
});

然後到controller中添加一個controller處理上傳

//博客圖片上傳問題
@RequestMapping("/file/upload")
@ResponseBody
public JSONObject fileUpload(@RequestParam(value = "editormd-image-file", required = true) MultipartFile file, HttpServletRequest request) throws IOException {
    //上傳路徑保存設置

    //獲得SpringBoot當前項目的路徑:System.getProperty("user.dir")
    String path = System.getProperty("user.dir")+"/upload/";

    //按照月份進行分類:
    Calendar instance = Calendar.getInstance();
    String month = (instance.get(Calendar.MONTH) + 1)+"月";
    path = path+month;

    File realPath = new File(path);
    if (!realPath.exists()){
        realPath.mkdirs();
    }

    //上傳文件地址
    System.out.println("上傳文件保存地址:"+realPath);

    //解決文件名字問題:我們使用uuid;
    String filename = "pg-"+ UUID.randomUUID().toString().replaceAll("-", "")+".jpg";
    File newfile = new File(realPath, filename);
    //通過CommonsMultipartFile的方法直接寫文件(注意這個時候)
    file.transferTo(newfile);

    //給editormd進行回調
    JSONObject res = new JSONObject();
    res.put("url","/upload/"+month+"/"+ filename);
    res.put("success", 1);
    res.put("message", "upload success!");

    return res;
}

增加一個適配器配置類,在該配置類中定義虛擬路徑和真實的物理路徑的映射關係。(目的:文件在物理路徑下,但是物理路徑畢竟過長,不簡潔,通過配置適配器,映射到簡潔的地址)

適配器友情鏈接

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
   // 文件保存在真實物理路徑/upload/下(即項目的物理地址下:F:\IDEA_Project_Location\自己\bookstore\upload\3月)
   // 訪問的時候使用虛路徑/upload,比如文件名爲1.png,就直接/upload/1.png就ok了。
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
       //將物理地址upload下的文件映射到/upload下
       //訪問的時候就直接訪問http://localhost:9000/upload/文件名
       registry.addResourceHandler("/upload/**")
          .addResourceLocations("file:"+System.getProperty("user.dir")+"/upload/");
  }
}

可以達到以下效果(重點在路徑)

最後就是查看文章的頁面了

先在數據庫中添加一條文章記錄

INSERT INTO `article` VALUES ('1', 'kk', '我愛你', '## 走在漆黑的夜裏');

在resources/template/editormd下創建一個article.html頁面,作爲查看頁面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title th:text="${article.title}"></title>
</head>
<body>

<div>
    <!--文章主體內容-->
    <div id="doc-content" style="width: 80%">
        <textarea style="display:none;" placeholder="markdown" th:text="${article.content}"></textarea>
    </div>

</div>

<link rel="stylesheet" th:href="@{/editormd/css/editormd.preview.css}" />
<script th:src="@{/editormd/lib/jquery.min.js}"></script>
<script th:src="@{/editormd/lib/marked.min.js}"></script>
<script th:src="@{/editormd/lib/prettify.min.js}"></script>
<script th:src="@{/editormd/lib/raphael.min.js}"></script>
<script th:src="@{/editormd/lib/underscore.min.js}"></script>
<script th:src="@{/editormd/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/editormd/lib/flowchart.min.js}"></script>
<script th:src="@{/editormd/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editormd/lib/editormd.min.js}"></script>

<script type="text/javascript">
    var testEditor;
    $(function () {
        testEditor = editormd.markdownToHTML("doc-content", {//注意:這裏是上面DIV的id
            htmlDecode: "style,script,iframe",
            emoji: true,
            taskList: true,
            tocm: true,
            tex: true, // 默認不解析
            flowChart: true, // 默認不解析
            sequenceDiagram: true, // 默認不解析
            codeFold: true
        });
    });
</script>
</body>
</html>

寫一個controller跳轉到article頁面

@GetMapping("/show")
public String show(Model model) {
    Article article = articleService.getArticleById(1);
    model.addAttribute("article", article);
    return "editor/article";
}

http://localhost:8080/article/show

測試成功!

實現文章提交按鈕,提交編輯好的文章,可以看我的github項目

覺得不錯有所幫助的請,博文點個贊,倉庫給個星,skr~謝謝!

GitHub地址

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