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

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

1.准备工作


该步骤完成主要的maven项目搭建,与一般的servlet项目开发流程相同。

1)创建maven项目


微信图片_20230111181133.png

2)引入必要依赖

MySQL 5版本依赖

servlet 3.1.0 版本依赖

jackson依赖


在pom文件中引入这些依赖

微信图片_20230111181128.png

3.创建必要目录,填写web.xml文件的代码块


微信图片_20230111181126.png


微信图片_20230111181123.png

4.编写基本servlet代码,用于测试环境是否搭建完成

微信图片_20230111181118.png

5、6打包部署

微信图片_20230111181109.png

7.验证


微信图片_20230111181114.png

2.前端页面设计


在这一步,我们先完成前端页面的设计,填写基本的内容,了解基本的业务需求,共需要设计以下界面:


2.1 博客列表页

微信图片_20230111181106.png


列表页HTML代码:blog_list.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客列表</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_list.css">
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- container作为页面的版心 -->
    <div class="container">
        <!-- 左侧个人信息 -->
        <div class="left">
            <!-- 表示整个用户信息区域 -->
            <div class="card">
                <img src="image/2.jpg" alt="">
                <h3>如风暖阳</h3>
                <a href="#">gitHub地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧个人信息 -->
        <div class="right">
            <!-- .blog对应一个博客 -->
            <div class="blog">
                <!-- 博客标题 -->
                <div class="title">
                    我的第一篇博客
                </div>
                <!-- 博客发布时间 -->
                <div class="date">
                    2022-10-21 21:24:00
                </div>
                <div class="desc">
                    刷爆LeetCode!Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore, hic ipsa veritatis adipisci rem, provident accusantium deserunt soluta magnam distinctio consequatur fugit, neque omnis explicabo deleniti reiciendis magni architecto eaque!
                </div>
                <a href="#">查看全文&gt;&gt;</a>
            </div>
            <div class="blog">
                <!-- 博客标题 -->
                <div class="title">
                    我的第一篇博客
                </div>
                <!-- 博客发布时间 -->
                <div class="date">
                    2022-10-21 21:24:00
                </div>
                <div class="desc">
                    刷爆LeetCode!Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore, hic ipsa veritatis adipisci rem, provident accusantium deserunt soluta magnam distinctio consequatur fugit, neque omnis explicabo deleniti reiciendis magni architecto eaque!
                </div>
                <a href="#">查看全文&gt;&gt;</a>
            </div>
        </div>
    </div>
</body>
</html>


列表页引入的css样式:


1.所有页面共同的css样式:common.css


* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
/* 给整个页面加上背景图 */
html,body {
    height: 100%;
}
body {
    background-image: url(../image/555.png);
    background-repeat: no-repeat;
    background-position: center center;
    background-size: cover;
}
.nav {
    width: 100%;
    height: 50px;
    background-color: rgba(51,51,51,0.5);
    color: white;
    /* 导航栏内部的内容,都是一行排列的 */
    display: flex;
    /* 实现子元素垂直居中 */
    align-items: center;
}
.nav img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    margin-left: 30px;
    margin-right: 10px;
}
.nav .spacer{
    width: 80%;
}
.nav a {
    color:white;
    text-decoration: none;
    padding: 0 10px;
}
/* 版心样式 */
.container {
    /* 版心略小于窗口 */
    width: 1000px;
    /* 闪出导航栏的高度 */
    height: calc(100% - 50px);
    /* 水平居中 */
    margin: 0 auto;
    display: flex;
    justify-content: space-around;
}
.container .left {
    height: 100%;
    width: 200px;
}
.container .right {
    height: 100%;
    width: 795px;
    background-color: rgba(255,255,255,0.8);
    border-radius: 10px;
    overflow:auto;
}
.card {
    background-color: rgba(255,255,255,0.8);
    border-radius: 10px;
    padding: 30px;
}
.card img{
    width: 140px;
    height: 140px;
    border-radius: 50%;
}
.card h3 {
    text-align: center;
    padding: 10px;
}
.card a {
    /* 默认a是行内元素,很多功能对行内元素不生效,需要将其设为块级元素 */
    display: block;
    text-align: center;
    text-decoration: none;
    color: #999;
    padding: 10px;
}
.card .counter {
    display: flex;
    justify-content: space-around;
    padding: 5px;
}


2.博客列表页单独的css样式:blog_list.css


/* 这个文件专门写和博客列表页相关的样式 */
.blog {
    width: 100%;
    padding: 20px;
}
.blog .title {
    text-align: center;
    font-size: 23px;
    font-weight: bold;
    padding: 10px 0;
}
.blog .date {
    text-align: center;
    color: rgb(15,100,60);
    padding: 10px 0;
}
.blog .desc {
    text-indent: 2em;
}
.blog a {
    /* 设置成块级元素,方便设置尺寸和边框 */
    display: block;
    width: 140px;
    height: 40px;
    margin: 10px auto;
    border: 2px black solid;
    color: black;
    line-height: 38px;
    text-align: center;
    text-decoration: none;
    transition: all 0.5s;
}
.blog a:hover {
    background-color: #333;
    color: #fff;
}


2.2 博客详情页

微信图片_20230111181101.png

详情页HTML代码块:blog_detail.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客详情页</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_detail.css">
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="#">注销</a>
    </div>
    <div class="container">
        <!-- 左侧个人信息 -->
        <div class="left">
            <!-- 表示整个用户信息区域 -->
            <div class="card">
                <img src="image/2.jpg" alt="">
                <h3>如风暖阳</h3>
                <a href="#">gitHub地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧个人信息 -->
        <div class="right">
            <!-- 使用该div来包裹整个博客的内容详情 -->
            <div class="blog-content">
                <!-- 博客标题 -->
                <h3>我的第一篇博客</h3>
                <!-- 博客的时间 -->
                <div class="date">2022-10-22 18:17</div>
                <!-- 正文 -->
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
                <p>
                    刷爆LeetCode!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores sunt ut odio earum sit dolorem ex delectus expedita ratione et quaerat, repudiandae tenetur possimus nihil officia distinctio quis rem voluptate!
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat fugiat totam perferendis veniam porro harum dolorem ullam reiciendis atque, amet quia minus odio neque odit iusto, temporibus veritatis. Magnam, accusantium!
                </p>
            </div>
        </div>
    </div>
</body>
</html>


详情页引入的CSS样式:blog_detail.css


/* 博客详情页样式文件 */
.blog-content {
    padding: 30px;
}
.blog-content h3 {
    text-align: center;
    padding: 20px 0;
}
.blog-content .date {
    text-align: center;
    color: rgb(0,128,0);
    padding: 10px 0;
}
.blog-content p {
    text-indent: 2em;
    padding: 10px 0;
}


2.3 博客登录页

微信图片_20230111181056.png

登录页HTML代码:blog_login.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_login.css">
</head>
<body>
    <div class="nav">
        <img src="image/dd.jpg" alt="">
        <span>我的博客系统</span>
        <!-- 空白元素,用来占位置 -->
        <div class="spacer"></div>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <!-- <a href="#">注销</a> -->
    </div>
    <div class="login-container">
        <div class="login-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>提交</button>
            </div>
        </div>
    </div>
</body>
</html>


引入的css样式:blog_login.css


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


2.4 博客编辑页

微信图片_20230111181051.png

实现博客编辑页,我们可以看到页面上需要有一个博客编辑器——markdown编辑器,我们可以通过引入第三方库来实现这样的效果。


插入编辑器流程如下:

1)搜索edito.md,下载压缩包,并解压到代码目录。


微信图片_20230111181034.png

微信图片_20230111181024.png

2)引入edtior编辑器必要的依赖jQuery

搜素jquery,复制其地址,引入script标签

微信图片_20230111181020.png

3)引入html文件中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>


4)初始化编译器


<script>
        // 初始化编辑器
        let editor = editormd("editor", {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. 
            width: "100%",
            // 设定编辑器高度
            height: "calc(100% - 50px)",
            // 编辑器中的初始内容
            markdown: "# 在这里写下一篇博客",
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/"
        });
    </script>


博客编辑页HTML文件:blog_edit.html


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


编辑页引入的css样式:blog_edit.css


.blog-edit-container {
    width: 1000px;
    height: calc(100% - 50px);
    margin: 0 auto;
}
.blog-edit-container .title {
    width: 100%;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: space-around;
}
.blog-edit-container .title input {
    width: 895px;
    height: 40px;
    border-radius: 10px;
    border: none;
    outline: none;
    font-size: 22px;
    line-height: 40px;
    padding-left: 40px;
    background-color: rgba(255,255,255,0.8);
}
.blog-edit-container .title button {
    width: 100px;
    height: 40px;
    border-radius: 10px;
    color: white;
    background-color: orange;
    border: none;
    outline: none;
}
.blog-edit-container .title button:active {
    background-color: #666;
}
#editor {
    border-radius: 10px;
    opacity: 80%;
}


2.5 前端页面引入项目

将刚刚完成的所有关于前端页面设计的文件,拷贝到webapp目录下。


微信图片_20230111181015.png

3.编写数据库操作代码


3.1 数据库设计


该步骤需要根据需求,完成数据库/数据表的创建。


根据需求中的实体,需要创建两个表——博客表(用于博客的管理)、用户表(用于用户登录的验证,以及用户的管理操作)


微信图片_20230111181012.png

SQL代码:


-- 编写建库建表的SQL
create database if not exists blog_system;
use blog_system;
-- 创建一个博客表
drop table if exists blog;
create table blog(
    blogID int primary key auto_increment,
    title varchar(1024),
    content mediumtext,
    userId int,
    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());
-- 创建一个用户表
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');


3.2 封装数据库操作


3.2.1 创建DBUtil类


创建DBUtil类,完成数据库连接操作的封装


package model;
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;
public class DBUtil {
    private static final String url="jdbc:mysql://localhost:3306/blog_system?characterEncoding=utf8&useSSL=false";
    private static final String user="root";
    private static final String password="1234";
    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(user);
                    ((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 e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}


3.2.2 创建实体类


用实体类来表示数据库中的一条记录,此处主要创建User类和Blog类

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


Blog类:


package model;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
//每个 model.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;
    }
    //返回格式化好的时间
    public String getPostTime() {
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }
    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}


3.2.3 封装针对数据的增删改查


创建DAO类,分别对对应的表能够进行增删该查操作。


BlogDao:


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) {
        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 e) {
            e.printStackTrace();
        } finally {
            //4)关闭连接,释放资源
            DBUtil.close(connection,statement,null);
        }
    }
    //2.能够获取到博客列表中的所有博客的信息
    // (用在博客列表页,获取到的是博客正文的摘要)
    public List<Blog> selectAll() {
        List<Blog> blogs=new ArrayList<>();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from blog order by postTime desc";
            statement= connection.prepareStatement(sql);
            resultSet=statement.executeQuery();
            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.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blogs.add(blog);
            }
        } catch (SQLException e) {
            e.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 {
            connection=DBUtil.getConnection();
            String sql="select * from blog where blogId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            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.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                return blog;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //4.从博客表中,根据博客id删除博客
    public void delete(int blogId) {
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="delete from blog where blogId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,null);
        }
    }
}


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 {
            connection=DBUtil.getConnection();
            String sql="select * from user where username=?";
            statement=connection.prepareStatement(sql);
            statement.setString(1,username);
            resultSet=statement.executeQuery();
            //此处username使用unique约束,要么能查到一个,要么一个都查不到
            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();
        } finally {
            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 {
            connection=statement.getConnection();
            String sql="select * from user where userId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            resultSet=statement.executeQuery();
            // 此处 username 使用 unique 约束, 要么能查到一个, 要么一个都查不到.
            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();
        } finally {
            DBUtil.close(connection, statement, resultSet);
        }
        return null;
    }
}
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
Java Android开发
如何在idea中使用jstl标签库
如何在idea中使用jstl标签库
|
数据可视化
52【软件设计】软件设计方法归纳总结
软件设计方法有:**结构化设计**(数据流图为依据)、**面向对象设计**(面向对象概念为依据);
1305 0
|
Cloud Native 中间件 调度
云原生信息提取系统:容器化流程与CI/CD集成实践
本文介绍如何通过工程化手段解决数据提取任务中的稳定性与部署难题。结合 Scrapy、Docker、代理中间件与 CI/CD 工具,构建可自动运行、持续迭代的云原生信息提取系统,实现结构化数据采集与标准化交付。
1712 1
云原生信息提取系统:容器化流程与CI/CD集成实践
|
编解码 Java 计算机视觉
探索 JavaCV:开启计算机视觉与多媒体处理新世界
JavaCV 是基于 OpenCV 和 FFmpeg 的 Java 接口库,助力开发者实现视频处理、图像分析等功能。支持多种音视频格式编解码、GPU 加速及跨平台运行,适用于直播录制、摄像头捕获、美颜相机等场景,是多媒体开发的利器。
1348 1
|
存储 人工智能 TensorFlow
你的旧电脑还跑得动AI吗?ToDesk云电脑/青椒云/顺网云算力支持实测报告
随着AI大模型的崛起及广泛应用,旧电脑显示出了硬伤,硬件配置方面,老旧的 CPU、GPU 性能不足,运算速度缓慢,导致 AI 模型训练和推理耗时极长。内存与存储有限,无法承载大型 AI 数据集和复杂模型。散热不佳,运行 AI 任务时易过热死机。且旧电脑可能不兼容新的 AI 框架与工具,软件更新困难。这使得用户在利用旧电脑探索 AI 时,体验大打折扣,而 ToDesk云电脑、青椒云、顺网云等或许能为解决这些问题带来新契机。今天就来实测一下常用的ToDesk云电脑/青椒云/顺网云,博主将从功能、优缺点等方面为你深度剖析这几款云电脑,帮你选出最适合的那一款!🏆
1835 5
|
人工智能 自然语言处理 IDE
CodeFuse IDE 0.7 版本发布,支持 Lint Error 智能改写
CodeFuse IDE 0.7 版本发布,支持 Lint Error 智能改写和 zsh 终端自然语言生成命令。它基于蚂蚁自研大模型和 OpenSumi 框架开发,提供代码编写建议、解释、单测生成等功能,提升开发效率。内置插件升级至 VS Code 1.88.1,未来将支持更多模型服务。下载地址:[GitHub](https://github.com/codefuse-ai/codefuse-ide/releases)。
1655 4
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
1096 3
|
存储 安全 网络安全
POP3 协议在计算机网络中的优缺点
【8月更文挑战第19天】
1098 0
POP3 协议在计算机网络中的优缺点
|
数据采集 自然语言处理 数据可视化
拿来及用的Python词云图代码 | wordcloud生成词云详解
词云也叫文字云,是一种可视化的结果呈现,常用在爬虫数据分析中,原理就是统计文本中高频出现的词,过滤掉某些干扰词,将结果生成一张图片,直观的获取数据的重点信息。今天,我们就来学习一下Python生成词云的常用库wordcloud。
|
监控 IDE Java
Tomcat 启动闪退问题解决方法
Tomcat 启动闪退问题解决方法