博客项目1——基于NodeJs的后端开发

Express简介
Express 是一个基于 Node.js 的极简、灵活的 Web 应用开发框架。它可以帮助你非常方便地搭建 Web 服务器和 API 服务。
主要特点如下:
- 极简易用:用很少的代码就能搭建一个 Web 服务。
- 中间件机制:通过中间件(middleware)可以灵活处理请求和响应,比如处理静态文件、解析请求体、处理跨域等。
- 路由系统:可以很方便地定义不同的 URL 路径和对应的处理函数,支持 GET、POST、PUT、DELETE 等多种 HTTP 方法。
- 生态丰富:有大量第三方中间件和插件,能快速扩展功能(如认证、日志、文件上传等)。
- 适合 RESTful API:非常适合用来开发 RESTful 风格的接口。
一句话总结:
Express 是 Node.js 领域最流行的 Web 框架之一,适合快速开发各种 Web 应用和后端 API 服务。
与jakarta对比
对比项 | Express(Node.js) | Jakarta EE(Java) |
---|---|---|
开发语言 | JavaScript/Node.js | Java |
生态 | 偏前端、全栈,npm包丰富 | 企业级后端主流,JCP标准,生态成熟 |
项目结构 | 灵活、自由,适合小中型项目 | 规范分层(Servlet、EJB、JPA等),适合大型项目 |
启动方式 | 直接 node app.js 启动 |
需部署到Servlet容器(如Tomcat、WildFly) |
路由/控制器 | app.get/post 或 router.get/post |
Servlet类+注解(如@WebServlet、@Path) |
数据库操作 | 直接写SQL或用ORM(如sequelize) | JPA/EJB/JDBC,ORM强大,类型安全 |
中间件/拦截 | app.use 中间件机制 |
Filter/Listener/Interceptor拦截器 |
配置部署 | 配置简单,轻量,适合云函数/轻量服务 | 配置项多,需XML/注解,适合传统服务器/容器化 |
性能场景 | 轻量高并发,I/O密集型,API、实时应用 | 业务复杂、强类型、安全性高的企业级应用 |
适合人群 | 前端转全栈、初学者、快速开发 | 后端开发、企业级团队、规范性要求高 |
总结: Express 更灵活、轻量、上手快,适合快速开发和小型项目;Jakarta EE 更规范、功能强大,适合大型、企业级项目。
创建Blog项目:
- 在某个磁盘分区创建一个Myblog的目录,进入该目录,然后用vscode打开它
- 在vscode的终端中依次运行下面的命令,创建项目目录并安装 Express:
mkdir backend
cd backend
npm install express --save
npm install bcryptjs --save
npm install mysql2 --save
- 在
backend
目录中创建一个app.js
文件,在其中插入下面的代码。
const express = require('express'); // 引入express
const app = express(); // 创建应用
//监听3000端口
app.listen(3000, () => {
console.log('Server started on port 3000');
console.log('http://localhost:3000');
})
//设置路由
app.get('/', (req, res) => {
res.send('Hello World!');
})
- 在终端中运行下面的命令,启动应用:
node app.js
- 访问应用:
打开浏览器,访问http://localhost:3000,可以看到"Hello World!"
创建数据库
我们的目标是做一个博客系统,可以实现登录、注册、发布文章、查看文章、修改文章、删除文章等功能。第一步我们首先要设计数据库,在数据库软件里创建一个数据库,名字为blog,然后创建一个用于保存文章的表,名字为articles,里面有id、uid、title、content、created_at、updated_at等字段,还要创建一个用户表,里面有id、username、password等字段。数据结构如下图所示:
可以直接使用sql语句创建数据库和表,具体做法如下:
打开Navicat软件,点击localhost建立连接,点击新建查询,粘贴下面的代码,最后点击运行
CREATE DATABASE IF NOT EXISTS blog;
USE blog;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
) ENGINE=InnoDB;
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
uid INT NOT NULL,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (uid) REFERENCES users(id)
) ENGINE=InnoDB;
INSERT INTO users (username, password) VALUES ('admin', '123456');
INSERT INTO articles (uid, title, content) VALUES (1, 'Hello World!', 'This is my first article.');
编写连接数据库的代码
在backend文件中创建一个db.js
文件,插入如下所示的代码(注意!密码password
要换成你自己数据库的密码哦!!!)
这段代码的作用是引入mysql2
模块,创建一个数据库连接,并导出这个连接,完整代码如下:
const mysql = require('mysql2'); // 引入mysql2模块
const db = mysql.createConnection({ // 创建数据库连接
host: 'localhost', // 数据库地址
user: 'root', // 数据库用户名
password: '123456789', // 数据库密码
database: 'blog' // 数据库名称
});
db.connect(err => { // 连接数据库
if (err) { // 如果连接失败
console.error('数据库连接失败:', err); // 打印错误信息
} else { // 如果连接成功
console.log('数据库连接成功'); // 打印连接成功信息
}
});
module.exports = db; // 导出数据库连接
编写用户注册和登录的接口
在backend
文件中创建routes
文件夹,然后在routes
文件夹中创建users.js
文件,编写用户登录和注册接口:
const express = require('express');
const router = express.Router();
const db = require('../db');
const bcrypt = require('bcryptjs');
// 注册
router.post('/register', (req, res) => {
const { username, password } = req.body;
// 检查用户名是否已存在
db.query('SELECT * FROM users WHERE username=?', [username], (err, results) => {
if (results.length > 0) {
return res.status(400).json({ message: '用户名已存在' });
}
// 密码加密
const hash = bcrypt.hashSync(password, 10);
db.query('INSERT INTO users (username, password) VALUES (?, ?)', [username, hash], (err) => {
if (err) return res.status(500).json({ message: '注册失败' });
res.json({ message: '注册成功' });
});
});
});
// 登录
router.post('/login', (req, res) => {
const { username, password } = req.body;
db.query('SELECT * FROM users WHERE username=?', [username], (err, results) => {
if (results.length === 0) {
return res.status(400).json({ message: '用户不存在' });
}
const user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return res.status(400).json({ message: '密码错误' });
}
// 登录成功,可以生成 token 或 session
res.json({ message: '登录成功', userId: user.id });
});
});
module.exports = router;
编写文章相关接口
在 routes
文件夹下新建 articles.js
,实现文章的增删改查(CRUD)接口:
- 发布文章(POST /api/article/add)
- 获取文章列表(GET /api/article/list)
- 获取单篇文章详情(GET /api/article/:id)
- 修改文章(POST /api/article/update/:id)
- 删除文章(POST /api/article/delete/:id)
// routes/articles.js
const express = require('express');
const router = express.Router();
const db = require('../db');
// 发布文章
router.post('/add', (req, res) => {
const { uid, title, content } = req.body;
db.query(
'INSERT INTO articles (uid, title, content) VALUES (?, ?, ?)',
[uid, title, content],
(err, result) => {
if (err) return res.status(500).json({ message: '发布失败' });
res.json({ message: '发布成功', articleId: result.insertId });
}
);
});
// 文章列表
router.get('/list', (req, res) => {
db.query('SELECT * FROM articles', (err, results) => {
if (err) return res.status(500).json({ message: '获取失败' });
res.json(results);
});
});
// 文章详情
router.get('/:id', (req, res) => {
db.query('SELECT * FROM articles WHERE id=?', [req.params.id], (err, results) => {
if (err) return res.status(500).json({ message: '获取失败' });
if (results.length === 0) return res.status(404).json({ message: '未找到' });
res.json(results[0]);
});
});
// 修改文章
router.post('/update/:id', (req, res) => {
const { title, content } = req.body;
db.query(
'UPDATE articles SET title=?, content=? WHERE id=?',
[title, content, req.params.id],
(err) => {
if (err) return res.status(500).json({ message: '修改失败' });
res.json({ message: '修改成功' });
}
);
});
// 删除文章
router.post('/delete/:id', (req, res) => {
db.query('DELETE FROM articles WHERE id=?', [req.params.id], (err) => {
if (err) return res.status(500).json({ message: '删除失败' });
res.json({ message: '删除成功' });
});
});
module.exports = router;
修改app.js
把app.js
改成下面这样
const express = require('express'); // 引入express
const app = express(); // 创建应用
const userRouter = require('./routes/users'); // 引入用户路由
const articleRouter = require('./routes/articles'); // 引入文章路由
app.use(express.json()); // 解析json请求体
app.use(express.urlencoded({ extended: true })); // 解析urlencoded请求体
app.use('/api/user', userRouter); // 使用用户路由
app.use('/api/article', articleRouter); // 使用文章路由
//监听3000端口
app.listen(3000, () => {
console.log('Server started on port 3000'); // 打印服务器启动信息
console.log('http://localhost:3000'); // 打印服务器地址
})
//设置根路由,返回Hello World!
app.get('/', (req, res) => {
res.send('Hello World!'); // 发送Hello World!响应
})
在终端中按键盘Ctrl+C停止服务器,然后运行node app.js重启服务器,然后按住Ctrl健用鼠标左键单击那个网址。
测试接口
- 首先打开微软的Edge浏览器,按下图所示的方式安装前端助手扩展
- 测试注册用户
按下图所示的步骤打开建议Postman
如下图所示,首先点一下【Post示例】,然后再点【参数专JSON格式】
接下来再接口地址输入 http://localhost:3000/api/user/register
再请求参数里面输入
{
"username": "youngshu",
"password": "123456"
}
点击【发送请求】按钮,可以看到服务器响应了注册成功信息,说明注册接口正常工作
打开数据库的用户表,可以看到表格中确实添加了我们刚发送过去的用户名,密码进行了加密。
- 测试用户登录
把接口地址换成http://localhost:3000/api/user/login
请求参加就用我们刚才注册的用户名和密码
{
"username": "youngshu",
"password": "123456"
}
然后点击【发送请求】,可看到服务器响应了登录成功的信息,说明登录接口也可以正常工作
- 测试添加文章
把接口地址换成http://localhost:3000/api/article/add
请求参数为:(注意!uid为用户id,你的不一定是3,要去数据库的user表格里面看你的用户名对应的id是多少)
{
"uid": 3,
"title": "我的第一篇文章",
"content": "这是内容"
}
发送请求后,可以看到服务器响应信息,如果是如下图所示,则说明增加文章成功
打开数据库的文章表格,可以看到刚才测试的数据确实增加到了数据库中,说明增加文章的功能OK。
接下来,请利用前端助手,多添加几篇文章
- 测试获取文章列表
首先把请求方式改成GET
然后把接口地址改成(注意,你的id不一定是3哦):http://localhost:3000/api/article/list?id=3
发送请求后,可以看到服务器把数据库中用户id为3的用户的所有文章返回过来了。
- 测试获取单篇文章
把接口地址改成http://localhost:3000/api/article/2
,然后发送请求,可以查询第2篇文章。
最后的数字改成3,可以查询第3篇文章,以此类推
- 测试更新文章
把请求方式改成POST
接口地址改成 http://localhost:3000/api/article/update/2
(2是你要修改的文章id)
请求参数为:
{
"title": "新标题",
"content": "新内容"
}
点击【发送请求】按钮,可以看到服务器响应了"修改成功"的信息,说明更新文章接口正常工作。
你可以去数据库的文章表格里查看,发现对应id的文章内容已经被修改。
- 测试删除文章
把请求方式改成POST
接口地址改成 http://localhost:3000/api/article/delete/2
(2是你要删除的文章id)
无需请求参数,直接点击【发送请求】按钮。
可以看到服务器响应了"删除成功"的信息,说明删除文章接口正常工作。
你可以去数据库的文章表格里查看,发现对应id的文章已经被删除。
作业
请自学一下GET请求和POST请求的区别
然后做一个说明文档说明为什么文章相关的接口有的使用GET请求,有的使用POST请求
- 发布文章(POST /api/article/add)
- 获取文章列表(GET /api/article/list)
- 获取单篇文章详情(GET /api/article/:id)
- 修改文章(POST /api/article/update/:id)
- 删除文章(POST /api/article/delete/:id)
评论 (0)
暂无评论,来发表第一条评论吧!