富文本编辑是开发过程中常用的功能之一,而markdown是开发人员最亲睐的编辑格式,此刻,我也正在使用的markdown编辑器进行编辑。刚好有了一些想法,所以实现了这个功能。

Markdown文本编辑功能实现

Editormd项目地址,Editormd的基本实现非常简单,只需要在html中引入必要的css文件(此处使用了thymeleaf)

<meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Edit</title>
    <link rel="stylesheet" th:href="@{/css/style.css}"
          href="/css/style.css"/>
    <link rel="stylesheet" th:href="@{/editormd/css/editormd.css}"
          href="/editormd/css/editormd.css"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>

在html中写上两个带有明确class:editormd-markdown-textarea和editormd-html-textarea的标签

<div class="editormd" id="test-editormd">
    <textarea class="editormd-markdown-textarea" name="test-editormd-markdown-doc" id="content"></textarea>
    <!-- 第二个隐藏文本域,用来构造生成的HTML代码,方便表单POST提交,这里的name可以任意取,后台接受时以这个name键为准 -->
    <textarea class="editormd-html-textarea" name="editormd-html-textarea" id="htmlContent"></textarea>
</div>

最后我们进行引入js后进行初始化操作即可

<script th:src="@{/js/jquery.min.js}" src="/js/jquery.min.js"></script>
<script th:src="@{/editormd/js/editormd.js}" src="/editormd/js/editormd.js"></script>
<script type="text/javascript">
    $(function() {
        editormd("test-editormd", {
            width   : "90%",
            height  : 640,
            syncScrolling : "single",
            //你的lib目录的路径,我这边用JSP做测试的
            tocm : true, // Using [TOCM]
            tex : true, // 开启科学公式TeX语言支持,默认关闭
            flowChart : true, // 开启流程图支持,默认关闭
            path    : "/editormd/lib/",
            //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。
            saveHTMLToTextarea : true
        });
    });

此时我们在后台中写添加

@RequestMapping("edit")
    public String   editor(){
        return "edit";
    }

可见如下效果

springboot后端存储markdown springboot markdown_SpringBoot

当我们添加基本的java对象并且在html中添加按钮之后我们就可以将数据传递到后台了。

@Id // 主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    private Long id; // 用户的唯一标识

    //@NotEmpty(message = "标题不能为空")
    @Column(nullable = false, length = 50) // 映射为字段,值不能为空
    private String title;

   //@NotEmpty(message = "摘要不能为空")
    @Column(nullable = false) // 映射为字段,值不能为空
    private String summary;

    @Lob  // 大对象,映射 MySQL 的 Long Text 类型

    //@NotEmpty(message = "内容不能为空")
    @Column(nullable = false) // 映射为字段,值不能为空
    private String content;
    @Lob  // 大对象,映射 MySQL 的 Long Text 类型
    //@NotEmpty(message = "内容不能为空")
    @Column(nullable = false) // 映射为字段,值不能为空
    private String htmlContent; // 将 md 转为 html
    public Long getId() {
        return id;
    }
    //省略get,set方法

js中添加

$("#submitBtn").click(
            function () {
                alert("点击按钮了");
                submitblog();
            }
        )
        function submitblog() {
            var  title = $("#title").val();
            var content = $("#content").val();
            var htmlContent = $("#htmlContent").val();
            $.ajax({
                url: "submit",
                data: {title: title, content:content,htmlContent:htmlContent},
                success:function () {
                    alert("发布成功");
                },
                error:function () {
                    alert("发布失败");
                }
            })
        }

Controller中添加接受方法

@RequestMapping("submit")
    @ResponseBody
    public void    submit(Blog blog){
        System.out.println(blog.getContent());
        System.out.println(blog.getHtmlContent());
        blogRepository.save(blog);
    }

即可保存

实现文本上传功能

前端实现

Editormd的文本上传功能在前端的实现也非常简单,只需要在前端js初始化的代码中加入

imageUpload : true,
            imageFormats : [ "jpg", "jpeg", "gif", "png", "bmp", "webp" ],
            imageUploadURL : "/uploadimg",
            onload: function () {
                //console.log('onload', this);
                //this.fullscreen();
                //this.unwatch();
                //this.watch().fullscreen();
                this.width("100%");
                this.height(480);
                //this.resize("100%", 640);
            }

onload方法为上传图片的回调方法,可以在这里设置图片的一些属性
但是实际测试过程中,发现这些属性并没有什么作用,网上也没有对应的例子。因此,这一步需要好好探究

后端实现

@RequestMapping(value="/uploadimg")
    public @ResponseBody Map<String,Object> demo(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file, HttpServletRequest request) {
        Map<String,Object> resultMap = new HashMap<String,Object>();
        System.out.println(request.getContextPath());
        String realPath = UPLOADED_FOLDER;
        String fileName = file.getOriginalFilename();
        System.out.println(fileName);
/*        File targetFile = new File(realPath, fileName);
        if(!targetFile.exists()){
            targetFile.mkdirs();
        }*/
        //保存
        try {
/*            file.transferTo(targetFile);*/
            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);
            resultMap.put("success", 1);
            resultMap.put("message", "上传成功!");
            resultMap.put("url",UPLOADED_FOLDER+fileName);
        } catch (Exception e) {
            resultMap.put("success", 0);
            resultMap.put("message", "上传失败!");
            e.printStackTrace();
        }
        System.out.println(resultMap.get("success"));
        return resultMap;


    }

此处有两个需要注意的点

  • 由于SpringBoot自带的Tomcat的原因,导致图片无法上传到项目目录下,自带的Tomcat的临时目录的存取权限有问题,因此此处我们使用了一个指定目录
  • Editormd前端规定了后台必须返回给前端一个map且形式为{“success”:1,message:”上传成功”,”url”:url},这里需要注意一下。
  • 其次,使用简单的file文件写入也许会存在问题,因此,我们这里采用了NIO的写入方式
byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);

代码地址