服务器版博客系统、前后端交互3

八、显示对应用户信息

每一次,左侧都是同样的登录内容

登录 ‘zhangsan’,但是当下用户信息,显示的是还是 “小吴的博客”
实际登录的用户,是 “zhangsan”

登录的用户 和 文章作者,可能是一个人,也可能不是一个人!!

在博客列表页,期望显示的用户信息,就是当前登录的用户

1、针对博客列表页 blog_list.html

修改 .left 内容:将 h3 中的内容 删除,

在 common.js 添加:在登录成功时调用

function changeUserName(username) {
    let h3 = document.querySelector('.card>h3');
    h3.innerHTML = username;
}

在这里插入图片描述

这里其实前面已经处理过了!!! (在检测用户登录状态的时候)
注意,当前虽然已经让用户名正常了,但是用户的头像,github,文章的统计,这些都是没有变化的,当前在设计数据库的时候,就没考虑这些~~


2、针对博客详情页

2.1、前端 区分列表页,详情页

当前看到的是,博客详情页,用户名,也是成了 zhangsan 了!!! 因为在 common.js 中,同时调用了
此处就需要处理一下,让博客列表页,和详情页,能够做出一些区分~~

希望 列表页 和 详情页 这里分别显示不同的内容~~

比如针对当前这个 blogld 为 6 的博客来说,这个博客的作者是 “lisi” ,此处显示的用户名,也就应该是 lisi~~

让服务器,提供一个新的接口,这个接口可以让客户端指定 blogld,获取到指定 blogld 的作者信息!!

修改 .left 内容:将 h3 内容的 “小吴的博客” 删除,

请求:

GET /authorlnfo?blogld=6

响应:

{
	userld: 2,
	username: 'lisi',
}

修改:

在这里插入图片描述

common.js 的 getUserInfo 获取登录状态方法中添加参数 pageName

common.js 完整代码:

这个逻辑是页面加载的时候,获取下用户的身份信息,判定是否登录

// 这个文件里放一些页面公共的代码

// 加上一个逻辑, 通过 GET /login 这个接口来获取下当前的登录状态
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');
        }
    });
}

// getUserInfo();

function changeUserName(username) {
    let h3 = document.querySelector('.card>h3');
    h3.innerHTML = username;
}

2.2、服务器代码 AuthorServlet

创建 AuthorServlet 类

package controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;
import model.User;
import model.UserDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@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));
    }
}

验证:

在这里插入图片描述


2.3、前端代码 blog_detail.html

调整顺序,编写 getAuthorInfo 方法获取作者信息

<!-- 在这里引入上述的 js 文件, 就可以执行到里面的代码, 也就进行了登录状态的监测了 -->
<script src="js/common.js"></script>

<script>
    function getBlogDetail() {
        $.ajax({
            type: 'get',
            // location.search 拿到了形如 '?blogId=5' 这样的一段内容
            url: 'blog' + location.search,
            success: function(body) { // body 中就是一个 js 对象
                // 根据 body 中的内容来构造页面
                // 1. 构造博客标题
                let h3 = document.querySelector('.blog-content>h3');
                h3.innerHTML = body.title;
                // 2. 构造博客发布时间
                let dateDiv = document.querySelector('.date');
                dateDiv.innerHTML = body.postTime;
                // 3. 构造博客正文
                // let contentDiv = document.querySelector('#content');
                // contentDiv.innerHTML = body.content;
                // 如果直接把 content 设为 innerHTML, 此时展示在界面上的内容, 是原始的 markdown 字符串
                // 咱们需要的是渲染后的, 带有格式的效果

                // 第一个参数对应 id=content 的 html 标签. 渲染后得到的 html 片段就会被放到这个 标签下.
                editormd.markdownToHTML('content', {
                    markdown: body.content
                });
            }
        });
    }
    
    getBlogDetail();

    
    // 判定用户登录状态
    getUserInfo('blog_detail.html');
    
    // 从服务器获取一下当前博客的作者信息, 并显示到界面上. 
    // 参数 user 就是刚才从服务器拿到的当前登录用户的信息
    function getAuthorInfo() {
        $.ajax({
            type: 'get',
            url: 'authorInfo' + location.search,
            success: function(body) {
                // 此处的 body, 就是服务器返回的 User 对象, 是文章的作者信息
                if (body.username) {
                    // 如果响应中的 username 存在, 就把这个值设置到页面上. 
                    changeUserName(body.username);
                } else {
                    console.log("获取作者信息失败! " + body.reason);
                }
            }
        });
    }
    
    getAuthorInfo(); // 
    
</script>

2.4、——验证

访问列表页,登录 “zhangsan”,点击最上面一篇博客作者为 “lisi” 的博客,跳转到详情页,此时看到,左侧的用户名就是 “lisi”,登录的是 “zhangsan” 的账户,但是是详情页按照文章作者来设置的

在这里插入图片描述

blogId 为 6 的 userId 为 2

mysql> select * from blog;
+--------+-----------------------+--------------------------------------------------------+--------+---------------------+
| blogId | title                 | content                                                | userId | postTime            |
+--------+-----------------------+--------------------------------------------------------+--------+---------------------+
|      1 | 这是第一篇博客        | 从今天开始, 我要认真学 Java                            |      1 | 2022-05-27 02:51:36 |
|      2 | 这是第二篇博客        | 从昨天开始, 我要认真学 Java                            |      1 | 2022-05-27 02:51:36 |
|      3 | 这是第三篇博客        | 从前天开始, 我要认真学 Java                            |      1 | 2022-05-27 02:51:36 |
|      4 | 这是第一篇博客        | 从今天开始, 我要认真学 C++                             |      2 | 2022-05-27 02:51:36 |
|      5 | 这是第二篇博客        | 从昨天开始, 我要认真学 C++                             |      2 | 2022-05-27 02:51:39 |
|      6 | 这是第三篇博客        | # 一级标题
 ### 三级标题
 > 这是引用内容               |      2 | 2022-05-27 20:48:10 |
+--------+-----------------------+--------------------------------------------------------+--------+---------------------+

查看 userId 为 2 的作者,是 lisi

mysql> select * from user;
+--------+----------+----------+
| userId | username | password |
+--------+----------+----------+
|      1 | zhangsan | 123      |
|      2 | lisi     | 123      |
+--------+----------+----------+

上述功能,就实现了把用户信息,显示到页面上 (左侧卡片中)

  1. 对于博客列表页,要显示登录用户的信息,登录用户的信息,在检测用户是否登录的接口中,就已经拿到了。只需要把拿到的用户信息,显示到界面上即可 (只是微调了前端代码,不涉及后端代码的修改)
  2. 对于博客详情页,要显示文章的作者信息,就需要提供一个新的 api,让客户端传一个博客 id 过去,然后在服务器这里查询当前的用户信息,查到之后返回给页面

通过上述的开发,就能有一个感受:
页面和服务器之间的交互,不一定只有一次,而且大概率是很多次交互~~

  • 像博客列表页:这里涉及到了两次交互
    • 从服务器拿到博客列表数据
    • 从服务器拿到当前的登录用户信息
  • 像博客详情页:涉及到了三次交互
    • 从服务器拿到博客的详细内容
    • 从服务器拿到了当前登录用户信息
    • 从服务器拿到了当前文章的作者信息

九、实现 “注销” 功能

退出当前登录的状态~~
在导航栏中安排一个 “注销” 按钮

当用户点击注销之后,就会在服务器上取消登录状态,并且能够跳转到登录页面
当下注销按钮这里啥都没有,点上去之后,也没反应~~

希望在点击之后,能够给服务器发送一个 HTTP 请求,从而触发注销动作 (这个动作具体就是把会话中的信息给删掉就行了!!)


1、约定交互接口

请求:

GET /logout

响应:

HTTP/1.1 302
Location: login.html

2、服务器代码 LogoutServlet

创建 LogoutServlet 类

用户有一个 session ,同时 session 有一个 user 属性,两者同时具备,才叫登录状态

注销,只要破坏掉上面的任意一个条件就行了~~
此处选择的是破坏第二个条件,把 user 属性从 session 中删了

loginServlet 类中,我们写重写了 doGet 方法,下图检测登录状态的代码,要求同时具备 session 对象和 user 属性

user 属性被删除,后续读取的时候得到的就是 null
因此就会给客户端返回一个无效 User 对象,客户端就明白,就认为是未登录状态!

在这里插入图片描述

代码:

package controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@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");
    }
}

3、修改客户端代码

  • 博客列表页,博客详情页,博客编辑页,这里的导航栏中的注销按钮href 属性都做出修改,改成 “logout” 这个路径。注意,不是 “/logout”
  • 登录页,是没有注销按钮的!!

在这里插入图片描述

修改完,访问页面,登录后,点击页面导航栏上的 “注销”,即跳转到登录页面

1、博客列表页 2、博客详情页 3、登录功能 4、检测用户登录状态 5、显示用户信息 6、注销

核心逻辑都是一样的!!!

  1. 约定前后端交互接口
  2. 实现服务器代码
    • 写 controller 层,写 servlet 来实现 api
    • 写 model 层,通过 jdbc 来操作数据库
  3. 实现客户端代码
    • ajax / form / a标签跳转

十、实现发布博客功能

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

1、约定交互接口

请求: 此处的内容都是需要 urlencoded 的,此处浏览器会自动进行编码

POST /blog
Content-Type: application/x-www-form-urlencoded

title=这是标题&content=这是正文……

响应:

HTTP/1.1 302
Location: blog_list.html

2、服务器代码 BlogServlet

接下来实现服务器代码,BlogServlet 里面添加一个 doPost 方法,来处理上述 post 请求~~

核心操作,就是读取请求中的标题和正文,构造 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、修改客户端代码 blog_edit.html

首先,这里就需要整一个 form 表单,把这里 blog-edit-container 的内容给套上~~

在这里插入图片描述

1、加了个 form 表单,把之前的输入框啥的包裹起来了~

2、给标题的输入框,加上了 name 属性

3、发布按钮,改成了 input 标签

4、创建了一个隐藏的 textarea 为了后续的 form 提交 <textarea name="content" style="display: none;"></textarea>

5、下面设置了一个标志位,使当前的输入框的内容能够自动保存到 textarea 中 saveHTMLToTextarea: true,

6、同样改成了 input,要对选择器进行调整,保证提交按钮的样式不丢失,发布按钮 id 设为 submit

代码:

<!-- 包裹整个博客编辑页内容的顶级容器 -->
<div class="blog-edit-container">
    <form action="blog" method="post">
        <div class="title">
            <input type="text" placeholder="在此处输入标题" name="title">
            <!-- <button>发布文章</button> -->
            <input type="submit" value="发布文章" id="submit">
        </div>
        <!-- 放置 md 编辑器 -->
        <div id="editor">
            <!-- 为了进行 form 的提交, 此处搞一个 textarea 多行编辑框, 借助这个编辑框来实现表单的提交 -->
            <!-- 可以设置 editor.md, 让编辑器把 markdown 内容也同步的保存到这个隐藏的 textarea 中, 从而可以进行 form 提交 -->
            <textarea name="content" style="display: none"></textarea>
        </div>
    </form>
</div>

<script>
    // 初始化编辑器
    let editor = editormd("editor", {
        // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. 
        width: "100%",
        // 设定编辑器高度
        height: "calc(100% - 50px)", /* 减 titile 的高度 */
        // 编辑器中的初始内容
        markdown: "# 在这里写下一篇博客",
        // 指定 editor.md 依赖的插件路径
        path: "editor.md/lib/",
        // 此处要加上一个重要的选项, 然后 editor.md 就会自动把用户在编辑器输入的内容同步保存到 隐藏的 textarea 中了!
        saveHTMLToTextarea: true,
    });
</script>

样式: blog_edit.css

.blog-edit-container .title #submit {
    width: 100px;
    height: 40px;
    border-radius: 10px;
    
    color: white;
    background-color: orange;
    border: none;
    outline: none;
    font-size: 18px; /* 调整按钮文字大小 */
}

.blog-edit-container .title #submit:active {
    background-color: #666;
}

——验证 修改

在这里插入图片描述

改动了代码之后,果然就出问题了!!
代码出问题,都是很正常的情况,不出问题,才是不科学的

#editor 设置了一个这样的高度:100% - 50px

100% 是相对于父元素的高度,之前 #editor 的父亲是 container,
但是包上一层 form 之后,此时 #editor 的父亲就是 form 了,而 form 自身没有高度,这个 100% 没撑起来~~

在这里插入图片描述

**修改: ** 再设置 id,让样式不影响按钮

<input type="text" placeholder="在此处输入标题" name="title" id="title">
.blog-edit-container .title #title {
    width: 895px;
    height: 40px;
    border-radius: 10px;
    border: none;
    outline: none;
    font-size: 22px;
    line-height: 40px;
    padding-left: 10px;

    background-color: rgba(255, 255, 255, 0.8);
}

当前博客发布这个功能,之所以比较复杂,主要是用了 form 表单来构造 HTTP 请求,就需要改标签结构,进一步的又要改样式…
但是这里如果不用 form 表单,也能实现类似的效果,基于 ajax 也能构造出 HTTP 请求来提交标题和正文~~


十一、实现删除博客功能

约定,只有自己能删除自己的博客,不能删除别人的博客!!! (此处咱们暂时不考虑管理员)

1、界面上的处理 blog_detail.html

博客详情页这里,就去进行判定,判定看当前这个博客的作者,是否就是登录的用户,

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

在博客详情页这块,其实既从服务器获取了当前用户的登录信息,又获取到了博客的作者信息。主要看这两个接口返回的用户信息是不是一样的?

这里大家一定要注意理解!!! 这两个函数,调用之后,就给服务器发送了两个 HTTP 请求,然后,这两个请求对应的响应,谁先回来,不确定!!
虽然函数有先后,但是两个 ajax 请求是并发的关系

第一个 ajax 发出去之后,不等响应回来,就已经发了第二个 ajax,这正是 ajax 名字的含义
asynchronize

如果这两个响应到达的顺序不确定,就不好进行判定了,必须手动的调整让这两个方法,按照一定的顺序来进行发送~~

在这里插入图片描述

代码:

<!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/picture.jpg" alt="">
        <span>我的博客系统</span>

        <!-- 空白元素 用来占位 -->
        <div class="spacer"></div>

        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <!-- <a href="#">注销</a> -->
        <a href="logout">注销</a>
    </div>

    <!-- .container 作为页面的版心 -->
    <div class="container">
        <!-- 左侧个人信息 -->
        <div class="left">
            <!-- 整个用户信息区 -->
            <div class="card">
                <img src="image/picture.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-content">
                <!-- 博客标题 -->
                <h3></h3>
                <!-- 博客日期 -->
                <div class="date"></div>
                <!-- 博客的正文内容 -->
                <div id="content" style="opacity: 73%;">

                </div>
            </div>
        </div>
    </div>

    <!-- 在这里引入上述的 js 文件, 就可以执行到里面的代码, 也就进行了登录状态的监测了 -->
    <!-- <script src="js/common.js"></script> -->
    <script>
        function getBlogDetail() {
            $.ajax({
                type: 'get',
                // location.search 拿到了形如 '?blogId=5' 这样的一段内容
                url: 'blog' + location.search,
                success: function(body) { // body 中就是一个 js 对象
                    // 根据 body 中的内容来构造页面
                    // 1. 构造博客标题
                    let h3 = document.querySelector('.blog-content>h3');
                    h3.innerHTML = body.title;
                    // 2. 构造博客发布时间
                    let dateDiv = document.querySelector('.date');
                    dateDiv.innerHTML = body.postTime;
                    // 3. 构造博客正文
                    // let contentDiv = document.querySelector('#content');
                    // contentDiv.innerHTML = body.content;
                    // 如果直接把 content 设为 innerHTML, 此时展示在界面上的内容, 是原始的 markdown 字符串
                    // 咱们需要的是渲染后的, 带有格式的效果

                    // 第一个参数对应 id=content 的 html 标签. 渲染后得到的 html 片段就会被放到这个 标签下.
                    editormd.markdownToHTML('content', {
                        markdown: body.content
                    });
                }
            });
        }

        getBlogDetail();


        // 加上一个逻辑, 通过 GET /login 这个接口来获取下当前的登录状态~
        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);

                        // 在 getUesrInfo 的回到函数汇总,来调用获取作者信息
                        getAuthorInfo(body); //
                    } else {
                        // 登录失败!
                        // 让前端页面, 跳转到 login.html
                        alert("当前您尚未登录! 请登录后再访问博客列表!");
                        location.assign('blog_login.html');
                    }
                },
                error: function() {
                    alert("当前您尚未登录! 请登录后再访问博客列表!");
                    location.assign('blog_login.html');
                }
            });
        }

        // 判定用户登录状态
        getUserInfo('blog_detail.html');

        // 从服务器获取一下当前博客的作者信息, 并显示到界面上.
        // 参数 user 就是刚才从服务器拿到的当前登录用户的信息
        function getAuthorInfo(user) {
            $.ajax({
                type: 'get',
                url: 'authorInfo' + location.search,
                success: function(body) {
                    // 此处的 body, 就是服务器返回的 User 对象, 是文章的作者信息
                    if (body.username) {
                        // 如果响应中的 username 存在, 就把这个值设置到页面上.
                        changeUserName(body.username);

                        if (body.username == user.username) {
                            // 作者和登录的用户是同一个人,显示 "删除按钮"
                            let navDiv = document.querySelector('.nav'); // 导航栏
                            let a = document.createElement('a'); // 加入 a 标签
                            a.innerHTML = '删除';
                            // 希望点击删除 构造一个形如 blogDelete?blogId=6 的请求
                            a.href = 'blogDelete' + location.search;
                            navDiv.appendChild(a);
                        }
                    } else {
                        console.log("获取作者信息失败! " + body.reason);
                    }
                }
            });
        }

        function changeUserName(username) {
            let h3 = document.querySelector('.card>h3');
            h3.innerHTML = username;
        }

    </script>

</body>
</html>

在这里插入图片描述

这是关键代码,要在第一个 ajax 的回调中
执行第二个 ajax,才能保证两个 ajax 之间获取数据的顺序先后~~

当前咱们只是两个 ajax 还好,即使是在回调里嵌套调用 ajax。也勉强能接受~~
但是如果咱们要进行的操作有十个八个的,如果一直是前一个 ajax 回调里面调用下一个 ajax 代码写起来就会非常之丑陋!!!
“回调地狱”

js ES6 引入了 Promise 就能解决这个问题~~
ES7 引入 async 和 await,能够更佳优雅的解决上述问题了~~

通过这些语法,能够简化代码,让代码看起来没那么复杂,没那么丑陋,执行的效果仍然是一样的


2、约定交互接口

请求:

GET /blogDelete?blogld=7

响应:

直接跳转到博客列表页即可


3、服务器代码 BlogDeleteServlet

创建 BlogDeleteServlet 类

服务器处理,用户点击删除按钮,触发一个 HTTP 请求, HTTP 请求就会让服务器删除指定的博客,服务器收到请求之后,就会把这个博客从数据库里给删除掉~~

package controller;

import model.Blog;
import model.BlogDao;
import model.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@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");
    }
}

4、——验证

登录 “lisi” 的账号,点击这篇博客,看到作者是 “lisi”,点击右上角的 ”删除“,即删除博客,跳转到博客列表页,查看数据库,此博客已被删除

在这里插入图片描述


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三春去后诸芳尽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值