基于NodeJs+Express+MySQL 实现的个人博客完整项目
创始人
2024-04-09 18:16:05

目录

一、创建项目并初始化

项目结构

二、安装项目所需要的包

三、创建所需要的数据库表

表 user 用于存放账户密码

表 notepad 用于存放文章数据

表 leaving 用于存放留言板的数据

三、编写app.js文件

1、导入所有需要的包

2、创建web服务器

3、创建db文件夹,在文件夹里面创建mysql.js 注册连接数据库的路由

4、配置中间件、跨域 和sssion认证

6、开始接口的配置

四、创建个人博客的页面

五、展示个人博客页面

实现的功能: 多用户登录,注册,session认证,通过数据库展示文章列表、文章详情,动态生成文章页面,文章分页查询,留言板功能

一、创建项目并初始化

项目结构

​​​​​​​​​​​​​​​​​​​​​

二、安装项目所需要的包

npm install msyql

npm install express

npm install ejs

三、创建所需要的数据库表

表 user 用于存放账户密码

CREATE TABLE user  (username varchar(100),password varchar(100)
) 

表 notepad 用于存放文章数据

CREATE TABLE notepad  (id int(11) NOT NULL AUTO_INCREMENT,username varchar(100),title varchar(100),content varchar(9999),time varchar(99),PRIMARY KEY (`id`)
) 

表 leaving 用于存放留言板的数据

CREATE TABLE leaving  (username varchar(100),content varchar(9999),time varchar(100)
) 

三、编写app.js文件

1、导入所有需要的包

// 导入express
const express = require('express')
var bodyParser = require('body-parser');
// 导入数据库操作模块
const db = require('./db/mysql')
// 导入 session 中间件
var session = require('express-session')
const ejs=require("ejs");
const fs=require("fs");

2、创建web服务器

// 创建web服务器
const app = express()// 调用app.listen(端口号, 启动成功后的回调函数)  启动服务器
app.listen(80, () => {console.log('127.0.0.1');
})

3、创建db文件夹,在文件夹里面创建mysql.js 注册连接数据库的路由

mysql.js

// 1. 导入 mysql 模块
const mysql = require('mysql')
// 2. 建立与 MySQL 数据库的连接关系
const db = mysql.createPool({host: 'localhost', // 数据库的 IP 地址user: 'root', // 登录数据库的账号password: 'root', // 登录数据库的密码database: 'movies', // 指定要操作哪个数据库
})module.exports = db

4、配置中间件、跨域 和sssion认证

// 设置默认首页
// app.use(myexpress.static(__dirname+"/public",{index:"首页地址"}));
app.use(function(req, res) {res.send('404 NOT Found')})
app.use(express.static(__dirname+"/pages",{index:"login.html"}));
// 跨域
app.use(cors())
app.use(session({secret: 'keyboard cat',  // secret 属性的值可以为任意字符串resave: false,           // 固定写法saveUninitialized: true  // 固定写法
}))
// 中间件定义post传递的格式
app.use(express.static('./pages'))
// 静态资源托管
app.use('/public', express.static('./public'))app.use(express.json())
app.use(bodyParser.urlencoded({extended:true}));//Context-Type 为application/x-www-form-urlencoded 时 返回的对象是一个键值对,当extended为false的时候,键值对中的值就为'String'或'Array'形式,为true的时候,则可为任何数据类型。
app.use(bodyParser.json());//用于解析json 会自动选择最为适宜的解析方式于解析json 会自动选择最为适宜的解析方式

6、开始接口的配置

登录接口

app.post('/api/getUsername', function(req, res) {const sqlStr = 'SELECT username,password FROM user;'db.query(sqlStr, (err, results) => {// 查询数据失败if (err) return console.log(err.message)console.log(results);// 查询数据成功// 注意:如果执行的是 select 查询语句,则执行的结果是数组let userData = results.map(item => item.username)let pwdData = results.map(item => item.password)if (userData.indexOf(req.body.username) == -1) {res.send({status: 400,message: '该用户不存在',})} else {// 用户存在,判断密码if (req.body.password == pwdData[userData.indexOf(req.body.username)]) {// 将用户的信息,存储到Session中req.session.user = req.body// 将用户的登陆状态,存储到Session中req.session.islogin = trueres.send({status: 200,message: '登录成功',})} else {res.send({status: 401,message: '登录失败,密码不正确',})}}}) 
})

注册接口

app.post('/api/register', function(req, res) {// 判断数据库里是否已经存在该用户名,如果没有则注册,如果有则提示重新注册const sqlStr = 'SELECT username FROM user;'db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {let userData = results.map(item => item.username)// 判断注册的账号是否与数据库里的账号相同 -1 代表数据库里不存在此数据if (userData.indexOf(req.body.username) == -1) {const sqlStr = `INSERT into user (username, password) VALUES ( '${req.body.username}', '${req.body.password}' );`db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {res.send({status: 200,message: '注册成功'})}})} else {res.send({status: 400,message: '账号已存在,请重新注册'})}}})
})

获取用户姓名的接口

app.get('/api/username', (req, res) => {// 判断用户是否登录if ( !req.session.islogin) {return res.send({status: 404,msg: 'fail'})}res.send({status: 200,msg: 'success',username: req.session.user.username})
})

退出登录的接口

app.post('/api/logout', (req, res) => {req.session.destroy()res.send({status: 200,msg: '退出登陆成功',})
})

获取文章列表

app.get('/api/getArticle', (req, res) => {const sqlStr = 'SELECT * FROM Notepad;'db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {res.send({status: 200,message: '获取文章成功',data: results,username: req.session.user.username})}})
})

新增文章接口

app.post('/api/addArticle', (req, res) => {let time = new Date()const sqlStr = `INSERT into Notepad VALUES (null, '${req.session.user.username}', '${req.body.title}', '${req.body.content}', '${time.toLocaleString()}');`db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {res.send({status: 201,message: '添加文章成功',data: {}})}
})
})

查找文章接口

app.post('/api/search', (req, res) => {let time = new Date()const sqlStr = `SELECT * FROM notepad where id=${req.body.id};`db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {res.send({status: 200,message: "查找成功",data: results })}})
})

动态获取接口用于渲染文章

app.get('/:_id', (req, res) => {var num = req.params._idnum = num.replace('_id', '')num = parseInt(num)// 根据id查找相应的数据 const sqlStr = `SELECT * FROM Notepad where id=${num};`db.query(sqlStr, (err, results) => {// 查询数据失败if (err) {return console.log(err.message)} else {res.render("index.ejs",{username: results[0].username,title:results[0].title,content: results[0].content,time: results[0].time,})}})
})

获取留言接口 

// 获取评论
app.get('/api/getlist',(req,res)=>{const sqlStr = 'select * from leaving'db.query(sqlStr, (err, results) => {// 失败if (err) {return console.log(err.message)} res.send({code: 200,msg: '获取评论列表成功',data: results,username: req.session.user.username})
})
}) 

新增留言接口

// 增加评论
app.post('/api/addlist', (req, res) => { let time = new Date()// 获取到客户端通过查询字符串,发送到服务器的数据// const sqlStr3 = `INSERT INTO leaving VALUES ('${body.text}');`const sqlStr = `INSERT INTO leaving VALUES ('${req.session.user.username}','${req.body.content}','${time.toLocaleString()}');`db.query(sqlStr, (err, results) => {// 失败if (err) {return console.log(err.message)} res.send({status: 200,msg: '添加数据成功',data: results,username: req.session.user.username})})
})

分页查询接口 

app.post('/api/limit', (req, res) => {const sqlStr = `SELECT * FROM notepad LIMIT 10 OFFSET ${req.body.num};`db.query(sqlStr, (err, results) => {// 失败if (err) {return console.log(err.message)} res.send({status: 200,msg: '分页查询成功',data: results,})})
})

四、创建个人博客的页面

登录页面   login.html



用户登录

HELLO HANG
登录
去注册
有问题?请联系站长

注册页面



用户注册

REGISTER
注册
有问题?请联系站长

博客主页 index.html  可进行分页查询


Document


添加文章的页面 



Document

提交成功...
写文章
文章标题

文章内容

发布文章
有问题?请联系站长

 渲染文章的页面,使用的ejs     index.ejs



Title

<%- title %>
用户: <%- username %>
<%- time %>
|
<%- content %>
有问题?请联系站长

留言板,用于展示留言,添加留言



Document

留言板
发布留言
有问题?请联系站长

五、展示个人博客页面

登陆页面

注册页面 

博客主页 

  添加文章页面

文章详细页面

留言板 

至此,我的个人博客大致完成,后续将会继续改进

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...