前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4. 项目1 —— 实现一个简易博客系统

4. 项目1 —— 实现一个简易博客系统

作者头像
小雨的分享社区
发布2022-10-26 15:55:26
2550
发布2022-10-26 15:55:26
举报
文章被收录于专栏:小雨的CSDN小雨的CSDN

1. 需求分析

本项目需要实现一个简易的博客系统,其中功能包括: 1)注册新用户 2)登陆已有用户 3)显示博客列表,包括文章的作者和文章的内容 4)点击文章就会跳转到文章详情 5)发布新博客 6)删除自己的博客

2. 数据库设计

设计当前代码中需要用到数据库的几张表,每张表上都有哪些字段,每个表之间有什么关联关系

1)提取出需求中的“实体”有哪些 【用户】【文章】 确定了有两张表:User表 和 Article表

2)确定实体需要的属性 用户:【名字,密码】 文章:【标题,内容】

3)确定实体和实体之间的关系 用户和文章应该是【一对多】的关系,在“多”的表中加上外键 (需要在user表中加入userId字段,表示身份标识 在Article表中加入一个userId字段,表示该文章是由哪个用户发的)

代码语言:javascript
复制
drop database if exists blogdemo;
create database blogdemo;

use blogdemo;

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

drop table if exists article;
create table article(
    articleId int primary key auto_increment,
    title varchar(255),
    content text,
    userId int ,
    foreign key(userId) references user(userId)
);

创建完成的数据库如下:

在这里插入图片描述
在这里插入图片描述

3. 开始写代码

a)创建一个类来管理数据库的连接(JDBC)

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
package model;

//管理数据库连接
//1.建立连接
//2.断开连接
//JDBC使用DataSourcr来管理连接
//DBUtil相当于是对DataSource再稍微包装一层
//因为 DataSource 应该是每个应用程序只应该有一个实例
//DBUtil本质上就是实现了一个单例模式,管理了一个唯一的DataSource实例

//单例模式的实现,有两种风格
//1.饿汉模式
//2.懒汉模式(在这里实现的)_______主要问题:线程不安全

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 volatile DataSource dataSource = null;
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/blogdome?characterEncoding=utf-8&useSSL=true";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "09050797";

    public static DataSource getDataSource(){
        if (dataSource == null) {
            synchronized (DBUtil.class) {
                if (dataSource == null){
                    dataSource = new MysqlDataSource();
                    //需要给DataSource设置一些属性
                    ((MysqlDataSource)dataSource).setURL(URL);
                    ((MysqlDataSource)dataSource).setUser(USERNAME);
                    ((MysqlDataSource)dataSource).setPassword(PASSWORD);
                }
            }
        }
        return dataSource;
    }

    //通过这个方法来获取连接
    public static Connection getConnection(){
        try {
            return getDataSource().getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //通过这个方法断开连接
    public static void close(Connection connection, PreparedStatement statement,
                             ResultSet resultSet){
        try {
            if (resultSet != null){
                resultSet.close();
            }
            if (statement != null){
                statement.close();
            }
            if (connection != null){
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

b)创建实体类 创建一个user类和article类,这俩类的属性要和数据库结构是相关联的

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
package model;

public class User {
    private int userId;
    private String name;
    private String password;

    public int getUserId() {
        return userId;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

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

}
代码语言:javascript
复制
package model;

public class Article {
    private int articleId;
    private String title;
    private String content;
    private int userId;

    public int getArticleId() {
        return articleId;
    }

    public void setArticleId(int articleId) {
        this.articleId = articleId;
    }

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

c)实现数据库的增删改查

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
package model;

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

//Dao表示数据访问层
public class UserDao {
    //1.新增用户(注册)
    //  把一个User对象插入到数据库中
    void add(User user){
        //1.获取带数据库连接
        Connection connection = DBUtil.getConnection();
        //2.拼装sql语句
        String sql = "insert into user values (null,?,?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,user.getName());
            statement.setString(2,user.getPassword());
            //3.执行sql语句
            int ret = statement.executeUpdate();
            if(ret != 1){
                //插入失败
                System.out.println("插入新用户失败!");
                return;
            }
            System.out.println("插入新用户成功!");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //4.释放数据库连接
            DBUtil.close(connection,statement,null);
        }
    }

    //2.按照名字查找(登录)
    public User selectByName(String name){
        //1.和数据库建立连接
        Connection connection = DBUtil.getConnection();
        //2.拼装SQL
        String sql = "select * from user where name = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,name);
            //3.执行SQL
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            if (resultSet.next()){
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setName(resultSet.getString("name"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.释放数据库连接
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
}
代码语言:javascript
复制
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 ArticleDao {
    //1.新增文章(发布博客)
    public void add(Article article){
        //1.获取数据库连接
        Connection connection = DBUtil.getConnection();
        //2.构造sql
        String sql = "insert into article value (null,?,?,?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,article.getTitle());
            statement.setString(2,article.getContent());
            statement.setInt(3,article.getUserId());
            //3.执行sql
            int ret = statement.executeUpdate();
            if (ret != 1){
                System.out.println("插入文章操作失败!");
                return;
            }
            System.out.println("插入文章操作成功!");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //4.释放连接
            DBUtil.close(connection,statement,null);
        }
    }


    //2.查看文章(把所有的文章信息都查出来)
    public List<Article> selectAll(){
        List<Article> articles = new ArrayList<>();
        Connection connection = DBUtil.getConnection();
        String sql = "select article,title,userId from article";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                Article article = new Article();
                article.setArticleId(resultSet.getInt("articleId"));
                article.setTitle(resultSet.getString("title"));
                article.setUserId(resultSet.getInt("userId"));
                articles.add(article);
            }
            return articles;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    //3.查看指定的文章详情
    public Article selectById(int articleId){
        Connection connection = DBUtil.getConnection();
        String sql = "select * from where articleId = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,articleId);
            resultSet = statement.executeQuery();
            if (resultSet.next()){
                Article article = new Article();
                article.setArticleId(resultSet.getInt("articleId"));
                article.setTitle(resultSet.getString("title"));
                article.setContent(resultSet.getString("content"));
                article.setUserId(resultSet.getInt("userId"));
                return article;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    //4.删除指定文章
    public void delete(int articleId){
        Connection connection = DBUtil.getConnection();
        String sql = "delete from article where articleId = ?";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,articleId);
            int ret = statement.executeUpdate();
            if (ret != 1){
                System.out.println("删除文章失败!");
                return;
            }
            System.out.println("删除文章成功!");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
}

4. 前后端接口设计

在这里插入图片描述
在这里插入图片描述

5. 开始实现接口

1) 实现注册页面

在这里插入图片描述
在这里插入图片描述

register.html

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>注册</title>
</head>
<body>
<form action="register" method="post">
    <input type="text" name="name" placeholder="请输入密码">
    <br/>
    <input type="text" name="password" placeholder="请输入密码">
    <br/>
    <input type="submit" value="注册">

</form>

</body>
</html>

RegisterServlet

代码语言:javascript
复制
package api;

import model.User;
import model.UserDao;
import view.HtmlGenerator;

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

public class RegisterServlet extends HttpServlet {
    //浏览器是通过POST方法来提交数据的
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        //1.获取到前端提交的数据(用户名,密码)校验是否合法
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        if(name == null || "".equals(name)||password==null||"".equals(password)){
            String html = HtmlGenerator.getMessagePage("用户名或者密码为空","register.html");
            resp.getWriter().write(html);
            return;
        }
        //2.拿着用户名在数据库中查一下,看看当前用户是否已经存在,如果存在,认为注册失败
        UserDao userDao = new UserDao();
        User existUser = userDao.selectByName(name);
        if (existUser != null){
            //说明已经存在,提示用户注册失败,用户名重复
            String html = HtmlGenerator.getMessagePage("用户名重复!请换个名字!","register.html");
            resp.getWriter().write(html);
            return;
        }
        //3.根据前端提交的数据构造user对象,并插入到数据库中
        User user = new User();
        user.setName(name);
        user.setPassword(password);
        userDao.add(user);
        //4.返回一个结果页面,提示当前注册成功
        String html = HtmlGenerator.getMessagePage("注册成功!点击这里跳转到登陆页面!","login.html");
        resp.getWriter().write(html);
        
    }
}

HtmlGenerator

代码语言:javascript
复制
package view;

public class HtmlGenerator {
    //通过字符串拼接的形式,构造出来HTML格式出来
    public static String getMessagePage(String message, String nextUrl) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<html>");
        stringBuilder.append("<head>");
        stringBuilder.append("<meta charset=\"utf-8\">");
        stringBuilder.append("<title>提示页面</title>");
        stringBuilder.append("</head>");
        stringBuilder.append("<body>");

        stringBuilder.append("<h3>");
        stringBuilder.append(message);
        stringBuilder.append("</h3>");

        stringBuilder.append(String.format("<a href=\"%s\"> 点击这里跳转 </a>",nextUrl));

        stringBuilder.append("</body>");
        stringBuilder.append("</html>");

        return stringBuilder.toString();

    }
}

配置web.xml文件

在这里插入图片描述
在这里插入图片描述

2) 实现登录功能

在这里插入图片描述
在这里插入图片描述

login.html

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>登录</title>
</head>
<body>
<form action="login" method="post">
    <input type="text" name="name" placeholder="请输入用户名">
    <br/>
    <input type="password" name="password" placeholder="请输入密码">
    <br/>
    <input type="submit" value="登录">

</form>

</body>
</html>

loginServlet

代码语言:javascript
复制
package api;

import model.User;
import model.UserDao;
import view.HtmlGenerator;

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

public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        //1.获取到用户名和密码,并进行简单的校验
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        if (name == null || "".equals(name) || password==null || "".equals(password)){
            String html = HtmlGenerator.getMessagePage("用户名或密码为空","login.html");
            resp.getWriter().write(html);
            return;
        }
        //2.数据库中查找,看看用户是否存在
        //3.对比密码是否匹配
        UserDao userDao = new UserDao();
        User user = userDao.selectByName(name);
        if (user==null || !password.equals(user.getPassword())){
            //用户名不存在
            String html = HtmlGenerator.getMessagePage("用户名或密码错误","login.html");
            resp.getWriter().write(html);
            return;
        }

        //4.匹配成功则认为登陆成功,创建一个session
        HttpSession httpSession = req.getSession(true);
        httpSession.setAttribute("user",user);

        //5.返回一个登陆成功的页面
        String html = HtmlGenerator.getMessagePage("登陆成功","article");
        resp.getWriter().write(html);
    }
}

3) 实现文章功能

在这里插入图片描述
在这里插入图片描述

ArticleServlet

代码语言:javascript
复制
package api;

import model.Article;
import model.ArticleDao;
import model.User;
import model.UserDao;
import view.HtmlGenerator;

import javax.servlet.ServletException;
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;

public class ArticleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        //1.验证用户是否已经登陆了,如果尚未登陆提示用户登录
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null){
            //当前是未登录状态
            String html = HtmlGenerator.getMessagePage("请先登录","login.html");
            resp.getWriter().write(html);
            return;
        }
        User user = (User)httpSession.getAttribute("user");
        //2.判断请求中是否存在articleId参数
        String articleIdStr = req.getParameter("articleId");
        if (articleIdStr == null){
            //a)没有这个参数就去执行获取文章列表的操作
            getAllArticle(user, resp);
        }else {
            //b)有这个参数就去执行获取文章详情的操作
            getOneArticle(Integer.parseInt(articleIdStr),user,resp);
        }

    }

    private void getOneArticle(int articleId, User user, HttpServletResponse resp) throws IOException {
        //1.查找数据库
        ArticleDao articleDao = new ArticleDao();
        Article article = articleDao.selectById(articleId);
        if (article == null){
            //文章未找到
            String html = HtmlGenerator.getMessagePage("文章不存在","article");
            resp.getWriter().write(html);
            return;
        }
        //根据作者ID。找到作者信息,进一步得到作者姓名
        UserDao userDao = new UserDao();
        User author = userDao.selectById(article.getUserId());
        //2.构造页面
        String html = HtmlGenerator.getArticleDetailPage(article,user,author);
        resp.getWriter().write(html);
    }


    private void getAllArticle(User user, HttpServletResponse resp) throws IOException {
        //1.查找数据库
        ArticleDao articleDao = new ArticleDao();
        List<Article> articles = articleDao.selectAll();
        //2.构造页面
        String html = HtmlGenerator.getArticleListPage(articles, user);
        resp.getWriter().write(html);
    }
}

HtmlGenerator

代码语言:javascript
复制
package view;

import model.Article;
import model.User;

import java.util.List;

public class HtmlGenerator {
    //通过字符串拼接的形式,构造出来HTML格式出来
    public static String getMessagePage(String message, String nextUrl) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<html>");
        stringBuilder.append("<head>");
        stringBuilder.append("<meta charset=\"utf-8\">");
        stringBuilder.append("<title>提示页面</title>");
        stringBuilder.append("</head>");
        stringBuilder.append("<body>");

        stringBuilder.append("<h3>");
        stringBuilder.append(message);
        stringBuilder.append("</h3>");

        stringBuilder.append(String.format("<a href=\"%s\"> 点击这里跳转 </a>",nextUrl));

        stringBuilder.append("</body>");
        stringBuilder.append("</html>");

        return stringBuilder.toString();

    }

    public static String getArticleListPage(List<Article> articles, User user) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<html>");
        stringBuilder.append("<head>");
        stringBuilder.append("<meta charset=\"utf-8\">");
        stringBuilder.append("<title>提示页面</title>");
        stringBuilder.append("<style>");
        stringBuilder.append("a{"+
                "color: #333;"+
                "text-decoration: none;"+
                "}");
        stringBuilder.append("a{"+
                "color: white"+
                "background-color: orange;"+
                "}");
        stringBuilder.append("</style>");
        stringBuilder.append("</head>");
        stringBuilder.append("<body>");

        stringBuilder.append("<h3> 欢迎您!"+ user.getName()+"</h3>");
        stringBuilder.append("<hr>");
        //要有一个文章列表,显示每个文章的标题
        for (Article article : articles){
           stringBuilder.append(String.format("<div style=\"width: 200px;height: 50px\"><a href=\"article?articleId=%d\"> %s </div>",
           article.getArticleId(),article.getTitle()));
        }
        stringBuilder.append("<hr>");
        stringBuilder.append(String.format("<div>当前共有博客 %d 篇 </div>",articles.size()));

        stringBuilder.append("</body>");
        stringBuilder.append("</html>");

        return stringBuilder.toString();
    }


    public static String getArticleDetailPage(Article article, User user, User author) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<html>");
        stringBuilder.append("<head>");
        stringBuilder.append("<meta charset=\"utf-8\">");
        stringBuilder.append("<title>提示页面</title>");
        stringBuilder.append("<style>");
        stringBuilder.append("a{"+
                "color: #333;"+
                "text-decoration: none;"+
                "}");
        stringBuilder.append("a{"+
                "color: white"+
                "background-color: orange;"+
                "}");
        stringBuilder.append("</style>");
        stringBuilder.append("</head>");
        stringBuilder.append("<body>");

        stringBuilder.append("<h3> 欢迎您!"+ user.getName()+"</h3>");
        stringBuilder.append("<hr>");

        stringBuilder.append(String.format("<h1>%s</h1>",article.getTitle()));
        stringBuilder.append(String.format("<h4>作者:%s</h4>",author.getName()));
        stringBuilder.append(String.format("<div>%s</div>",article.getContent()));

        stringBuilder.append("</body>");
        stringBuilder.append("</html>");
        return stringBuilder.toString();

    }
}

3) 实现删除文章

代码语言:javascript
复制
package api;


import model.Article;
import model.ArticleDao;
import model.User;
import view.HtmlGenerator;

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

public class DeleteArticleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        // 1. 验证用户的登陆状态, 如果未登陆, 肯定不能删除.
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            String html = HtmlGenerator.getMessagePage("您尚未登陆!",
                    "login.html");
            resp.getWriter().write(html);
            return;
        }
        User user = (User) httpSession.getAttribute("user");
        // 2. 读取请求内容, 获取到要删除的文章 id
        String articleIdStr = req.getParameter("articleId");
        if (articleIdStr == null || "".equals(articleIdStr)) {
            String html = HtmlGenerator.getMessagePage("要删除的文章 id 有误",
                    "article");
            resp.getWriter().write(html);
            return;
        }
        // 3. 根据文章 id 查找到该文章的作者. 当前用户如果就是作者, 才能删除, 否则删除失败.
        ArticleDao articleDao = new ArticleDao();
        Article article = articleDao.selectById(Integer.parseInt(articleIdStr));
        if (article.getUserId() != user.getUserId()) {
            String html = HtmlGenerator.getMessagePage("您只能删除自己的文章!",
                    "article");
            resp.getWriter().write(html);
            return;
        }
        // 4. 真正执行数据库删除操作
        articleDao.delete(Integer.parseInt(articleIdStr));
        // 5. 返回一个 "删除成功" 的页面.
        String html = HtmlGenerator.getMessagePage("删除成功!",
                "article");
        resp.getWriter().write(html);
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 需求分析
  • 2. 数据库设计
  • 3. 开始写代码
  • 4. 前后端接口设计
  • 5. 开始实现接口
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档