SpringBoot 整合 Editormd(完整版)

SpringBoot 整合 Editormd(完整版)

Editormd 下载

Editormd官网进行下载。

下载好了之后,解压,打开。会发现文件的内容如下图所示

OK,有了这些,我们就可以开始整合项目了。

SpringBoot 创建项目

不同的学者可能采用的IDE不同,在这篇推文中使用的是IntelliJ IDEA
个人采用的是使用Spring Initializr 进行创建SpringBoot项目。如下图:

点击Next。

填写具有个人特色的Group和自己想要的Artifact。如下图:

选择依赖,我们只需要添加我们需要用的依赖,后续需要添加一个Alibaba的fastjson依赖即可。如下图:

选择文件Location.如下图:

SpringBoot 项目依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</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>
         <!-- 如果按照上面已经选了一些依赖,那么只需要添加这个依赖即可 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
    </dependencies>

SpringBoot 项目配置

我们在这里使用的是yml配置。

server:
  port: 8081

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 记得创建自己本地的数据库哦,并修改密码
    url: jdbc:mysql://localhost:3306/markdown?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    username: root
    password: laochou
  # 这里的配置主要是用来上传文件映射来使用的,这个location就是我们的存放图像的目录。当然这里还是要看你的数据库图片路径是如何设置的。
  # 大家仔细的话,我在static目录下有个upload目录,这个目录就是我存放上传图片的目录。但是我们在location里面只到了 static这层,因此我的数据库中存放的便是 "/upload/xxxx.png"。拼接在一起就刚好。
  # 图片的绝对路径:F:\JAVA\SpringBoot-MarkDown\src\main\resources\static\upload\0deeac80-6071-45e7-a1f4-d0107173a077.jpg
  servlet:
    multipart:
      location: F:/JAVA/SpringBoot-MarkDown/src/main/resources/static
  web:
    resources:
      static-locations: classpath:static/, file:${spring.servlet.multipart.location}


mybatis:
  mapper-locations: classpath:/mappers/*.xml
  type-aliases-package: cn.laochou.markdown.pojo
  configuration:
    map-underscore-to-camel-case: true

SpringBoot 代码编写

项目会放在百度网盘里面,到时候大家自行下载阅读。这里也会展示,本项目为Demo,所以代码写的比较随意,没有做很多的校验,大家勿怪。
我们先看下代码结构吧

OK,我们先从我们的Article实体来讲

package cn.laochou.markdown.pojo;

public class Article {

    private int id;

    private String title;

    private String author;

    private String content;
    // 省去了 Get和Set方法。在这里个人建议还是使用原生的Get和Set。
}

Ok,实体有了,那么数据库表如何设计的呢?

然后就看我们的Mapper吧。因为Mapper来操作数据库的,其实这里只有两个方法,一个是插入文章数据,一个便是根据Id获取文章数据。

package cn.laochou.markdown.mapper;

import cn.laochou.markdown.pojo.Article;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface ArticleMapper {

    public int insertArticle(Article article);
    public Article getArticleById(int id);

}

Ok,ArticleMapper的接口大家看到了,因为我们采用的还是MyBatis,那么肯定是由ArticleMapper.xml。这就来:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.laochou.markdown.mapper.ArticleMapper">
    <insert id="insertArticle" parameterType="cn.laochou.markdown.pojo.Article">
        insert into article (title, author, content) values(#{title}, #{author}, #{content});
    </insert>

    <select id="getArticleById" resultType="cn.laochou.markdown.pojo.Article" parameterType="int">
        select * from article where id = #{id};
    </select>
</mapper>

接下来,就是我们的Service层了,其实也就是两个方法。没啥很大的区别

package cn.laochou.markdown.service;

import cn.laochou.markdown.mapper.ArticleMapper;
import cn.laochou.markdown.pojo.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ArticleService {


    private final ArticleMapper articleMapper;

    @Autowired
    public ArticleService(ArticleMapper articleMapper) {
        this.articleMapper = articleMapper;
    }

    public boolean publishArticle(Article article) {
        int res = articleMapper.insertArticle(article);
        if(res > 0) {
            return true;
        }
        return false;
    }


    public Article getArticleById(int id) {
        return articleMapper.getArticleById(id);
    }

}

最后就是我们的Controller层了,因为Controller层会用到一个工具类FileUtil,所以先展示我们的FileUtils

package cn.laochou.markdown.utils;

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * 文件上传工具类
 */
public class FileUtils {

    // static目录下的upload目录可自己建,也可不建。因为在上传的时候,会判断是否存在,若不存在便自动创建
    private static final String prePath = System.getProperty("user.dir") + "/src/main/resources/static/upload/";

    /**
     * 上传文件
     * @param file
     * @return 返回文件路径(以相对路径放回)
     */
    public static String uploadFile(MultipartFile file) {
        if(file.isEmpty()) {
            return "";
        }
        // 获取原文件名
        String originFileName = file.getOriginalFilename();
        // 我们通过UUID 来重新重组文件名
        String uid = UUID.randomUUID().toString();
        assert originFileName != null;
        String suffix = originFileName.substring(originFileName.lastIndexOf('.') + 1);
        String path = prePath + uid + "." + suffix;
        String returnPath = "/upload/" + uid + "." + suffix;
        File newFile = new File(path);
        if(newFile.getParentFile() != null && !newFile.getParentFile().exists()) {
            System.out.println("创建目录ing");
            // 上面的 newFile.getParentFile() 已经保证了不为null.
            if(newFile.getParentFile().mkdirs()) {
                System.out.println("创建目录成功");
            }else {
                System.out.println("创建目录失败");
                return "";
            }
        }
        try {
            file.transferTo(newFile);
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
        return returnPath;
    }

}

ArticleController:

package cn.laochou.markdown.controller;

import cn.laochou.markdown.pojo.Article;
import cn.laochou.markdown.service.ArticleService;
import cn.laochou.markdown.utils.FileUtils;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/article")
public class ArticleController {


    private final ArticleService articleService;

    @Autowired
    public ArticleController(ArticleService articleService) {
        this.articleService = articleService;
    }

    @RequestMapping("/publish")
    @ResponseBody
    public String publishArticle(Article article) {
        boolean res = articleService.publishArticle(article);
        if(res) {
            return "success";
        }
        return "false";
    }


    @RequestMapping("/image/upload")
    @ResponseBody
    // 注意RequestParam中的name,不可改。
    public JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {
        JSONObject jsonObject = new JSONObject();
        if(image != null) {
            String path = FileUtils.uploadFile(image);
            System.out.println(path);
            jsonObject.put("url", path);
            jsonObject.put("success", 1);
            jsonObject.put("message", "upload success!");
            return jsonObject;
        }
        jsonObject.put("success", 0);
        jsonObject.put("message", "upload error!");
        return jsonObject;
    }


    @RequestMapping("/get/{id}")
    public ModelAndView getArticleById(@PathVariable(name = "id")int id) {
        ModelAndView modelAndView = new ModelAndView();
        Article article = articleService.getArticleById(id);
        modelAndView.setViewName("article");
        if(article == null) {
            modelAndView.addObject("article", new Article());
        }
        modelAndView.addObject("article", article);
        return modelAndView;
    }

}

MarkDownController:

package cn.laochou.markdown.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/markdown")
public class MarkDownController {

    // 这个接口,主要是进行跳转页面的。
    @RequestMapping("/edit")
    public String edit() {
        return "edit";
    }

}

前端页面

因为本人是后端研发,所以前端这边,花的时间挺久的,同样也挺丑的。哈哈哈,大家见谅。
首先就是我们的一个静态资源。

  • css : 我们需要将我们下载好的editormd解压后editor.md-master文件夹中的examples目录中的css文件夹中的style.css 拷贝到我们的 static/css/examples/style.css,以及editor.md-master文件夹下的 editormd.css 拷贝到我们的 static/css目录。以上的目录放在哪里,可以根据自己的个性以及想法,但是一定得保证访问的到,你如果觉得有问题,就跟我同样的目录。
  • js : 我们需要将我们下载好的editormd解压后editor.md-master文件夹中的examples目录中的js文件夹中的所有js文件 拷贝到我们的 static/css/examples/目录下,以及editor.md-master文件夹下的 editormd.min.js 拷贝到我们的 static/js目录。
  • fonts : 这个目录很重要,如果没有这个目录,Markdown的编辑工具栏的icon无法显示。需要将editor.md-master文件夹中的fonts文件夹直接拷贝到static文件夹中。
  • lib : 将editor.md-master文件夹中的lib文件拷贝到static文件夹中即可。
  • plugins : 将editor.md-master文件夹中的plugin文件拷贝到static文件夹中即可。

接下来就是我们的 HTML文件了
edit.html :

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>Simple example - Editor.md examples</title>
    <link rel="stylesheet" th:href="@{/css/examples/style.css}" />
    <link rel="stylesheet" th:href="@{/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>
    <form name="mdEditorForm">
        标题:<input type="text" name="title"><br>
        作者:<input type="text" name="author">
        <div id="test-editormd">
            <textarea style="display:none;" name="content"></textarea>
        </div>
    </form>

</div>
<script th:src="@{/js/examples/jquery.min.js}"></script>
<script th:src="@{/js/editormd.min.js}"></script>
<script type="text/javascript">
    var testEditor;

    $(function() {
        testEditor = editormd("test-editormd", {
            width   : "90%",
            height  : 640,
            syncScrolling : "single",
            path    : "../lib/",
            // 表示支持上传图片
            imageUpload : true,
            imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            // 上传图片的请求接口
            imageUploadURL : "/article/image/upload",
            // 工具栏图标的设置,大家可以自定义。比如 publish就是我定义的。
            toolbarIcons : function () {
                return ["undo","redo","|","bold","del","italic","quote","ucwords","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","reference-link","image","code","preformatted-text","code-block","table","datetime","emoji","html-entities","pagebreak","|","goto-line","watch","preview","fullscreen","clear","search","|","help","info", "||", "publish"];
            },
            // 自定义图标后,定义图标对应的文字
            toolbarIconTexts: {
                publish: "<span bgcolor='gray'>发布</span>"
            },
            // 自定义图标的触发
            toolbarHandlers : {
                publish: function (cm, icon, cursor, selection) {
                    mdEditorForm.method = "post";
                    mdEditorForm.action = "/article/publish";//提交至服务器的路径
                    mdEditorForm.submit();
                }
            }
        });

        /*
        // or
        testEditor = editormd({
            id      : "test-editormd",
            width   : "90%",
            height  : 640,
            path    : "../lib/"
        });
        */
    });
</script>
</body>
</html>

article.html :

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文章</title>
    <link rel="stylesheet" th:href="@{/css/examples/style.css}" />
    <link rel="stylesheet" th:href="@{/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 th:text="${article.title}"></h1>
        <h2 th:text="${article.author}"></h2>
    </header>
    <div id="test-editormd">
                <textarea style="display:none;" th:text="${article.content}"></textarea>
    </div>
</div>

// 一个JS文件都不能少,少一个便无法渲染。注意静态资源路径问题
<script th:src="@{/js/examples/jquery.min.js}"></script>
<script th:src="@{/lib/marked.min.js}"></script>
<script th:src="@{/lib/prettify.min.js}"></script>
<script th:src="@{/lib/raphael.min.js}"></script>
<script th:src="@{/lib/underscore.min.js}"></script>
<script th:src="@{/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/lib/flowchart.min.js}"></script>
<script th:src="@{/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/js/editormd.min.js}"></script>
<script type="text/javascript">

    var testEditor;

    $(function () {
        testEditor = editormd.markdownToHTML("test-editormd", {
            width: "90%",
            height: 700,
            path: "../lib/",
            preview: true,
            watch: true,
            editor: false,
        })
    })

</script>
</body>
</html>

网盘文件

链接:https://pan.baidu.com/s/1eJh-_dnfANQosJqnPCiHUw
提取码:fm15
点解链接前往 提取码:fm15

效果截图


点击发布之后,可以看到数据库多了一条数据

然后通过接口访问

最后

以上就是今天的分享了。创作不易,还望点赞支持。
也欢迎大家关注FingerDance,我们在这里谈天说地,一起耍。

  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值