项目-博客系统(基于云服务器)

目录

前言

创建maven项目

数据库的设计 

封装数据库的操作代码

1、创建DBUtil类

2、创建Blog

3、创建User

4、创建BlogDao

5、创建UserDao

博客系统的前端代码

1、博客列表页

2、博客详情页

3、登录页

4、博客编辑页

前后端交互

1、实现博客列表的展示功能

1.1、约定前后端交互接口

1.2、实现BlogServlet 

1.3、实现前端代码

2、实现博客详情的展示功能

2.1、 约定前后端交互接口

2.2、实现BlogServlet

2.3、实现前端代码

3、登录功能(暂时不实现注册)

3.1、 约定前后端交互接口 

3.2、实现LoginServlet

3.3、实现前端代码 

4、实现登录状态判定功能

4.1、 约定前后端交互接口

4.2、在LoginServlet进行代码添加

4.3、实现前端代码

5、显示用户的信息

5.1查询用户信息或者作者信息

5.2 实现前端代码

6、实现注销(退出登录)

6.1、 约定前后端交互接口 

6.2、实现LogoutServlet

6.3、实现前端代码

7、发布博客

7.1、 约定前后端交互接口 

7.2、在BlogServlet中添加doPost方法

7.3、 实现前端代码

8、删除博客

8.1、 约定前后端交互接口 

8.2、实现BlogDeleteServlet 

8.3、实现前端代码

部署到云服务器


前言

目前为止,已经学完了前端知识和部分的后端知识,现在,基于所学知识,实现一个简易的个人博客系统,技术栈后端为Tomcat+Servlet+Mysql,前端为css+html+js

创建maven项目

创建目录,引入依赖

数据库的设计 

整个博客系统所用到的有两个表:博客表和用户表

博客表

blog(blogId,title,content,postTime,useId)

用户表

user(userId,username,password)

create database if not exists java105_blog_system;


use java105_blog_system;

drop table if exists blog;
create table blog (
    blogId int primary key auto_increment,
    title varchar(256),
    content text,
    postTime datetime,
    -- userId 就是文章作者的用户 id
    userId int
);

drop table if exists user;
create table user (
    userId int primary key auto_increment,
    username varchar(50) unique,
    password varchar(50)
);

insert into blog values(null, "这是第一篇博客", "Byeon BAEK HYUN, born on May 6, 1992 in Bucheon, Gyeonggi Province, South Korea, is a South Korean male singer and actor, member of male singing groups EXO, EXO-K, EXO-CBX and SuperM.", '2022-11-24 20:00:00', 1);
insert into blog values(null, "这是第二篇博客", "都敬秀,艺名D.O.(包括两个大写字母和两个标点符号),曾用名都暻秀,1993年1月12日出生于韩国日山,韩国男歌手、演员。2012年2月15日,D.O.通过Teaser正式被公开;同年4月8日,作为组合EXO/EXO-K的成员出道,在组合中担任主唱、EXO-K第三领舞,擅长欧美R&B式唱腔。", '2022-11-25 20:00:00', 1);
insert into blog values(null, "这是第三篇博客", "朴灿烈(박찬열、Park Chanyeol),1992年11月27日出生于韩国首尔,仁荷大学研究生在读,韩国男子演唱组合EXO、EXO-K、EXO-SC成员,韩国男歌手、演员。2012年4月8日,随EXO-K发行首张迷你专辑《MAMA》并正式出道。", '2022-11-26 20:00:00', 1);

insert into user values(null, "啵啵", "123");
insert into user values(null, "嘟嘟", "123");

封装数据库的操作代码

1、创建DBUtil类

用来封装数据库的DataSource

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

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

/**
 * @author krystal
 * @date 2022/12/2 13:01
 * 博客系统
 */
//通过这个类来封装DataSource
public class DBUtil {
    private static DataSource dataSource=null;

    public static DataSource getDataSource(){
        if (dataSource==null){
            synchronized (DBUtil.class){
                if (dataSource==null){
                    dataSource=new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java105_blog_system?characterEncoding=utf8&useSSL=false");
                    ((MysqlDataSource)dataSource).setUser("root");
                    ((MysqlDataSource)dataSource).setPassword("19930112");
                }
            }
        }
        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 e) {
                e.printStackTrace();
            }
        }

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

        if (resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2、创建Blog

代表一篇博客

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

/**
 * @author krystal
 * @date 2022/12/2 15:19
 * 博客系统
 */
public class Blog {
    private int blogId;
    private String title;
    private String content;
    private Timestamp postTime;
    private int userId;

    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 String getPostTime() {
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }

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

    public int getUserId() {
        return userId;
    }

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

3、创建User

代表一个用户

/**
 * @author krystal
 * @date 2022/12/2 15:19
 * 博客系统
 */
public class User {
    private int userId;
    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;
    }
}

4、创建BlogDao

针对博客表进行增删查改操作

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

/**
 * @author krystal
 * @date 2022/12/2 15:44
 * 博客系统
 */
//封装针对博客表的相关操作
public class BlogDao {
    //1、插入一个博客到数据库中-发布博客
    public void insert(Blog blog){
        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
            int ret=statement.executeUpdate();
            if (ret!=1){
                System.out.println("博客插入失败!");
            }else {
                System.out.println("博客插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //4、释放相应的资源
            DBUtil.close(connection,statement,null);
        }
    }

    //2、根据博客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();
            //4、遍历结果集合
            if (resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blog.setUserId(resultSet.getInt("userId"));
                return blog;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //3、直接查询博客列表-博客列表页
    public List<Blog> selectAll(){
        List<Blog> blogs=new ArrayList<>();
        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();
            //4、遍历结果集合
            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()>100){
                    content=content.substring(0,100)+"...";
                }
                blog.setContent(content);
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blog.setUserId(resultSet.getInt("userId"));
                blogs.add(blog);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return blogs;
    }

    //4、删除指定博客
    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
            int ret=statement.executeUpdate();
            if (ret!=1){
                System.out.println("博客删除失败!");
            }else {
                System.out.println("博客删除成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //4、释放相应的资源
            DBUtil.close(connection,statement,null);
        }

    }
}

5、创建UserDao

针对用户表进行增查操作

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

/**
 * @author krystal
 * @date 2022/12/2 15:55
 * 博客系统
 */
public class UserDao {
    //根据用户名来查询用户的详情
    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();
            //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 e) {
            e.printStackTrace();
        }
        return null;
    }

    //根据用户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();
            //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 e) {
            e.printStackTrace();
        }
        return null;
    }

}

博客系统的前端代码

1、博客列表页

<!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="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>

    <!-- 这个div表示页面的主区域(版心) -->
    <div class="container">
        <!-- 左侧内容区域 -->
        <div class="container-left">
            <!-- 用这个表示用户的信息 -->
            <div class="card">
                <!--用户头像-->
                <img src="img/logo3.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="container-right">
            <!-- 每个.blog代表一篇博客 -->
            <div class="blog">
                
                <a href="blog_detail.html">查看全文 &gt;&gt;</a>
            </div>
        </div>
    </div>
    
</body>
</html>

2、博客详情页

<!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/blod_detail.css">
</head>
<body>
    <div class="nav">
        <img src="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>

    <!-- 这个div表示页面的主区域(版心) -->
    <div class="container">
        <!-- 左侧内容区域 -->
        <div class="container-left">
            <!-- 用这个表示用户的信息 -->
            <div class="card">
                <!--用户头像-->
                <img src="img/logo3.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="container-right">
            <div class="blog_detail">
                <h3>我的第一篇博客</h3>
                <div class="date">1992-5-4 00.00.00</div>
                <p>
                    边伯贤,艺名BAEK HYUN,1992年5月6日生于韩国京畿道富川市,韩国男歌手、演员,男子演唱组合EXO、EXO-K、EXO-CBX、SuperM成员。
                </p>
            </div>
        </div>
</body>
</html>

3、登录页

<!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/login.css">
</head>
<body>
    <div class="nav">
        <img src="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- 用这个元素作为页面的版心 -->
    <div class="login-container">
        <!-- 登录对话框 -->
        <div class="dialog">
            <h3>登录</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" id="username">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" id="password">
            </div>
            <div class="row">
                <button id="login-btn">登录</button>
            </div>
        </div>
    </div>

</body>
</html>

4、博客编辑页

<!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_edit.css">

    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <!-- <script src="js/jquery.min.js"></script> -->
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/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="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- 整个编辑页的版心 -->
    <div class="blog-edit-container">
        <!-- 标题的编辑区 -->
        <div class="title">
            <!-- 输入的标题内容 -->
            <input type="text" id="blog-title" placeholder="在这里输入博客标题">
            <button id="submit">发布文章</button>
        </div>
        <!-- 正文的编辑区 -->
        <div id="editor"></div>
    </div>

    <script>
        // 初始化编辑器, 代码也是截取自 官方文档 . 
        var editor = editormd("editor", {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. 
            width: "100%",
            // 设定编辑器高度
            height: "calc(100% - 52px)",
            // 编辑器中的初始内容
            markdown: "## hello world",
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/"
        });
    </script>
</body>
</html>

前后端交互

1、实现博客列表的展示功能

1.1、约定前后端交互接口

1.2、实现BlogServlet 

import com.fasterxml.jackson.databind.ObjectMapper;

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

/**
 * @author krystal
 * @date 2022/12/2 18:06
 * 博客系统
 */
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 按照约定的接口格式返回数据
        // 在博客列表页中, 已经使用了 BlogServlet.doGet 方法了.
        // 博客详情页, 也想用. 就需要做出区分. 使用 query string 来区分.
        // 如果请求带有 query string , 有 blogId 这个参数, 就认为是博客详情页的请求.
        // 如果请求不带有 query string, 就认为是博客列表页的请求.
        resp.setContentType("application/json;charset=utf8");
        BlogDao blogDao=new BlogDao();
        String blogId=req.getParameter("blogId");
        if(blogId==null){
            //博客列表页发送的请求
            List<Blog> blogs=blogDao.selectAll();
            resp.getWriter().write(objectMapper.writeValueAsString(blogs));
        }else {
            //博客详情页发送的请求
            Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
            resp.getWriter().write(objectMapper.writeValueAsString(blog));
        }
    }

1.3、实现前端代码

在 blog_list.html 中 实现 ajax(注意引入依赖)

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script>
        //发送ajax从服务器获取数据
        function getBlogs(){
            $.ajax({
                type:'get',
                url:'blog',
                success:function(body){
                    //获取成功,则body就是一个js对象数组,每个元素就是一个博客
                    let container=document.querySelector('.container-right');
                    for(let blog of body){
                        //构造blogDiv
                        let blogDiv=document.createElement('div');
                        blogDiv.className='blog';

                        //构造博客标题
                        let titleDiv=document.createElement('div');
                        titleDiv.className='title';
                        titleDiv.innerHTML=blog.title;

                        //构造博客的日期
                        let dateDiv=document.createElement('div');
                        dateDiv.className='date';
                        dateDiv.innerHTML=blog.postTime;

                        //构造博客的摘要
                        let descDiv=document.createElement('div');
                        descDiv.className='desc';
                        descDiv.innerHTML=blog.content;

                        //构造全文查看按钮
                        let a=document.createElement('a');
                        a.href='blog_detail.html?blogId='+blog.blogId;
                        a.innerHTML='查看全文&gt;&gt';

                        //拼装最终结果
                        blogDiv.appendChild(titleDiv);
                        blogDiv.appendChild(dateDiv);
                        blogDiv.appendChild(descDiv);
                        blogDiv.appendChild(a);
                        container.appendChild(blogDiv);

                    }
                }
            });
        }

        //函数调用
        getBlogs();

2、实现博客详情的展示功能

2.1、 约定前后端交互接口

2.2、实现BlogServlet

import com.fasterxml.jackson.databind.ObjectMapper;

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

/**
 * @author krystal
 * @date 2022/12/2 18:06
 * 博客系统
 */
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 按照约定的接口格式返回数据
        // 在博客列表页中, 已经使用了 BlogServlet.doGet 方法了.
        // 博客详情页, 也想用. 就需要做出区分. 使用 query string 来区分.
        // 如果请求带有 query string , 有 blogId 这个参数, 就认为是博客详情页的请求.
        // 如果请求不带有 query string, 就认为是博客列表页的请求.
        resp.setContentType("application/json;charset=utf8");
        BlogDao blogDao=new BlogDao();
        String blogId=req.getParameter("blogId");
        if(blogId==null){
            //博客列表页发送的请求
            List<Blog> blogs=blogDao.selectAll();
            resp.getWriter().write(objectMapper.writeValueAsString(blogs));
        }else {
            //博客详情页发送的请求
            Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
            resp.getWriter().write(objectMapper.writeValueAsString(blog));
        }
    }

2.3、实现前端代码

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

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> 
    <script>
        function getBlog(){
            $.ajax({
                type:'get',
                url:'blog'+location.search,
                success:function(body){
                    let h3 = document.querySelector('.blog-detail>h3');
                    h3.innerHTML = body.title;
                    let dateDiv = document.querySelector('.blog-detail>.date');
                    dateDiv.innerHTML = body.postTime;
                    // let contentDiv = document.querySelector('#content');
                    // contentDiv.innerHTML = body.content;

                    // 此处使用 editor.md 来进行渲染
                    editormd.markdownToHTML('content', { markdown: body.content });
                }
            });
        }
        getBlog();

3、登录功能(暂时不实现注册)

用户有一个session,同时session有一个User属性,两者兼备才算登录状态

3.1、 约定前后端交互接口 

3.2、实现LoginServlet

/**
 * @author krystal
 * @date 2022/12/6 9:15
 * 博客系统
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、从请求中获取用户名和密码
        req.setCharacterEncoding("utf-8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if (username==null || username.equals("") || password==null || password.equals("")){
            //用户名密码为空,直接登陆失败
            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);
        //在回话中保存user
        session.setAttribute("user",user);

        //4、构造302响应报文
        resp.sendRedirect("blog_list.html");
    }

3.3、实现前端代码 

<!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/login.css">
</head>
<body>
    <div class="nav">
        <img src="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="logout">注销</a>
    </div>
    <!-- 用这个元素作为页面的版心 -->
    <div class="login-container">
        <form action="login" method="post">
            <!-- 登录对话框 -->
            <div class="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="login-btn" value="登陆">
                </div>
            </div>
        </form>
    </div>

</body>
</html>

4、实现登录状态判定功能

4.1、 约定前后端交互接口

4.2、在LoginServlet进行代码添加

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用这个方法来针对当前登录状态进行判定
        //1、获取一下当前的会话
        HttpSession session=req.getSession(false);
        if (session==null){
            //没有会话,当前是未登录状态
            resp.setStatus(403);
            return;
        }
        //判断user对象是否存在
        User user=(User) session.getAttribute("user");
        if (user==null){
            //虽然有会话,但是没有user对象,也认为是未登录状态
            resp.setStatus(403);
            return;
        }

        //2、返回200这样的响应即可
        resp.setStatus(200);
    }

4.3、实现前端代码

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

function getLoginStatus(){
    $.ajax({
        type:'get',
        url:'login',
        success:function(body){
            //得到200,此处不做任何工作
            console.log("当前已经登陆过!");
        },
        error:function(){
            //得到403
            //让页面强行转到login.html
            console.log("当前还未登陆!");
            location.assign('login.html');
        }
    });
}

5、显示用户的信息

5.1查询用户信息或者作者信息

import com.fasterxml.jackson.databind.ObjectMapper;

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("/userInfo")
public class UserInfoServlet extends HttpServlet {
    ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取用户信息
        String blogId = req.getParameter("blogId");
        if (blogId == null) {
            // 列表页, 获取当前登陆用户的信息
            // 直接从 session 中获取即可~~
            getUserInfoFromSession(req, resp);
        } else {
            // 详情页, 获取文章作者的信息
            // 查询数据库
            getUserInfoFromDB(req, resp, Integer.parseInt(blogId));
        }
    }

    private void getUserInfoFromDB(HttpServletRequest req, HttpServletResponse resp, int blogId) throws IOException {
        // 1. 先根据 blogId 查询 Blog 对象, 获取到 userId (作者是谁)
        BlogDao blogDao = new BlogDao();
        Blog blog = blogDao.selectOne(blogId);
        if (blog == null) {
            // 如果参数传来的这个 blogId 是随便瞎写的. 数据库里没有.
            resp.setStatus(404);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("blogId 不存在");
            return;
        }
        // 2. 根据 userId 查询对应的 User 对象即可
        UserDao userDao = new UserDao();
        User user = userDao.selectById(blog.getUserId());
        if (user == null) {
            resp.setStatus(404);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("blogId 不存在");
            return;
        }
        // 3. 把 user 对象返回给浏览器了
        user.setPassword("");
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }

    private void getUserInfoFromSession(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        HttpSession session = req.getSession(false);
        if (session == null) {
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("当前未登录");
            return;
        }
        User user = (User) session.getAttribute("user");
        if (user == null) {
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("当前未登录");
            return;
        }
        // user 获取到了, 把 user 中的 password 给干掉, 然后返回.
        user.setPassword("");

        resp.setContentType("application/json; charset=utf-8");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }
}

5.2 实现前端代码

        // 针对博客列表页, 获取到当前用户的登陆信息
        function getUserInfo() {
            $.ajax({
                type: 'get',
                url: 'userInfo',
                success: function(body) {
                    // 获取成功, body 就是一个 User 对象
                    // 把 user 对象里的内容填写到页面上即可. 
                    // 此处主要就是填用户名. 
                    console.log(body);
                    // github 地址, 头像, 就只要改动 user 表即可. 
                    let h3 = document.querySelector('.container-left>.card>h3');
                    h3.innerHTML = body.username;
                }
            });
        }

        getUserInfo();


        function getUserInfo(){
            $.ajax({
                type:'get',
                url:'userInfo'+location.search,
                success:function(body){
                    //获取成功,body就是一个user对象
                    //把user对象里的内容填写到页面上即可
                    let h3=document.querySelector('.container-left>.card>h3');
                    h3.innerHTML=body.username;
                }
            });
        }

        getUserInfo();

6、实现注销(退出登录)

6.1、 约定前后端交互接口 

6.2、实现LogoutServlet

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;

/**
 * @author krystal
 * @date 2022/12/8 17:42
 * 博客系统
 */
@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.setStatus(403);
            return;
        }
        //直接把session中之前的user对象删除掉
        session.removeAttribute("user");
        //重定向到登录页面
        resp.sendRedirect("login.html");
    }
}

6.3、实现前端代码

 

7、发布博客

7.1、 约定前后端交互接口 

7.2、在BlogServlet中添加doPost方法

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用这个方法,来实现提交新博客
        //1、先检查用户的登录状态,获取到会话和用户信息
        //未登录,不能提交博客
        HttpSession session = req.getSession(false);
        if (session == null) {
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("当前未登录,不能发布博客!");
            return;
        }
        User user = (User) session.getAttribute("user");
        if (user == null) {
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("当前未登录,不能发布博客!");
            return;
        }
        //2、获取请求中的参数(博客正文和标题)
        req.setCharacterEncoding("utf-8");
        String title=req.getParameter("title");
        String content=req.getParameter("content");
        //3、构造Blog对象,并插入到数据库中
        Blog blog=new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        blog.setUserId(user.getUserId());
        BlogDao blogDao=new BlogDao();
        blogDao.insert(blog);
        //4、构造重定向报文,回到博客列表页
        resp.sendRedirect("blog_list.html");
    }

7.3、 实现前端代码

<!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_edit.css">

    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <!-- <script src="js/jquery.min.js"></script> -->
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/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="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <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" id="blog-title" placeholder="在这里输入博客标题" name="title">
                <input id="submit" value="发布文章" type="submit">
            </div>
            <!-- 正文的编辑区 -->
            <div id="editor">
                <textarea name="content" style="display: none"></textarea>
            </div>
        </form>
    </div>

    <script src="js/app.js"></script>
    <script>
        // 初始化编辑器, 代码也是截取自 官方文档 . 
        var editor = editormd("editor", {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. 
            width: "100%",
            // 设定编辑器高度
            height: "calc(100% - 52px)",
            // 编辑器中的初始内容
            markdown: "## hello world",
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/",
            saveHTMLToTextarea:true,
        });

        getLoginStatus();
    </script>
</body>
</html>

8、删除博客

8.1、 约定前后端交互接口 

8.2、实现BlogDeleteServlet 

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;

/**
 * @author krystal
 * @date 2022/12/8 18:42
 * 博客系统
 */
@WebServlet("/blog_delete")
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.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("您当前未登录,不能进行删除操作");
            return;
        }
        User user = (User) session.getAttribute("user");
        if (user == null) {
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("您当前未登录,不能进行删除操作");
            return;
        }
        //2、获取到blogId
        String blogId=req.getParameter("blogId");
        if (blogId==null){
            //这个blogId参数不存在,无法删除
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("您当前删除的blogId有误");
            return;
        }
        //3、查询出这个blogId对应的blog对象
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
        if (blog==null){
            resp.setStatus(404);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("您当前删除的博客不存在,blogId="+blogId);
            return;
        }
        //4、判定登录用户是否就是文章作者
        if (blog.getUserId()!= user.getUserId()){
            //blog.getUserId()是文章作者id
            //user.getUserId()是session里登陆的用户
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("您不能删除别人的博客");
            return;
        }
        //5、真正执行删除操作
        blogDao.delete(Integer.parseInt(blogId));
        //6、返回302重定向
        resp.sendRedirect("blog_list.html");
    }
}

8.3、实现前端代码

<!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="https://apps.bdimg.com/libs/jquery/2.1.4/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="img/logo1.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- spacer不显示内容,占位 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="logout">注销</a>
        <a href="#" id="delete-btn">删除</a>
    </div>

    <!-- 这个div表示页面的主区域(版心) -->
    <div class="container">
        <!-- 左侧内容区域 -->
        <div class="container-left">
            <!-- 用这个表示用户的信息 -->
            <div class="card">
                <!--用户头像-->
                <img src="img/logo3.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="container-right">
            <div class="blog-detail">
                <h3></h3>
                <div class="date"></div>
                <div id="content"  style="background-color: transparent">

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

    <!-- <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> -->
    <script src="js/app.js"></script>
    <script>
        function getBlog(){
            $.ajax({
                type:'get',
                url:'blog'+location.search,
                success:function(body){
                    let h3 = document.querySelector('.blog-detail>h3');
                    h3.innerHTML = body.title;
                    let dateDiv = document.querySelector('.blog-detail>.date');
                    dateDiv.innerHTML = body.postTime;
                    // let contentDiv = document.querySelector('#content');
                    // contentDiv.innerHTML = body.content;

                    // 此处使用 editor.md 来进行渲染
                    editormd.markdownToHTML('content', { markdown: body.content });
                }
            });
        }
        getBlog();

        getLoginStatus();

        function getUserInfo(){
            $.ajax({
                type:'get',
                url:'userInfo'+location.search,
                success:function(body){
                    //获取成功,body就是一个user对象
                    //把user对象里的内容填写到页面上即可
                    let h3=document.querySelector('.container-left>.card>h3');
                    h3.innerHTML=body.username;
                }
            });
        }

        getUserInfo();

        function updateDeleteURL(){
            let deleteBtn=document.querySelector("#delete-btn");
            deleteBtn.href='blog_delete'+location.search;
        }

        updateDeleteURL();
    </script>
</body>
</html>

部署到云服务器

参考部署过程

此处是博主的博客系统

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值