1. Database design

Article: a list of articles

Note | | field | | | -- -- -- -- -- - | -- -- -- -- -- -- -- - | -- -- -- -- -- - | | | id int the only id | | article | author | varchar author | | | in the | varchar title | | | The content | longtext | | the content of the articleCopy the code

See table SQL:

CREATE TABLE 'article' (' id 'int (10) NOT NULL AUTO_INCREMENT COMMENT 'int ', 'author' varchar(50) NOT NULL COMMENT '主 ',' title 'varchar(100) NOT NULL COMMENT' 主 ', 'content' longtext NOT NULL COMMENT '表 示 ', PRIMARY KEY (' id')) ENGINE=InnoDB DEFAULT CHARSET=utf8Copy the code

2. Construction of basic projects

2.1. Build a SpringBoot project configuration

spring: datasource: username: root password: 123456 #? ServerTimezone = UTC time zone solving error url: JDBC: mysql: / / localhost: 3306 / springboot? serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources>Copy the code

2.2 Entity Class:

// @data @noargsconstructor @allargsconstructor public class implements Serializable {private int public implements Serializable; Private String author; // Author name private String title; // Title private String content; // The content of the article}Copy the code

2.3 Mapper Interface:

@mapper@repository public interface ArticleMapper {List<Article> queryArticles(); // add a new Article int addArticle(Article Article); Article getArticleById(int id); Int deleteArticleById(int id); } <? The 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.kuang.mapper.ArticleMapper"> <select id="queryArticles" resultType="Article"> select * from article </select> <select id="getArticleById" resultType="Article"> select * from article where id = #{id} </select> <insert id="addArticle" parameterType="Article"> insert into article (author,title,content) values (#{author},#{title},#{content}); </insert> <delete id="deleteArticleById" parameterType="int"> delete from article where id = #{id} </delete> </mapper>Copy the code

Now that you have provided myBatis mapping configuration files, it is natural to tell Spring Boot where these files are **

mybatis:
mapper-locations: classpath:com/kuang/mapper/*.xml
type-aliases-package: com.kuang.pojo
Copy the code

Write a Controller test, ok;

3. Article editing and integration (key points)

3.1. Import resources in editor.md and delete redundant files

3.2. Edit the article page editor. HTML, need to introduce jQuery;

<! DOCTYPE html> <html class="x-admin-sm" lang="zh" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="renderer" content="webkit"> <meta http-equiv=" x-UA-compatible" Content ="IE=edge, Chrome =1"> <meta name="viewport" content="width=device-width, user-Scalable =yes, minimum-scale=0.4, Initial - scale = 0.8, the target - densitydpi = low - dpi "/ > <! --Editor.md--> <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 class="layui-fluid"> <div class="layui-row layui-col-space15"> <div class="layui-col-md12"> <! <input type="text" name="title"> </div> <input type="text" name="author"> </div> <div id="article-content"> <textarea name="content" id="content" style="display:none;" > </textarea> </div> </form> </div> </div> </div> </body> <! --editormd--> <script th:src="@{/editormd/lib/jquery.min.js}"></script> <script th:src="@{/editormd/editormd.js}"></script> <script type="text/javascript"> var testEditor; / / the window. The onload = function () {} $(function () {testEditor = editormd (" article - the content ", {width: "95%", / / width height: 500, // high syncScrolling: "single", path: ".. // saveHTMLToTextarea emoji: true, // open theme: "Dark ",// toolbar theme previewTheme: "dark",// previewTheme editorTheme: "pastel on-dark",// edit theme Tex: Flowsheet; true; // Switch on science-formula flowsheet support; default off flowChart: true; ImageUpload: true, imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"], imageUploadURL : "/article/file/upload", onload : function() { console.log('onload', this); }, /* Specify the function buttons to display */ 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", "releaseIcon", "index"]}, / * custom function button, <span bgcolor= "gray "> post </span>", index: "<span bgColor = "red "> Return home </span>",}, /* Specify callback functions for custom buttons */ toolbarHandlers:{releaseIcon: Function (cm, icon, cursor, selection) {// MdeditorForm. method = "post"; mdEditorForm.action = "/article/addArticle"; // Submit to the server path mdeditorform.submit (); }, index : function(){ window.location.href = '/'; }}}); }); </script> </html>Copy the code

3.3. Write Controller, jump, and save articles

@Controller @RequestMapping("/article") public class ArticleController { @GetMapping("/toEditor") public String toEditor(){ return "editor"; } @PostMapping("/addArticle") public String addArticle(Article article){ articleMapper.addArticle(article); return "editor"; }}Copy the code

Image uploading problem

1. Add configuration to front-end JS

ImageUpload: true, imageFormats: [" JPG ", "JPEG "," GIF ", "PNG "," BMP ", "webp"], imageUploadURL: "/article/file/upload", // // this is the address to access when uploading the imageCopy the code

2, the backend request, receive to save the image, need to import the FastJson dependency

@requestMapping ("/file/upload") @responseBody public JSONObject fileUpload(@requestParam (value = value) "editormd-image-file", required = true) MultipartFile file, HttpServletRequest Request) throws IOException {// Upload path save Settings // Get the current SpringBoot project path: System.getProperty("user.dir") String path = System.getProperty("user.dir")+"/upload/"; Calendar instance = calendar.getInstance (); String month = (instance.get(calendar.month)+ 1)+" month "; path = path+month; File realPath = new File(path); if (! realPath.exists()){ realPath.mkdir(); } system.out. println(" upload file save address: "+realPath); // Solve the file name problem: we use uuid; String filename = "ks-"+UUID.randomUUID().toString().replaceAll("-", ""); TransferTo (new file (realPath +"/"+ filename)); JSONObject res = new JSONObject(); res.put("url","/upload/"+month+"/"+ filename); res.put("success", 1); res.put("message", "upload success!" ); return res; }Copy the code

3, solve the problem of file display, set up virtual directory mapping! In our own extended MvcConfig configuration can be!

@configuration public class MyMvcConfig implements WebMvcConfigurer {// implements WebMvcConfigurer; // implements WebMvcConfigurer; For example, if the file name is 1.png, /upload/1.png is ok. @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/upload/**") .addResourceLocations("file:"+System.getProperty("user.dir")+"/upload/"); }}Copy the code

The Emoji problem

Manually download the emoji package and place it in the picture path:

Modify the editormd.js file

// Emoji graphics files url path editormd.emoji = { path : ".. /editormd/plugins/emoji-dialog/emoji/", ext : ".png" };Copy the code

4. Article presentation

4.1. Add methods in Controller

@GetMapping("/{id}")
public String show(@PathVariable("id") int id,Model model){
   Article article = articleMapper.getArticleById(id);
   model.addAttribute("article",article);
   return "article";
}
Copy the code

4.2 write the page 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> <! < h1 style="margin: auto 0" th:text="${article. Title}"></h2> left" th:text="${article.author}"></span> <! <div id="doc-content"> <div 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/editormd.js}"></script> <script type="text/javascript"> var testEditor; $(function () {testEditor = editormd.markdowntohtml ("doc-content"), {// Flowsheet "style,script,iframe", emoji: true, taskList: true, tocm: true, Tex: true, // Default not parsing flowChart: True, // The sequenceDiagram: true, // the codeFold: true}); }); </script> </body> </html>Copy the code

5. Possible problems

Upload picture, upload data not found

public class BinaryUploader { public static final State save(HttpServletRequest request, Map<String, Object> conf) { if (! ServletFileUpload.isMultipartContent(request)) { return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); } the try {/ / will request into MultipartHttpServletRequest MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString()); if(multipartFile==null){ return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); } String savePath = (String) conf.get("savePath"); String originFileName = multipartFile.getOriginalFilename(); String suffix = FileType.getSuffixByFilename(originFileName); originFileName = originFileName.substring(0, originFileName.length() - suffix.length()); savePath = savePath + suffix; long maxSize = ((Long) conf.get("maxSize")).longValue(); if (! validType(suffix, (String[]) conf.get("allowFiles"))) { return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); } savePath = PathFormat.parse(savePath, originFileName); String uploadPath = ""; // SpringBoot uploadPath = ""; if(request.getAttribute("uploadPath")! =null){ uploadPath = (String)request.getAttribute("uploadPath"); } String physicalPath = uploadPath + savePath; InputStream is = multipartFile.getInputStream(); State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize); is.close(); if (storageState.isSuccess()) { storageState.putInfo("url", PathFormat.format(savePath)); storageState.putInfo("type", suffix); storageState.putInfo("original", originFileName + suffix); } return storageState; } catch (IOException e) { } return new BaseState(false, AppInfo.IO_ERROR); } private static boolean validType(String type, String[] allowTypes) { List<String> list = Arrays.asList(allowTypes); return list.contains(type); }}Copy the code

Recompile and package, let’s test it again;

6, test,

Restart the project, enter http://localhost:8080/ in the browser address bar, visit to test! And you’re done!

end~