# 博客系统_Spring **Repository Path**: wangzhi430/blog-system--spring ## Basic Information - **Project Name**: 博客系统_Spring - **Description**: 基于 Spring Boot + Spring MVC + MyBatis - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2022-06-20 - **Last Updated**: 2022-12-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README @[TOC] # 1. 项目设计 **前端**使用 `HTML+CSS+JavaScript+JQuery` **后端**使用 `Spring MVC+Spring Boot+MyBatis` ![在这里插入图片描述](https://img-blog.csdnimg.cn/29afc6302a60457c8d1bbc3442f49a2c.png) # 2. 效果展示 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0318239ce9344186ab510cb717fef800.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/ee9c6ef9669d45abbe44e68cf5ed1632.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/bf1916cc6f2b4982b7a3326c8b4c33d8.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/c69eb449c6f6443c95cc382072e79147.png) # 3. 创建项目并配置文件 ## 1.1 创建 Spring 项目 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ca8776a425f445b4b01a68acda8eb014.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/b4e5bff2197c454bb66c32146917f3b1.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/0afc54c4787f485fbdb10f57395f8026.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/716ec2f6a61c4e8fab7c86f65cf3f541.png) ## 1.2 配置文件 `application.properties` 配置内容 ```xml spring.profiles.active=dev ``` `application-dev.properties` 配置内容 ```xml spring.datasource.url=jdbc:mysql://localhost:3306/MyBlogSystem?characterEncoding=utf8&useSSL=true spring.datasource.username=root spring.datasource.password=0000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath:mapper/**Mapper.xml ``` # 4. 数据库实现用户和博客管理 ## 4.1 设计数据库 这里博客系统, 是一个用户表和博客表, > 用户一般分为: > - 用户Id (每个人一个且互不相同) > - 用户名 (每个人的用户名不相同) > - 密码 > - 用户头像(暂不实现) > - 用户马云地址(暂不实现) > 博客一般分为: > - 博客Id (每篇博客一个且互不相同) > - 标题 > - 正文 > - 创建时间 > - 修改时间 (这里没用到, 自己想加也可以) > - 用户Id (可以设置一个外键,这里没设置) ```sql create database if not exists MyBlogSystem; use MyBlogSystem; drop table if exists blog; -- 创建一个博客表 create table blog ( blogId int primary key auto_increment, title varchar(1024), content mediumtext, postTime datetime, userId int ); drop table if exists user; -- 创建一个用户信息表 create table user ( userId int primary key auto_increment, username varchar(128) unique, password varchar(128) ); ``` ## 4.2 使用 MyBatis 操作数据库 > 在 `resources` 下创建一个 `mapper` 包. 包下创建 `UserMapper.xml` 和 > `BlogMapper.xml` > - BlogMapper.xml 里是对博客表的数据库操作 > - UserMapper.xml 里是对用户表的数据库操作 ### UserMapper.xml ```xml insert into user(username password) values (#{username}, #{password}) ``` ### BlogMapper.xml ```xml insert into blog(title,content,postTime,userId) values(#{title},#{content},#{postTime},#{userId}) delete from blog where blogId = #{blogId} update blog set content = #{content},title = #{title} where blogId = #{blogId} ``` ### User 实体类 和 Blog 实体类 在 model 包下 创建 User 类 和 Blog 类 User 类 ```java @Data public class User { public int userId; public String username; public String password; } ``` Blog 类 ```java @Data public class Blog { public int blogId; public String title; public String content; public Timestamp postTime; public int userId; } ``` ### UserMapper 接口 和 BlogMapper 接口 在 mapper 包下创建 UserMapper 和 BlogMapper 接口 UserMapper ```java @Mapper public interface UserMapper { void addUser(User user); User selectByName(String username); User selectById(Integer userId); } ``` BlogMapper ```java @Mapper public interface BlogMapper { List getAllBlog(); Blog getBlogByBid(Integer blogId); void postBlog(Blog blog); void deleteBlog(Integer blogId); void updateBlog(Blog blog); List getAllBlogById(); } ``` ### UserService 类 和 BlogService 类 `service` 包下创建 **UserService类** 和 **BlogService类** `UserService` ```java @Service public class UserService { @Resource private UserMapper userMapper; public void addUser(User user){ userMapper.addUser(user); } public User selectByName(String username){ return userMapper.selectByName(username); } public User selectById(Integer userId){ return userMapper.selectById(userId); } } ``` `BlogService` ```java @Service public class BlogService { @Resource private BlogMapper blogMapper; public List getAllBlog(){ return blogMapper.getAllBlog(); } public Blog getBlogByBid(Integer blogId){ return blogMapper.getBlogByBid(blogId); } public void postBlog(Blog blog) { blogMapper.postBlog(blog); } public void deleteBlog(Integer blogId){ blogMapper.deleteBlog(blogId); } public void updateBlog(Blog blog){ blogMapper.updateBlog(blog); } public List getAllBlogById(){ return blogMapper.getAllBlogById(); } } ``` # 5. 前后端交互接口设计 ![在这里插入图片描述](https://img-blog.csdnimg.cn/fd534b88e5594dcea05bba9c7fbe7d74.png) **交互1** ![在这里插入图片描述](https://img-blog.csdnimg.cn/8f594f1e6c684bd1a9136da3585b96a0.png) **交互2** ![在这里插入图片描述](https://img-blog.csdnimg.cn/1bf62e5eb24e4553a86a1c1677a3321d.png) **交互3** ![在这里插入图片描述](https://img-blog.csdnimg.cn/117b70b3d0c44841b354db5353130a98.png) **交互4** ![在这里插入图片描述](https://img-blog.csdnimg.cn/5e31b37731b84b93ad551f4a696a8ef4.png) **交互5** ![在这里插入图片描述](https://img-blog.csdnimg.cn/43a03f042e8a49eaaa1ddada15373dcf.png) **交互6** ![在这里插入图片描述](https://img-blog.csdnimg.cn/d478debb13134d21b503fb756427a089.png) **交互7** ![在这里插入图片描述](https://img-blog.csdnimg.cn/e9d260f330a640078e880aa1f0996cb4.png) **交互8** ![在这里插入图片描述](https://img-blog.csdnimg.cn/58cce7f7b9714f8a90b0a1ea9e1c94da.png) **交互9** ![在这里插入图片描述](https://img-blog.csdnimg.cn/2eace88b113d4225af7b33e3e45a309d.png) **交互10** ![在这里插入图片描述](https://img-blog.csdnimg.cn/beec3505e1234d3ba73c6204327f9cc2.png) **交互11** ![在这里插入图片描述](https://img-blog.csdnimg.cn/cf5334601dee4061ab1c2e9d6a402ec8.png) # 6. 导入前端代码 **导入前端代码到 `resources` 的 `static`下** ![在这里插入图片描述](https://img-blog.csdnimg.cn/f77516fc2014429fa9f3ccad6fb79a93.png) 具体代码查看 文章 [博客系统前端界面](https://wangzhi430.blog.csdn.net/article/details/124649884) [https://wangzhi430.blog.csdn.net/article/details/124649884](https://wangzhi430.blog.csdn.net/article/details/124649884) # 7. 实现博客主页 这里的交互接口是 `交互6` ## 7.1 实现后端代码 ```java @RestController public class IndexController { @Autowired private BlogService blogService; @RequestMapping("/index") public List getAllBlog() { return blogService.getAllBlog(); } } ``` ## 7.2 实现前端代码 ```javascript $.ajax({ url: "index", method: "GET", success: function(data,status) { buildBlogs(data); } }) function buildBlogs(blogs){ let rightDiv = document.querySelector('.right'); for(let blog of blogs){ let blogDiv = document.createElement('div'); blogDiv.className = 'article'; // 创建 title let h2 = document.createElement('h2'); h2.className = 'title'; h2.innerHTML = blog.title; blogDiv.appendChild(h2); // 创建 postTime let postTime = document.createElement('span'); postTime.className = 'date'; postTime.innerHTML = DateFormat(blog.postTime); blogDiv.appendChild(postTime); // 创建 content let content = document.createElement('div'); content.className = 'desc'; content.innerHTML = blog.content; blogDiv.appendChild(content); // 创建 详情页的超链接 let detailA = document.createElement('a'); detailA.className = 'more'; detailA.href = 'art.html?blogId=' + blog.blogId; detailA.innerHTML = '查看全文>>'; blogDiv.appendChild(detailA); // 加入到 right 中 rightDiv.appendChild(blogDiv); } } // 把毫秒级时间戳转化成格式化日期 function DateFormat(timeStampMS) { var date = new Date(timeStampMS); var year = date.getFullYear(), month = date.getMonth()+1,//月份是从0开始的 day = date.getDate(), hour = date.getHours(), min = date.getMinutes(), sec = date.getSeconds(); var newTime = year + '-' + (month < 10? '0' + month : month) + '-' + (day < 10? '0' + day : day) + ' ' + (hour < 10? '0' + hour : hour) + ':' + (min < 10? '0' + min : min) + ':' + (sec < 10? '0' + sec : sec); return newTime; } ``` ## 7.3 测试代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b71656b5a583488f962adabd19a709a8.png) ## 7.4 解决页面内容太多超出当前浏览器 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3fa255361cea435cbd2ea86a16fdfab4.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/121e30a9d0b54ab4b681db39253ebf5e.png) ## 7.5 解决页面顺序不是按最新时间排序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/282abf501526422e9dbeb8c1b01b87a3.png) **在BlogMapper.xml中修改当前sql语句.** ![在这里插入图片描述](https://img-blog.csdnimg.cn/285b2183e2734bc283eda1c05b5999ad.png) ## 7.6 解决内容太多, 导致显示的时候占位太多. ![在这里插入图片描述](https://img-blog.csdnimg.cn/2081722d3a0341efb793760cdc8040d3.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/4b5dd54b2a3b4580a8b3e61e0557638e.png) ## 7.7 再次测试代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ffa08f7431ae43619c7156e198d4e635.png) # 8. 实现博客详情页 这里的交互是 `交互5` ## 8.1 实现后端代码 根据当前blogId来获取文章, 要判断blogId是否合法, 是否存在当前blogId的文章 这里使用, message来判断, 返回的message不为空就表示异常. ```java @RestController public class DetailsController { @Autowired private BlogService blogService; @RequestMapping("/details") public Object ShowBlog(Integer blogId) { HashMap map = new HashMap<>(); if (blogId == null || blogId < 1) { map.put("message","blogId异常!"); return map; } Blog blog = blogService.getBlogByBid(blogId); if (blog == null) { map.put("message","不存在当前blogId的文章"); return map; } return blog; } } ``` ## 8.2 实现前端代码 ```javascript $.ajax({ url: "details"+location.search, method: "GET", success: function(data,status) { if(data.message == null) { buildBlog(data); } else { alert(data.message); location.assign("home.html"); } } }) function buildBlog(blog){ // 1. 更新 title let titleDiv = document.querySelector('.title'); titleDiv.innerHTML = blog.title; // 2. 更新 postTime let postTime = document.querySelector('.date'); postTime.innerHTML = DateFormat(blog.postTime); editormd.markdownToHTML('content', {markdown: blog.content}); } // 把毫秒级时间戳转化成格式化日期 function DateFormat(timeStampMS) { var date = new Date(timeStampMS); var year = date.getFullYear(), month = date.getMonth()+1,//月份是从0开始的 day = date.getDate(), hour = date.getHours(), min = date.getMinutes(), sec = date.getSeconds(); var newTime = year + '-' + (month < 10? '0' + month : month) + '-' + (day < 10? '0' + day : day) + ' ' + (hour < 10? '0' + hour : hour) + ':' + (min < 10? '0' + min : min) + ':' + (sec < 10? '0' + sec : sec); return newTime; } ``` ## 8.3 测试代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bdc1f19223af494aa693c37c74ee3122.png) ## 8.4 这里展示为markdown语法的正文 展示为 markdown 语法的正文. 注意这里的几段代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/709a1735b2ef472b8ebb11bfbea7a1c6.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/02645f128b6a4d0eba9696aab074ac24.png) 这里还需要导入依赖包 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3786840d634d4325ae7979717f00c099.png) # 9. 实现博客登录界面 这里的交互是 `交互8` ## 9.1 实现后端代码 这里要根据前端穿过来的 json 格式数据进行判断 判断当前是否存在用户, 以及当前用户密码是否正确 登录成功之后, 要创建一个session ```java @RestController public class LoginController { @Autowired private UserService userService; @RequestMapping("/login") public Object userLogin(@RequestBody User user, HttpServletRequest request) { HashMap map = new HashMap<>(); if (user == null) { map.put("message","当前还没有输入用户名和密码,登录失败!"); return map; } User user1 = userService.selectByName(user.getUsername()); if (user1 == null) { map.put("message","当前用户名不存在!"); return map; } if (!user.getPassword().equals(user1.getPassword())) { map.put("message","当前用户名密码错误!"); return map; } user.setUserId(user1.getUserId()); HttpSession session = request.getSession(true); if (session != null) { session.setAttribute("user",user); } return map; } } ``` ## 9.2 实现前端代码 这里前端去除了前后空格,以及为空的情况 ```java let submit = document.querySelector('.button'); submit.onclick = function() { let username = document.querySelector('.user'); let password = document.querySelector('.password'); if (username.value.trim() == ""){ alert('请先输入用户名!'); username.focus(); return; } if (password.value.trim() == ""){ alert('请先输入密码!'); password.focus(); return; } $.ajax({ url: "login", method: "POST", data: JSON.stringify({username: username.value.trim(), password: password.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data, status) { if(data.message == null) { location.assign("home.html"); }else{ alert(data.message); username.value=""; password.value=""; username.focus(); } } }) } ``` # 10. 实现登录判断 --- 拦截器 ### 10.1 实现自定义拦截器 ```java public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(false); if (session != null && session.getAttribute("user") != null) { return true; } response.setStatus(401); response.sendRedirect("/login.html"); return false; } } ``` ## 10.2 将自定义拦截器加入到系统配置 ```java @Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/**/*.js") .excludePathPatterns("/**/*.jpg") .excludePathPatterns("/**/*.css") .excludePathPatterns("/**/*.png") .excludePathPatterns("/**/login.html") .excludePathPatterns("/**/register.html") .excludePathPatterns("/**/login") .excludePathPatterns("/**/register"); } } ``` # 11. 实现注册功能 这里的交互是 `交互9` ## 11.1 实现后端代码 实现一个 类 Register 来接收前端返回来的数据 ```java class Register { public String username; public String password1; public String password2; } ``` 这里后端需要判断当前用户名是否已经被使用. ```java @RestController public class RegisterController { @Autowired private UserService userService; @RequestMapping("/register") public Object userRegister(@RequestBody Register register) { HashMap map = new HashMap<>(); User user = userService.selectByName(register.username); if (user != null) { map.put("message","当前用户名已经存在了, 请更换!"); return map; } User user1 = new User(); user1.setUsername(register.username); user1.setPassword(register.password1); userService.addUser(user1); return map; } } ``` ## 11.2 实现前端代码 要对输入内容去除前后空格,并且判空 ```javascript let submit = document.querySelector('.button'); submit.onclick = function() { let username = document.querySelector('.user'); let password1 = document.querySelector('.password1'); let password2 = document.querySelector('.password2'); if(username.value.trim() == ""){ alert("请先输入用户名!"); username.focus(); return; } if(password1.value.trim() == ""){ alert('请先输入密码!'); password1.focus(); return; } if(password2.value.trim() == ""){ alert('请再次输入密码!'); password2.focus(); return; } if(password1.value.trim() != password2.value.trim()) { alert('两次输入的密码不同!'); passwrod1.value=""; password2.value=""; return; } $.ajax({ url: "register", method: "POST", data: JSON.stringify({username: username.value.trim(), password1: password1.value.trim(),password2: password2.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data,status){ if(data.message != null){ alert(data.message); username.value=""; password1.value=""; password2.value=""; username.focus(); }else{ location.assign('login.html'); } } }) } ``` # 12. 实现注销功能 这里的交互是 `交互10` ## 12.1 实现后端代码 因为 注销功能是点击注销的时候, 触发一个logout的url, 然后发送一个请求. 这里只需要实现后端代码既可 ```java @Controller public class LogoutController { @RequestMapping("/logout") public void userLogout(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(false); // 拦截器的拦截, 所以不可能出现session为空的情况 session.removeAttribute("user"); response.sendRedirect("login.html"); } } ``` # 13. 实现博客编辑页 这里的交互是 `交互1` ## 13.1 实现后端代码 ```java @RestController public class EditController { @Autowired private BlogService blogService; @RequestMapping("/edit") public void postBlog(@RequestBody Blog blog, @SessionAttribute(value = "user",required = false)User user){ blog.setPostTime(new Timestamp(System.currentTimeMillis())); blog.setUserId(user.getUserId()); blogService.postBlog(blog); } } ``` ## 13.2 实现前端代码 ```java let submit = document.querySelector('.publish'); submit.onclick = function() { let title = document.querySelector('.title'); let content = document.querySelector('.content'); if(title.value.trim() == ""){ alert('当前文章标题为空,请输入!'); title.focus(); return; } if(content.value.trim() == ""){ alert('当前文章内容为空,请输入!'); content.focus(); return; } $.ajax({ url: "edit", method: "POST", data: JSON.stringify({title: title.value.trim(), content: content.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data,status) { location.assign('home.html'); } }) } ``` # 14. 实现博客个人主页 这里的交互是 `交互7` 这里的前端页面主要就是主页页面的改进 ## 14.1 实现后端代码 ```java @RestController public class PersonController { @Autowired private BlogService blogService; @RequestMapping("/person") public List getMyBlog(@SessionAttribute(value = "user",required = false)User user) { List blogs = blogService.getAllBlogById(user.getUserId()); for (Blog blog : blogs) { if (blog.getContent().length() > 80) { blog.setContent(blog.getContent().substring(0,80) + " ..."); } } return blogs; } } ``` ## 14.2 实现前端代码 ```javascript $.ajax({ url: "person", method: "GET", success: function(data,status) { buildBlogs(data); } }) function buildBlogs(blogs){ let rightDiv = document.querySelector('.right'); for(let blog of blogs){ let blogDiv = document.createElement('div'); blogDiv.className = 'article'; // 创建 title let h2 = document.createElement('h2'); h2.className = 'title'; h2.innerHTML = blog.title; blogDiv.appendChild(h2); // 创建 postTime let postTime = document.createElement('span'); postTime.className = 'date'; postTime.innerHTML = DateFormat(blog.postTime); blogDiv.appendChild(postTime); // 创建 content let content = document.createElement('div'); content.className = 'desc'; content.innerHTML = blog.content; blogDiv.appendChild(content); // 创建 详情页的超链接 let detailA = document.createElement('a'); detailA.className = 'more'; detailA.href = 'art.html?blogId=' + blog.blogId; detailA.innerHTML = '查看全文>>'; blogDiv.appendChild(detailA); // 加入到 right 中 rightDiv.appendChild(blogDiv); } } // 把毫秒级时间戳转化成格式化日期 function DateFormat(timeStampMS) { var date = new Date(timeStampMS); var year = date.getFullYear(), month = date.getMonth()+1,//月份是从0开始的 day = date.getDate(), hour = date.getHours(), min = date.getMinutes(), sec = date.getSeconds(); var newTime = year + '-' + (month < 10? '0' + month : month) + '-' + (day < 10? '0' + day : day) + ' ' + (hour < 10? '0' + hour : hour) + ':' + (min < 10? '0' + min : min) + ':' + (sec < 10? '0' + sec : sec); return newTime; } ``` # 15. 实现展示用户信息的功能 这里的交互是 `交互11` 这里需要分情况考虑, 展示个人信息主要是 主页页面, 详情页面, 个人主页页面. 以带不带blogId来区分 ## 15.1 实现后端代码 这里判断了 blogId丢失的情况以及,文章作者丢失情况(数据库表数据被删除的时候会出现这种错误) ```java @RestController public class UserController { @Autowired private UserService userService; @Autowired private BlogService blogService; @RequestMapping("/user") public Object getUser(Integer blogId, @SessionAttribute(value = "user",required = false)User user){ if(blogId == null) { return user; }else { HashMap map = new HashMap<>(); Blog blog = blogService.getBlogByBid(blogId); if(blog == null) { map.put("message","不存在当前blogId的文章"); return map; } User author = userService.selectById(blog.getUserId()); if(author == null){ map.put("message","当前文章作者出错"); return map; } return author; } } } ``` ## 15.2 实现前端代码 详情页的情况: ```javascript $.ajax({ url: "user"+location.search, method: "GET", success: function(data,status) { if(data.message == null){ let username = document.querySelector('.name'); username.innerHTML = data.username; }else{ alert(data.message); location.assign('home.html'); } } }) ``` 个人主页和主页的情况 ```javascript $.ajax({ url: "user", method: "GET", success: function(data,status){ let username = document.querySelector('.name'); username.innerHTML = data.username; } }) ``` # 16. 实现博客的删除功能 这里需要用到 `交互2` 这里在详情页的时候进行构建, 在Blog实体类中加一项 `isAuthor`, 为1的时候就是当前文章就是作者. 前端接收到这个的时候, 进行判断, 如果为1就显示删除的按钮. ## 16.1 改进代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/577755d126734f81aebff0083b23f3f1.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/eff1e44d76c545359465f236010d45c8.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/471d110354484fd7a5eadef5cf2b2b13.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/be0091c00404484886ca395a26d7d242.png) ## 16.2 实现后端代码 ```java @Controller public class DeleteController { @Autowired private BlogService blogService; @RequestMapping("/delete") public Object deleteBlog(Integer blogId) { blogService.deleteBlog(blogId); return "/home.html"; } } ``` # 17. 实现博客的修改功能 这里的交互是 `交互3` 和 `交互4` 交互3是在新的页面进行加载 ## 17.1 实现后端代码 ```java @RestController public class UpdateController { @Autowired private BlogService blogService; @RequestMapping("/updateLoad") public Object updateLoad(Integer blogId){ HashMap map = new HashMap<>(); if(blogId == null) { map.put("message","blogId丢失!"); return map; } Blog blog = blogService.getBlogByBid(blogId); if(blog == null) { map.put("blog","不存在当前blog的文章!"); return map; } return blog; } @RequestMapping("/update") public Object Update(Integer blogId, @RequestBody Blog blog, @SessionAttribute(value = "user",required = false)User user) { HashMap map = new HashMap<>(); if(blogId == null) { map.put("message","blogId丢失!"); return map; } blog.setBlogId(blogId); blog.setUserId(user.getUserId()); blogService.updateBlog(blog); return map; } } ``` ## 17.2 实现前端代码 ```javascript $.ajax({ url: "updateLoad"+location.search, method: "GET", success: function(data,status) { if(data.message == null) { let title = document.querySelector('.title'); title.value=data.title; let content = document.querySelector('.content'); content.value=data.content; }else{ alert(data.message); location.assign('home.html'); } } }) // 初始化编辑器 var editor = editormd("editor", { // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. width: "100%", // 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度 height: "calc(100% - 60px)", // 指定 editor.md 依赖的插件路径 path: "editor.md/lib/", // 放到 textarea中 saveHTMLToTextArea: true }); let submit = document.querySelector('.publish'); submit.onclick = function() { let title = document.querySelector('.title'); let content = document.querySelector('.content'); if(title.value.trim() == ""){ alert('当前文章标题为空,请输入!'); title.focus(); return; } if(content.value.trim() == ""){ alert('当前文章内容为空,请输入!'); content.focus(); return; } $.ajax({ url: "update"+location.search, method: "POST", data: JSON.stringify({title: title.value.trim(), content: content.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data,status) { if(data.message == null){ location.assign('home.html'); }else{ alert(data.message); location.assign('home.html'); } } }) } ```