手把手带你搭建个人博客系统(二)

简介: 手把手带你搭建个人博客系统(二)

1.针对完成任务


在前端共涉及的四个页面,都需要分别完成“约定前后端交互接口”、“编写服务器代码”、“编写客户端代码”等任务流程。


1.1博客列表页

这个页面需要展示出数据库中的博客列表,按以下开发流程来进行操作


1)约定接口


微信图片_20230111182729.png

2)编写服务器代码


//通过这个类来处理 /blog 路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    //这个方法用来获取到数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从数据库中查询到博客列表,转成JSON格式,然后直接返回即可
        BlogDao blogDao=new BlogDao();
        List<Blog> blogs=blogDao.selectAll();
        //把blogs对象转成JSON格式
        String respJson=objectMapper.writeValueAsString(blogs);
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respJson);
    }
}


postman测试成功:

微信图片_20230111182725.png

3)编写客户端代码

这一步需要我们在之前写好的前端代码中进行调整,加入ajax请求,使得前端页面能够与服务器交互,并从数据库中获取到博客列表。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客列表</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_list.css">
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- container作为页面的版心 -->
    <div class="container">
        <!-- 左侧个人信息 -->
        <div class="left">
            <!-- 表示整个用户信息区域 -->
            <div class="card">
                <img src="image/2.jpg" alt="">
                <h3>如风暖阳</h3>
                <a href="#">gitHub地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧个人信息 -->
        <div class="right">
            <!-- <div class="blog">
                <div class="title">
                    我的第一篇博客
                </div>
                <div class="date">
                    2022-10-21 21:24:00
                </div>
                <div class="desc">
                    刷爆LeetCode!Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore, hic ipsa veritatis adipisci rem, provident accusantium deserunt soluta magnam distinctio consequatur fugit, neque omnis explicabo deleniti reiciendis magni architecto eaque!
                </div>
                <a href="#">查看全文&gt;&gt;</a>
            </div> -->
        </div>
    </div>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script>
        // 在页面加载的时候, 通过 ajax 给服务器发送数据, 获取到博客列表信息, 并且显示在界面上. 
        function getBlogList() {
            $.ajax({
                type: 'get',
                url: 'blog',
                success: function(body) {
                    // 获取到的 body 就是一个 js 对象数组, 每个元素就是一个 js 对象, 根据这个对象构造 div
                    // 1. 先把 .right 里原有的内容给清空
                    let rightDiv = document.querySelector('.right');
                    rightDiv.innerHTML = '';
                    // 2. 遍历 body, 构造出一个个的 blogDiv
                    for (let blog of body) {
                        let blogDiv = document.createElement('div');
                        blogDiv.className = 'blog';
                        // 构造标题
                        let titleDiv = document.createElement('div');
                        titleDiv.className = 'title';
                        titleDiv.innerHTML = blog.title;
                        blogDiv.appendChild(titleDiv);
                        // 构造发布时间
                        let dateDiv = document.createElement('div');
                        dateDiv.className = 'date';
                        dateDiv.innerHTML = blog.postTime;
                        blogDiv.appendChild(dateDiv);
                        // 构造博客的摘要
                        let descDiv = document.createElement('div');
                        descDiv.className = 'desc';
                        descDiv.innerHTML = blog.content;
                        blogDiv.appendChild(descDiv);
                        // 构造 查看全文
                        let a = document.createElement('a');
                        a.innerHTML = '查看全文 &gt;&gt;';
                        // 此处希望点击之后能够跳转到 博客详情页 !!
                        // 这个跳转过程需要告知服务器要访问的是哪个博客的详情页. 
                        a.href = 'blog_detail.html?blogId=' + blog.blogId;
                        blogDiv.appendChild(a);
                        // 把 blogDiv 挂到 dom 树上
                        rightDiv.appendChild(blogDiv);
                    }
                }, 
                error: function() {
                    alert("获取博客列表失败!");
                }
            });
        }
        getBlogList();
    </script>
</body>
</html>


1.2博客详情页


1)约定前后端交互接口


微信图片_20230111182720.png

可以发现在博客详情页的请求中,与博客列表页不同的是多了?blogId=1这样的查询字符串;

该查询字符串在blog_list.html的a链接标签中就加入了

微信图片_20230111182717.png

2)编写客户端代码

加入ajax请求,使得博客详情页的内容,可以通过请求,从服务器中根据查询字符串中的信息,找到对应的博客,展示在前端页面上。


该操作还需要注意,博客正文要用markdown格式渲染,所以要引入editor.md依赖


核心代码块:


微信图片_20230111182713.png

完整前端代码:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客详情页</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_detail.css">
    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <script src="js/jquery.min.js"></script>
    <script src="editor.md/lib/marked.min.js"></script>
    <script src="editor.md/lib/prettify.min.js"></script>
    <script src="editor.md/editormd.js"></script>
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <div class="container">
        <!-- 左侧个人信息 -->
        <div class="left">
            <!-- 表示整个用户信息区域 -->
            <div class="card">
                <img src="image/2.jpg" alt="">
                <h3>如风暖阳</h3>
                <a href="#">gitHub地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧个人信息 -->
        <div class="right">
            <!-- 使用该div来包裹整个博客的内容详情 -->
            <div class="blog-content">
                <!-- 与博客详情页逻辑不同的是,该页面不再需要创建标签,
                    直接在已经挂在DOM树上的标签中填写内容即可,因为该页面是固定区域的,
                    而列表页是多个列表 -->
                <!-- 博客标题 -->
                <h3></h3>
                <!-- 博客的时间 -->
                <div class="date"></div>
                <!-- 正文 -->
                <div id="content" style="opacity: 80%">
                </div>
            </div>
            <script>
                function getBlogDetail() {
                    $.ajax({
                        type:'get',
                        //location.search 拿到查询字符串
                        url:'blog'+location.search,
                        success:function(body) {
                            //body就是一个blog,根据body中的内容来构造页面
                            //1.构造博客标题
                            let h3=document.querySelector(".blog-content>h3");
                            h3.innerHTML=body.title;
                            //2.构造博客发布时间
                            let dateDiv=document.querySelector('.date');
                            dateDiv.innerHTML=body.postTime;
                            //3.构造博客正文,用markdown渲染
                            editormd.markdownToHTML('content',{
                                markdown:body.content
                            });
                        }
                    });
                }
                getBlogDetail();
            </script>
        </div>
    </div>
</body>
</html>


3)编写服务器代码,在BlogServlet类中修改doGet方法,使得浏览器发来的请求中,如果有查询字符串,就返回博客详情页json数据;如果没有查询字符串,就返回博客列表页json数据。


//通过这个类来处理 /blog 路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    //这个方法用来获取到数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        BlogDao blogDao=new BlogDao();
        //先尝试获取到req中的blogId参数,如果该参数存在,说明是要求请求博客详情
        //如果该参数不存在,说明是要请求博客的列表
        String parm=req.getParameter("blogId");
        if(parm==null) {
            //不存在参数,获取博客列表
            List<Blog> blogs=blogDao.selectAll();
            //把blogs对象转成JSON格式
            String respJson=objectMapper.writeValueAsString(blogs);
            resp.getWriter().write(respJson);
        }else {
            //存在参数,获取博客详情
            int blogId=Integer.parseInt(parm);
            Blog blog=blogDao.selectOne(blogId);
            String respJson=objectMapper.writeValueAsString(blog);
            resp.getWriter().write(respJson);
        }
    }
}


效果预览:


微信图片_20230111182708.png

1.3登录功能


1)约定接口


微信图片_20230111182705.png

登录成功后,跳转到博客列表页。

在前端登录实现部分中,我们使用的是input标签,所以通过form表单的方式来构造登录请求更方便。

2)编写前端代码

主要是加入form表单,并把提交按钮类型改为submit,还需要改提交按钮对应的css样式


blog_login.html:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_login.css">
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <!-- <a href="#">注销</a> -->
    </div>
    <div class="login-container">
        <form action="login" method="post">
            <div class="login-dialog">
                <h3>登录</h3>
                <div class="row">
                    <span>用户名</span>
                    <input type="text" id="username" name="username">
                </div>
                <div class="row">
                    <span>密码</span>
                    <input type="password" id="password" name="password">
                </div>
                <div class="row">
                    <input type="submit" id="submit" value="提交">
                </div>
            </div>
        </form>
    </div>
</body>
</html>


blog_login.css:


.login-container {
    width: 100%;
    /* 注意减号两边有空格 */
    height: calc(100% - 50px);
    /* 需要让里面的子元素, 垂直水平居中, 需要用到 flex 布局 */
    display: flex;
    align-items: center;
    justify-content: center;
}
.login-dialog {
    width: 400px;
    height: 350px;
    background-color: rgba(255,255,255,0.8);
    border-radius: 10px;
}
.login-dialog h3 {
    text-align: center;
    padding: 50px 0;
}
.login-dialog .row {
    height: 50px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
.login-dialog .row span {
    /* 把span设置为块级元素方便后续设置尺寸 */
    display: block;
    width: 100px;
    font-weight: 700;
}
#username,#password {
    width: 200px;
    height: 40px;
    font-size: 22px;
    line-height: 40px;
    padding-left: 10px;
    border-radius: 10px;
}
.row #submit {
    width: 300px;
    height: 50px;
    border-radius: 10px;
    color: white;
    background-color: rgb(0,128,0);
    border: none;
    outline: none;
    margin-top:50px ;
}
.row #submit:active {
    background-color: #666;
}


3)编写服务器代码

约定的路径是/login,需要新建一个Servlet类来处理这里的登录请求


@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        //1.获取到请求中的参数
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        System.out.println("username="+username+",password="+password);
        if(username==null||"".equals(username)||password==null||"".equals(password)) {
            // 请求的内容缺失, 肯定是登录失败!!
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前的用户名或密码为空!");
            return;
        }
        //2.和数据库中的内容进行比较
        UserDao userDao=new UserDao();
        User user=userDao.selectByName(username);
        if(user==null||!user.getPassword().equals(password)) {
            //用户没有查到或者密码不匹配,登录失败!
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("用户名或密码错误!");
            return;
        }
        //3.如果比较通过,就创建会话
        HttpSession session=req.getSession(true);
        //把刚才的用户信息,存储到会话中
        session.setAttribute("user",user);
        //4.返回一个重定向报文,跳转到博客列表页
        resp.sendRedirect("blog_list.html");
    }
}


效果预览:


微信图片_20230111182700.gif

1.4检验登录状态


在我们完成了登录功能后,需要对前边两个页面(博客列表页和博客详情页)进行调整,使得这两个页面必须登录后才能访问。


要想实现上述的功能,就需要在博客列表页/详情页加载的时候,通过ajax访问一下服务器,获取当前的登录状态,看看能不能获取到,如果获取到了,就说明当前确实是已经登录了,此时就可以留在这个页面了;如果没有获取到,说明未登录,就需要跳转到登录页面。


1)约定接口


微信图片_20230111182656.png

如果登录了就返回当前登录的用户信息,未登录,就直接返回一个userId=0的对象。

微信图片_20230111182654.png

2)编写服务器代码


在LoginServlet类中加上doGET方法


//这个方法用来让前端检测当前的登录状态
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        HttpSession session=req.getSession(false);
        if(session==null) {
            //检测下会话是否存在,不存在说明未登录
            User user=new User();
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        User user=(User) session.getAttribute("user");
        if(user==null) {
            //虽然会话存在,但是会话里没有user对象,也视为未登录
            user=new User();
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        //代码执行到这里说明已经登录
        //不把密码返回给前端
        user.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }


3)编写前端代码

在博客详情页和博客列表页中加入ajax请求,在页面一加载出来的时候就向服务器发送请求来判定登录状态。


因为两个页面都需要进行判断,所以把判断逻辑单独出一个js文件中,让这两个前端代码引入即可。


//这个文件放一些页面公共的代码
function getUserInfo(pageName) {
    $.ajax({
        type:'get',
        url:'login',
        success:function(body) {
            //判定此处的body是不是一个有效的user对象(userId是否为0)
            if(body.userId&&body.userId>0) {
                //登录成功,不做处理
                console.log("当前用户登录成功! 用户名: " + body.username);
            }else {
                //登录失败!
                //让前端页面跳转到login.html
                alert("当前您尚未登录!请登录后再访问博客列表!");
                location.assign('blog_login.html');
            }
        },
        error: function() {
            alert("当前您尚未登录! 请登录后再访问博客列表!");
            location.assign('blog_login.html');
        }
    });
}


微信图片_20230111182649.png

1.5正确显示用户信息


该步骤需要注意两点:


在博客列表页的用户名,要根据登录的用户来进行确定

在博客详情页的用户名,要根据博客的作者来确定

1.5.1 博客列表页


因为在数据库中并没有存储个人的头像和文章数量等信息,所以只能对用户名做出变动,因为之前在1.4中完成了登录状态检测的步骤后,也就完成了后端代码,这一步只需要在前端进行微调,在页面是博客列表页时,能够将用户名做出修改即可。


//这个文件放一些页面公共的代码
function getUserInfo(pageName) {
    $.ajax({
        type:'get',
        url:'login',
        success:function(body) {
            //判定此处的body是不是一个有效的user对象(userId是否为0)
            if(body.userId&&body.userId>0) {
                //登录成功,不做处理
                console.log("当前用户登录成功! 用户名: " + body.username);
                if(pageName=='blog_list.html') {
                    changeUserName(body.username);
                }
            }else {
                //登录失败!
                //让前端页面跳转到login.html
                alert("当前您尚未登录!请登录后再访问博客列表!");
                location.assign('blog_login.html');
            }
        },
        error: function() {
            alert("当前您尚未登录! 请登录后再访问博客列表!");
            location.assign('blog_login.html');
        }
    });
}
function changeUserName(username) {
    let h3=document.querySelector('.card>h3');
    h3.innerHTML=username;
}


效果预览:

微信图片_20230111182645.png

1.5.2 博客详情页

要想完成博客详情页中用户名的更改,还需要重新约定接口、编写前后端代码。


1)约定接口

微信图片_20230111182641.png

2)编写前端代码


关键代码:

前端代码中的两个ajax请求,是异步并发执行的,并不能确定先后顺序,所以在一个函数的回调函数中,调用另一个函数,让其变为串行执行,才能控制顺序。


微信图片_20230111182638.png


微信图片_20230111182634.png



3)编写服务器代码


@WebServlet("/authorInfo")
public class AuthorServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json; charset=utf8");
        // 通过这个方法, 来获取到指定的博客的作者信息.
        String param = req.getParameter("blogId");
        if (param == null || "".equals(param)) {
            // 参数缺少了.
            resp.getWriter().write("{ \"ok\": false, \"reason\": \"参数缺失!\" }");
            return;
        }
        // 根据当前 blogId 在数据库中进行查找, 找到对应的 Blog 对象, 再进一步的根据 blog 对象, 找到作者信息.
        BlogDao blogDao = new BlogDao();
        Blog blog = blogDao.selectOne(Integer.parseInt(param));
        if (blog == null) {
            resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的博客不存在!\" }");
            return;
        }
        // 根据 blog 对象, 查询到用户对象
        UserDao userDao = new UserDao();
        User author = userDao.selectById(blog.getUserId());
        if (author == null) {
            resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的用户不存在!\" }");
            return;
        }
        // 把 author 返回到浏览器这边
        // 注意要把密码给干掉!
        author.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(author));
    }
}


1.6注销功能


在导航栏中有一个“注销”按钮,当用户点击注销以后,就会在服务器上取消登录状态,并且能够跳转到登录页面。


1)约定前后端交互接口


微信图片_20230111182631.png

2)注销逻辑的服务器代码


@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先找到当前用户的会话
        HttpSession session=req.getSession(false);
        if(session==null) {
            //用户没有登录,不用注销
            resp.getWriter().write("当前用户尚未登录!无法注销!");
            return;
        }
        //把这个用户的会话中的信息给删掉即可
        session.removeAttribute("user");
        resp.sendRedirect("blog_login.html");
    }
}


用户有一个session,同时session中有一个user属性,两者同时兼备时,就是登陆状态,注销只要把其中一个条件破坏掉即可。


微信图片_20230111182627.png

3)客户端代码修改

把博客列表页、博客详情页、博客编辑页中的导航栏中的注销按钮中的herf属性,都做出修改,改成“logout”这个路径。


1.7发布博客


在博客编辑页中,当用户输入了博客标题和正文之后,点击发布,此时就会把博客数据提交到服务器,由服务器存储到数据库中。


1)约定前后端交互接口

微信图片_20230111182624.png

2)实现服务器代码


在BlogServlet里面添加一个doPost方法,来处理上述的post请求;

核心操作,就是读取请求中的标题和正文,构造blog,构造Blog对象,并插入数据库


@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session=req.getSession(false);
        if(session==null) {
            //当前用户未登录,不能提交博客
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前用户未登录,不能提交博客!");
            return;
        }
        User user=(User) session.getAttribute("user");
        if(user==null) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前用户未登录,不能提交博客!");
            return;
        }
        //一定要先指定好请求,按照哪种编码来解析
        req.setCharacterEncoding("utf8");
        //先从请求中取出参数(博客的标题和正文)
        String title=req.getParameter("title");
        String content=req.getParameter("content");
        if(title==null||"".equals(title)||content==null||"".equals(content)) {
            //直接告诉客户端,请求参数不对
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("提交博客失败!缺少必要的参数!");
            return;
        }
        //构造Blog对象,把当前的信息填进去,并插入数据库中
        //此处要给Blog设置的属性,主要是title,content,userId(作者信息)
        //postTime和blogId都不需要手动指定,都是插入数据库的时候自动生成的
        Blog blog=new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        //作者id就是当前提交这个博客的用户的身份信息
        blog.setUserId(user.getUserId());
        BlogDao blogDao=new BlogDao();
        blogDao.insert(blog);
        //重定向到博客列表页
        resp.sendRedirect("blog_list.html");
    }


3)调整客户端代码

将整个文章内容用form表单套住,提交form表单


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_edit.css">
    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <script src="js/jquery.min.js"></script>
    <script src="editor.md/lib/marked.min.js"></script>
    <script src="editor.md/lib/prettify.min.js"></script>
    <script src="editor.md/editormd.js"></script>
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="logout">注销</a>
    </div>
    <!-- 包裹整个博客编辑页内容的顶级容器 -->
    <div class="blog-edit-container">
        <form action="blog" method="post" style="height: 100%;">
            <div class="title">
                <input type="text" placeholder="在此处输入标题" name="title" id="title">
                <!-- <button>发布文章</button> -->
                <input type="submit" value="发布文章" id="submit">
            </div>
            <!-- 放置md编译器 -->
            <div id="editor">
                <textarea name="content" style="display:none"></textarea>
            </div>
        </form>
    </div>
    <script>
        // 初始化编辑器
        let editor = editormd("editor", {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. 
            width: "100%",
            // 设定编辑器高度
            height: "calc(100% - 50px)",
            // 编辑器中的初始内容
            markdown: "# 在这里写下一篇博客",
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/",
            // 此处要加上一个重要的选项, 然后 editor.md 就会自动把用户在编辑器输入的内容同步保存到 隐藏的 textarea 中了!
            saveHTMLToTextarea: true,
        });
    </script>
</body>
</html>


注意对css样式的选择器进行调整,保证提交按钮的样式不丢。


微信图片_20230111182620.png

1.8删除博客


只有自己能够删除自己的博客,不能够删除别人的博客。


1)约定接口

微信图片_20230111182616.png

2)调整前端代码


我们需要在博客详情页中进行判定,当前博客的作者,是否就是登录的用户;


如果是,就在导航栏里显示一个删除按钮,如果不是,就不显示删除按钮。


微信图片_20230111182606.png

3)编写服务器代码


@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.检查当前用户是否登录
        HttpSession session=req.getSession(false);
        if(session==null) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前尚未登录,不能删除!");
            return;
        }
        User user=(User) session.getAttribute("user");
        if(user==null) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前尚未登录,不能删除!");
            return;
        }
        //2.获取到参数中的blogId
        String blogId=req.getParameter("blogId");
        if(blogId==null||"".equals(blogId)) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前blogId参数不对!");
            return;
        }
        //3.获取要删除的博客信息
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
        if(blog==null) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前要删除的博客不存在!");
            return;
        }
        //4.再次校验,当前的用户是否是博客的作者
        if(user.getUserId()!=blog.getUserId()) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前登录的用户不是作者,没有删除权限");
            return;
        }
        //5.确认无误,开始删除
        blogDao.delete(Integer.parseInt(blogId));
        //6.重定向到博客列表
        resp.sendRedirect("blog_list.html");
    }
}
相关文章
|
7月前
|
域名解析 数据安全/隐私保护
自己动手搭建一个网站
最近在研究着随便搞一个网站玩玩,既然有想法了,马上行动。 各种查资料的过程就忽略掉了,下面直入主题。
|
9月前
|
弹性计算 关系型数据库 Apache
手把手教你使用阿里云服务器搭建个人博客
这是我第一次搭建个人博客网站,总体上来说还是非常顺利的,主要四个步骤,首先创建阿里云服务器,其次创建云数据库实例,再次阿里云服务器链接云数据库,最后安装WordPress。四步轻松就可以搭建个人博客网站啦,之前搭建博客起码需要一两周的时间,这次建站只花费了我1个小时就完成啦。
1249 9
|
9月前
|
JavaScript 开发工具 数据安全/隐私保护
手把手教你打造炫酷个人博客:从零开始到成功上线
手把手教你打造炫酷个人博客:从零开始到成功上线
89 0
|
前端开发 JavaScript Java
手把手带你搭建个人博客系统(一)
手把手带你搭建个人博客系统(一)
291 0
手把手带你搭建个人博客系统(一)
|
域名解析 缓存 JavaScript
手把手教你从零开始搭建个人博客,20分钟上手
手把手教你从零开始搭建个人博客,20分钟上手
335 0
手把手教你从零开始搭建个人博客,20分钟上手
|
存储 缓存 JavaScript
第一次搭建个人博客
以前一直都是用的开发环境,从来没有想过在服务器上搭建一个网站。本来因为搭建博客会很简单,没想到单单的配置mongodb就花了我将近一天的时间。最后迫于无奈只能用宝塔面板来搭建我的个人博客了
第一次搭建个人博客
|
JavaScript Shell Linux
从0到1手把手教你搭建个人博客
从0到1手把手教你搭建个人博客
从0到1手把手教你搭建个人博客
|
缓存 IDE Java
快速搭建个人博客
大家好, 我是时间静止, 今天我们介绍基于gitee快速搭建个人博客
快速搭建个人博客
|
开发框架 .NET Serverless
阿里云快速搭建个人博客
使用阿里云体验搭建博客
阿里云快速搭建个人博客
|
Windows
手把手带你搭建个人博客(汇总版)(二)
你是不是特别想创建一个自己的私人博客?以及为什么要使用 blogdown 搭建博客?难度是不是很大,和其他搭建博客而言有什么优点? 在小编使用过一段时间后,个人认为 blogdown 搭建博客的优势在于,将 Rmarkdown 与 hugo 相结合,再加上 github 和一个可以部署的网站。你可以轻松的将一篇篇 Rmarkdown 的文章自动上传上去。而 Rmarkdown 的优势在于,你的代码结果都可以轻松呈现。而不是“复制粘贴”结果!
270 0
手把手带你搭建个人博客(汇总版)(二)