JavaWeb项目—— 博客系统

文章目录

  • 效果展示
    • 1. 创建 maven 项目
    • 2. 设计数据库
    • 3. 封装数据库的操作代码
      • 3.1 创建 DBUtil 类
      • 3.2 创建 Blog(代表一篇博客)
      • 3.3 创建 User(代表一个用户)
      • 3.4 创建类 BlogDao(对博客表进行操作)
      • 3.5 创建类 UserDao (对用户表进行操作)
    • 4. 导入之前已经写好的前端代码
    • 5. 实现博客主页界面
      • 5.1 约定好前后端交互接口
      • 5.2 实现 BlogServlet
      • 5.3 实现 前端代码
    • 6. 实现博客详情界面
      • 6.1 约定好前后端交互接口
      • 6.2 实现BlogServlet
      • 6.3 实现前端代码
    • 7. 实现登录界面
      • 7.1 约定好前后端交互接口
      • 7.2 实现 LoginServlet
      • 7.3 实现前端代码
    • 8. 实现登录状态判定功能
      • 8.1 约定前后端交互接口
      • 8.2 在 LoginServlet 进行代码添加
      • 8.3 在前端代码中创建 common.js
      • 8.4 修改前端代码
    • 9. 实现显示用户信息功能
      • 9.1 约定好前后端交互接口
      • 9.2 实现 AuthorServlet 代码
      • 9.3 实现前端代码
        • 针对博客列表页进行修改
        • 针对博客详情页
    • 10. 实现注销功能
      • 10.1 约定好前后端交互接口
      • 10.2 实现 LogouServlet
      • 10.3 实现前端代码
    • 11. 实现发布博客功能
      • 11.1 约定好前后端交互的接口
      • 11.2 在BlogServlet中添加doPost方法
      • 11.3 实现前端代码
    • 12. 删除博客
      • 12.1 约定号前后端交互接口
      • 12.1 实现前端代码
      • 12.2 实现BlogDeleteServlet

效果展示

JavaWeb项目—— 博客系统_第1张图片

JavaWeb项目—— 博客系统_第2张图片


1. 创建 maven 项目

创建必要的目录,引入需要的依赖

JavaWeb项目—— 博客系统_第3张图片
JavaWeb项目—— 博客系统_第4张图片
JavaWeb项目—— 博客系统_第5张图片

2. 设计数据库

本系统要存入博客文章的信息用户的信息

创建博客表:

博客的 id,博客的标题,博客的内容,博客的日期,博文的博主 id

创建用户表:

用户 id 用户名 用户密码

-- 创建一个数据库
create database if not exists java102_blog;

use java102_blog;

-- 创建一个博客表.
drop table if exists blog;
create table blog (
    blogId int primary key auto_increment,
    title varchar(1024),
    content mediumtext,
    userId int,         -- 文章作者的 id
    postTime datetime   -- 发布时间
);

---- 给博客表中插入点数据, 方便测试.
insert into blog values(null, '这是第一篇博客', '从今天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第二篇博客', '从昨天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第三篇博客', '从前天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第一篇博客', '从今天开始, 我要认真学 C++', 2, now());
insert into blog values(null, '这是第二篇博客', '从昨天开始, 我要认真学 C++', 2, now());
insert into blog values(null, '这是第三篇博客', '# 一级标题\n ### 三级标题\n > 这是引用内容', 2, now());

-- 创建一个用户表
drop table if exists user;
create table user (
    userId int primary key auto_increment,
    username varchar(128) unique,    -- 后续会使用用户名进行登录, 一般用于登录的用户名都是不能重复的.
    password varchar(128)
);

insert into user values(null, 'zhangsan', '123');
insert into user values(null, 'lisi', '123');
insert into user values(null, 'ling', '123');

3. 封装数据库的操作代码

创建包 model 用来存放数据库的代码

3.1 创建 DBUtil 类

用于和数据库建立连接

package model;

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 *这个类 封装 和 建立 数据库 连接 的 操作
 */
public class DBUtil {
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/java102_blog?characterEncoding=utf8&useSSL=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "707703";

    private volatile static DataSource dataSource = null;

    private static DataSource getDataSource() {
        if(dataSource == null) {
            synchronized (DBUtil.class) {
                if(dataSource == null) {
                    dataSource = new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setUrl(URL);
                    ((MysqlDataSource)dataSource).setUser(USERNAME);
                    ((MysqlDataSource)dataSource).setPassword(PASSWORD);
                }
            }
        }
        return dataSource;
    }

    // 建立链接
    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    // 断开链接
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet)  {
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(statement != null) {
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}


3.2 创建 Blog(代表一篇博客)

package model;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;

// 每个 blog对象 ,对应 blog 表里的一条记录
public class Blog {
    private int blogId;
    private String title;
    private String content;
    private int userId;
    private Timestamp postTime;

    public int getBlogId() {
        return blogId;
    }

    public void setBlogId(int blogId) {
        this.blogId = blogId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }
    
    // 把这里 的 getter 方法给改了,不是返回一个 时间搓对象,而是返回一个 string(格式化的时间)
    public String getPostTime() {
        // 使用这个类 来完成时间戳到格式化日期的转换
        // 这个 转换过程,需要构造方法中制定要转换的格式,然后调用 format 来进行转换
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }


    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}

3.3 创建 User(代表一个用户)

package model;

// 每个 model.User 对象, 期望能够表示 user 表中的一条记录.
public class User {
    private int userId = 0;
    private String username = "";
    private String password = "";
    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

3.4 创建类 BlogDao(对博客表进行操作)

注意:
对数据进行插入删除操作时,执行 sql:
JavaWeb项目—— 博客系统_第6张图片
其他操作:
JavaWeb项目—— 博客系统_第7张图片
插入顺序:
在这里插入图片描述

package model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 这个类用于去封装博客表的 基本操作
 */
public class BlogDao {
    // 1.往博客表里,插入一个博客
    public void insert(Blog blog) {
        // JDBC 代码
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            // 1. 先和数据库建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "insert into blog values(null,?,?,?,now())";
            statement = connection.prepareStatement(sql);
            // 赋值
            statement.setString(1, blog.getTitle());
            statement.setString(2, blog.getContent());
            statement.setInt(3,blog.getUserId());
            // 3. 执行 sql
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 4. 关闭连接,释放资源
            DBUtil.close(connection,statement,null);
        }
    }

    // 2. 获取博客列表中的所有博客信息
    public List selectAll() {
        List blogs = new ArrayList<>();
        // JDBC 代码
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            // 1. 先建立链接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "select * from blog order by postTime desc";
            statement = connection.prepareStatement(sql);
            // 3. 执行 sql
            resultSet = statement.executeQuery();
            // 把查询到的数据 存储到 blogs 当中
            while (resultSet.next()) {
                Blog blog = new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                // 这里需要针对内容进行截断(太长,就去掉后面的)
                String content = resultSet.getString("content");
                if(content.length() > 50) {
                    content = content.substring(0,50) + "..点进来吧我的宝";
                }
                blog.setContent(content);
                blog.setUserId(resultSet.getShort("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blogs.add(blog);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return blogs;
    }

    // 3. 能够根据博客 id 获取到制定的博客内容(用于博客详情页)
    public Blog selectOne(int blogId) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
            // 1. 建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "select * from blog where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            // 3. 执行 sql
            resultSet = statement.executeQuery();
            // 此处我们是使用 主键 来作为 查询条件,查询结果,要么是 1,要么是 0
            if(resultSet.next()) {
                Blog blog = new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setUserId(resultSet.getShort("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                return blog;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 4. 关闭连接 释放资源
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    // 4.  从博客列表中,根据博客 id 删除博客
    public void delete(int blogId) {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            // 1. 建立 连接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "delete from blog where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            // 3. 执行 sql
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
}

3.5 创建类 UserDao (对用户表进行操作)

package model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 这个类用于 封装 用户表的 基本操作
 */
public class UserDao {

    // 1. 根据用户名 查找用户信息
    public User selectByName(String username) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
            // 1. 建立 连接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "select * from user where username = ?";
            statement = connection.prepareStatement(sql);
            statement.setString(1,username);
            // 3. 执行 sql
            resultSet = statement.executeQuery();
            if(resultSet.next()) {
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 4. 关闭连接 释放资源
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    // 2. 根据 用户 id 来找 用户信息
    // 博客详情页 就可以根据用户 id 来查询作者的名字,把作者名字显示出来
    public User selectById(int userId) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            // 1. 建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 sql 语句
            String sql = "select * from user where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,userId);
            // 3. 执行sql
            resultSet = statement.executeQuery();
            // 此处的 username 使用 unique 约束,要么能查到一个,要么一个都查不到
            // 4. 遍历结果集
            if(resultSet.next()) {
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
}


4. 导入之前已经写好的前端代码

JavaWeb项目—— 博客系统_第8张图片

5. 实现博客主页界面

5.1 约定好前后端交互接口

JavaWeb项目—— 博客系统_第9张图片

5.2 实现 BlogServlet

import model.BlogDao;

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;
import java.util.List;

// 通过这个类, 来处理 /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 blogs = blogDao.selectAll();
         //把 blogs 对象转成 JSON 格式.
        String respJson = objectMapper.writeValueAsString(blogs);
        resp.setContentType("application/json; charset=utf8");
        resp.getWriter().write(respJson);
    }
}

5.3 实现 前端代码

在 blog_list.html 中 实现 ajax

注意:引入依赖


    

6. 实现博客详情界面

6.1 约定好前后端交互接口

JavaWeb项目—— 博客系统_第10张图片

6.2 实现BlogServlet

这里后端代码和博客列表页的获取,基本相同,就直接放到一个方法中,来实现!使用blogId参数来区别是获取博客列表还是详情
这里注意:博客列表页在也在BlogServlet中实现的,我们如何去区别呢?:
JavaWeb项目—— 博客系统_第11张图片

package controller;

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

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;
import java.util.List;

/**
 * // doGet 获取博客列表页
 */
@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 param = req.getParameter("blogId");
        if (param == null) {
            // 不存在参数, 获取博客列表
            List blogs = blogDao.selectAll();
            // 把 blogs 对象转成 JSON 格式.
            String respJson = objectMapper.writeValueAsString(blogs);
            resp.getWriter().write(respJson);
        } else {
            // 存在参数, 获取博客详情
            int blogId = Integer.parseInt(param);
            Blog blog = blogDao.selectOne(blogId);
            String respJson = objectMapper.writeValueAsString(blog);
            resp.getWriter().write(respJson);
        }
    }
}

6.3 实现前端代码

修改 blog_detail.html,让这个页面加载的时候,能够调用到上述的接口,来从服务器获取到博客数据

注意:
JavaWeb项目—— 博客系统_第12张图片

在这里插入图片描述

在博客详情页中引入 editor



7. 实现登录界面

这里需要注意:啥样才算是已经登录

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

这里先给注销做铺垫:理解一下注销是如何操作的:

注销只要破坏掉上面的任意一个条件就行了

7.1 约定好前后端交互接口

JavaWeb项目—— 博客系统_第13张图片

7.2 实现 LoginServlet

package controller;

import com.fasterxml.jackson.databind.ObjectMapper;
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 javax.servlet.http.HttpSession;
import java.io.IOException;


// 实现登录页面
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private  ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        // 1. 获取到请求中的参数
        String username = req.getParameter("username");
        String password = req.getParameter("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");
    }
 }

7.3 实现前端代码

修改blog_login.html 这里只需要在原来登录操作上套上一层 form 标签就可以了
JavaWeb项目—— 博客系统_第14张图片

因为这里在原有的基础上填上了 form表单,我们在 css 中也会有一些改动

JavaWeb项目—— 博客系统_第15张图片




    
    
    
    登录页面
    
    


     
     
    
    

8. 实现登录状态判定功能

JavaWeb项目—— 博客系统_第16张图片

8.1 约定前后端交互接口

JavaWeb项目—— 博客系统_第17张图片

8.2 在 LoginServlet 进行代码添加

package controller;

import com.fasterxml.jackson.databind.ObjectMapper;
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 javax.servlet.http.HttpSession;
import java.io.IOException;


// 实现登录页面
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private  ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        // 1. 获取到请求中的参数
        String username = req.getParameter("username");
        String password = req.getParameter("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");
    }


 //   //  这个方法用来让前端检测当前的登录状态~~~~~~~~~~~~~~~~~~~~~~
    // 1)检测有无会话 2)检测有无属性
    @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) {
           // 1) 检测有无会话,无说明未登录
           // 创建对象--> 里面为空
           User user = new User();
           resp.getWriter().write(objectMapper.writeValueAsString(user));
           return;
       }
       User user = (User) session.getAttribute("user");
       if(user == null) {
           // 2)虽然有会话,但是会话里如果没有 user 对象,也视为未登录
           user = new User();
           resp.getWriter().write(objectMapper.writeValueAsString(user));
           return;
       }
       // 已经登录的状态!
        // 注意,此处不要把密码返回到前端
        user.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }
}

8.3 在前端代码中创建 common.js

JavaWeb项目—— 博客系统_第18张图片

// 这个文件里放一些 页面公共的代码
// 加上一个逻辑,通过 GET/login 这个接口来获取下当前的登录状态
function getUserInfo() {
    $.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');
        }
    });
    

}
getUserInfo();

8.4 修改前端代码

blog_list.html blog_detil.html 中引入 js文件,就可以执行到里面的代码,也就进行了登录状态的监测了

 

JavaWeb项目—— 博客系统_第19张图片
JavaWeb项目—— 博客系统_第20张图片

9. 实现显示用户信息功能

9.1 约定好前后端交互接口

9.2 实现 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;


/**
 * 根据博客 id 查 博客信息
 * 根据 博客信息里的 作者 id 查 作者信息
 */
@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));

    }
}

9.3 实现前端代码

在这里插入图片描述

针对博客列表页进行修改

在 common.js 中 修改代码
JavaWeb项目—— 博客系统_第21张图片

针对博客详情页


10. 实现注销功能

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

10.1 约定好前后端交互接口

JavaWeb项目—— 博客系统_第22张图片

10.2 实现 LogouServlet

package controller;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Enumeration;

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

10.3 实现前端代码

将 blog_detail.html blog_list.html bloh_edit.htm中的注销标签进行修改

JavaWeb项目—— 博客系统_第23张图片

11. 实现发布博客功能

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

11.1 约定好前后端交互的接口

JavaWeb项目—— 博客系统_第24张图片

11.2 在BlogServlet中添加doPost方法

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

11.3 实现前端代码

JavaWeb项目—— 博客系统_第25张图片
JavaWeb项目—— 博客系统_第26张图片
JavaWeb项目—— 博客系统_第27张图片




    
    
    
    博客编辑页
    
    
   

    
    
    
    
    
    


    
    
    
    
    

12. 删除博客

JavaWeb项目—— 博客系统_第28张图片

12.1 约定号前后端交互接口

JavaWeb项目—— 博客系统_第29张图片

12.1 实现前端代码

 

12.2 实现BlogDeleteServlet

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


你可能感兴趣的