伤心客 发表于 2022-6-26 03:13:00

基于 SpringBoot + MyBatis 的博客系统

文章目录



[*]1. 项目设计
[*]2. 效果展示
[*]3. 创建项目并配置文件
[*]

[*]1.1 创建 Spring 项目
[*]1.2 配置文件

[*]4. 数据库实现用户和博客管理
[*]

[*]4.1 设计数据库
[*]4.2 使用 MyBatis 操作数据库
[*]

[*]UserMapper.xml
[*]BlogMapper.xml
[*]User 实体类 和 Blog 实体类
[*]UserMapper 接口 和 BlogMapper 接口
[*]UserService 类 和 BlogService 类


[*]5. 前后端交互接口设计
[*]6. 导入前端代码
[*]7. 实现博客主页
[*]

[*]7.1 实现后端代码
[*]7.2 实现前端代码
[*]7.3 测试代码
[*]7.4 解决页面内容太多超出当前浏览器
[*]7.5 解决页面顺序不是按最新时间排序
[*]7.6 解决内容太多, 导致显示的时候占位太多.
[*]7.7 再次测试代码

[*]8. 实现博客详情页
[*]

[*]8.1 实现后端代码
[*]8.2 实现前端代码
[*]8.3 测试代码
[*]8.4 这里展示为markdown语法的正文

[*]9. 实现博客登录界面
[*]

[*]9.1 实现后端代码
[*]9.2 实现前端代码

[*]10. 实现登录判断 --- 拦截器
[*]

[*]

[*]10.1 实现自定义拦截器
   
[*]10.2 将自定义拦截器加入到系统配置

[*]11. 实现注册功能
[*]

[*]11.1 实现后端代码
[*]11.2 实现前端代码

[*]12. 实现注销功能
[*]

[*]12.1 实现后端代码

[*]13. 实现博客编辑页
[*]

[*]13.1 实现后端代码
[*]13.2 实现前端代码

[*]14. 实现博客个人主页
[*]

[*]14.1 实现后端代码
[*]14.2 实现前端代码

[*]15. 实现展示用户信息的功能
[*]

[*]15.1 实现后端代码
[*]15.2 实现前端代码

[*]16. 实现博客的删除功能
[*]

[*]16.1 改进代码
[*]16.2 实现后端代码

[*]17. 实现博客的修改功能
[*]

[*]17.1 实现后端代码
[*]17.2 实现前端代码


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 配置内容
spring.profiles.active=dev application-dev.properties 配置内容
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 (可以设置一个外键,这里没设置)
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 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.example.demo.mapper.UserMapper">
   
    <insert id="addUser" keyProperty="userId" keyColumn="userId">
      insert into user(username password) values (#{username}, #{password})
    </insert>

   
    <select id="selectByName" resultType="com.example.demo.model.User">
      select * from user where username = #{username}
    </select>

   
    <select id="selectById" resultType="com.example.demo.model.User">
      select * from user where userId = #{userId}
    </select>
</mapper> BlogMapper.xml

<?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.example.demo.mapper.BlogMapper">
   
    <select id="getAllBlog" resultType="com.example.demo.model.Blog">
      select * from blog
    </select>

   
    <select id="getBlogByBid" resultType="com.example.demo.model.Blog">
      select * from blog where blogId = #{blogId}
    </select>

   
    <insert id="postBlog" keyColumn="userId" keyProperty="userId">
      insert into blog(title,content,postTime,userId) values(#{title},#{content},#{postTime},#{userId})
    </insert>

   
    <delete id="deleteBlog">
      delete from blog where blogId = #{blogId}
    </delete>

   
    <update id="updateBlog">
      update blog set content = #{content},title = #{title} where blogId = #{blogId}
    </update>

   
    <select id="getAllBlogById" resultType="com.example.demo.model.Blog">
      select * from blog where userId = #{userId}
    </select>
</mapper> User 实体类 和 Blog 实体类

在 model 包下 创建 User 类 和 Blog 类
User 类
@Data
public class User {
    public int userId;
    public String username;
    public String password;
} Blog 类
@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
@Mapper
public interface UserMapper {
    void addUser(User user);

    User selectByName(String username);

    User selectById(Integer userId);
} BlogMapper
@Mapper
public interface BlogMapper {
    List<Blog> getAllBlog();
   
    Blog getBlogByBid(Integer blogId);
   
    void postBlog(Blog blog);
   
    void deleteBlog(Integer blogId);
   
    void updateBlog(Blog blog);
   
    List<Blog> getAllBlogById();
} UserService 类 和 BlogService 类

service 包下创建 UserService类 和 BlogService类
UserService
@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
@Service
public class BlogService {
    @Resource
    private BlogMapper blogMapper;

    public List<Blog> 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<Blog> 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
7. 实现博客主页

这里的交互接口是 交互6
7.1 实现后端代码

@RestController
public class IndexController {
    @Autowired
    private BlogService blogService;

    @RequestMapping("/index")
    public List<Blog> getAllBlog() {
      return blogService.getAllBlog();
    }
} 7.2 实现前端代码

$.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不为空就表示异常.
@RestController
public class DetailsController {
    @Autowired
    private BlogService blogService;

    @RequestMapping("/details")
    public Object ShowBlog(Integer blogId) {
      HashMap<String,Object> 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 实现前端代码

        $.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
@RestController
public class LoginController {
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public Object userLogin(@RequestBody User user, HttpServletRequest request) {
      HashMap<String,Object> 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 实现前端代码

这里前端去除了前后空格,以及为空的情况
      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 实现自定义拦截器

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 将自定义拦截器加入到系统配置

@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 来接收前端返回来的数据
class Register {
    public String username;
    public String password1;
    public String password2;
} 这里后端需要判断当前用户名是否已经被使用.
@RestController
public class RegisterController {
    @Autowired
    private UserService userService;

    @RequestMapping("/register")
    public Object userRegister(@RequestBody Register register) {
      HashMap<String,Object> 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 实现前端代码

要对输入内容去除前后空格,并且判空
      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, 然后发送一个请求.
这里只需要实现后端代码既可
@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 实现后端代码

@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 实现前端代码

      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 实现后端代码

@RestController
public class PersonController {
    @Autowired
    private BlogService blogService;

    @RequestMapping("/person")
    public List<Blog> getMyBlog(@SessionAttribute(value = "user",required = false)User user) {
      List<Blog> 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 实现前端代码

      $.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丢失的情况以及,文章作者丢失情况(数据库表数据被删除的时候会出现这种错误)
@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<String,Object> 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 实现前端代码

详情页的情况:
      $.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');
                }
            }
      }) 个人主页和主页的情况
      $.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 实现后端代码

@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 实现后端代码

@RestController
public class UpdateController {
    @Autowired
    private BlogService blogService;

    @RequestMapping("/updateLoad")
    public Object updateLoad(Integer blogId){
      HashMap<String, Object> 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<String, Object> 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 实现前端代码

      $.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');
                  }
                }
            })
      }
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 基于 SpringBoot + MyBatis 的博客系统