Node.js 开发详解
一、Node.js 核心知识框架
1.1 基础概念
- 什么是 Node.js:基于 Chrome V8 引擎构建的 JavaScript 运行环境
- 事件驱动架构:非阻塞 I/O 模型
- 单线程与事件循环:高效处理并发请求
- NPM(Node 包管理器):Node.js 的默认包管理工具
1.2 核心模块与 API
- 文件系统 (fs):文件操作
- HTTP/HTTPS:创建 Web 服务器
- 事件系统 (events):事件驱动编程
- 流 (stream):处理流式数据
- 路径 (path):处理文件路径
- 进程 (process):进程信息与控制
- 缓冲区 (buffer):处理二进制数据
- 操作系统 (os):获取操作系统信息
- 集群 (cluster):多进程能力
1.3 架构模式
- CommonJS 模块系统:Node.js 中的模块机制
- 回调函数与 Promise:异步处理方式
- Async/Await:现代化异步语法
- 中间件模式:Express 等框架的核心概念
1.4 Web 开发相关
- RESTful API 设计
- 数据库集成(MongoDB, MySQL, PostgreSQL)
- 身份验证与授权
- 错误处理机制
- 日志记录
Node.js 博客系统架构图
系统整体架构

用户认证流程
文章操作流程
Express 中间件执行顺序
graph LR
A[Incoming Request] --> B[Application Level Middleware<br/>app.use(...)]
B --> C[Route Middleware<br/>router.use(...)]
C --> D[Route Handler<br/>app.get/post/put/delete]
D --> E[Error Handling Middleware<br/>app.use(err, req, res, next)]
E --> F[Response Sent to Client]
数据模型关系图
API 端点映射图
二、实战项目:简易博客系统
2.1 项目结构设计
blog-system/
├── app.js # 应用入口文件
├── package.json # 项目配置文件
├── routes/ # 路由目录
│ ├── posts.js # 文章路由
│ └── users.js # 用户路由
├── controllers/ # 控制器目录
│ ├── postController.js # 文章控制器
│ └── userController.js # 用户控制器
├── models/ # 数据模型目录
│ ├── Post.js # 文章模型
│ └── User.js # 用户模型
├── middleware/ # 中间件目录
│ └── auth.js # 认证中间件
└── utils/ # 工具函数目录
└── database.js # 数据库连接
2.2 完整项目实现
package.json - 项目配置文件
{
"name": "blog-system",
"version": "1.0.0",
"description": "A simple blog system built with Node.js",
"main": "app.js",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.5.0",
"bcryptjs": "^2.4.3",
"jsonwebtoken": "^9.0.2",
"cors": "^2.8.5",
"dotenv": "^16.3.1"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
app.js - 应用入口文件
// 导入所需模块
const express = require('express');
const cors = require('cors');
require('dotenv').config();
// 创建 Express 应用实例
const app = express();
const PORT = process.env.PORT || 3000;
// 中间件配置
app.use(cors()); // 允许跨域请求
app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码的请求体
// 导入路由
const postRoutes = require('./routes/posts');
const userRoutes = require('./routes/users');
// 使用路由
app.use('/api/posts', postRoutes);
app.use('/api/users', userRoutes);
// 根路径欢迎页面
app.get('/', (req, res) => {
res.json({
message: '欢迎使用博客系统 API',
version: '1.0.0',
endpoints: {
posts: '/api/posts',
users: '/api/users'
}
});
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
message: '服务器内部错误',
error: process.env.NODE_ENV === 'development' ? err.message : {}
});
});
// 404 处理
app.use('*', (req, res) => {
res.status(404).json({
message: '页面未找到'
});
});
// 启动服务器
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
});
module.exports = app;
models/User.js - 用户数据模型
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// 定义用户 Schema
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3,
maxlength: 30
},
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true
},
password: {
type: String,
required: true,
minlength: 6
},
createdAt: {
type: Date,
default: Date.now
}
});
// 密码加密中间件(保存前执行)
userSchema.pre('save', async function(next) {
// 如果密码没有被修改,则跳过加密
if (!this.isModified('password')) return next();
try {
// 对密码进行哈希加密
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} catch (error) {
next(error);
}
});
// 验证密码方法
userSchema.methods.comparePassword = async function(candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
// 创建并导出 User 模型
module.exports = mongoose.model('User', userSchema);
models/Post.js - 文章数据模型
const mongoose = require('mongoose');
// 定义文章 Schema
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
trim: true,
maxlength: 200
},
content: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
tags: [{
type: String,
trim: true
}],
published: {
type: Boolean,
default: false
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
}
});
// 更新时间中间件
postSchema.pre('save', function(next) {
this.updatedAt = Date.now();
next();
});
// 创建并导出 Post 模型
module.exports = mongoose.model('Post', postSchema);
controllers/userController.js - 用户控制器
const User = require('../models/User');
const jwt = require('jsonwebtoken');
// 生成 JWT token
const generateToken = (userId) => {
return jwt.sign({ id: userId }, process.env.JWT_SECRET || 'default_secret', {
expiresIn: '7d'
});
};
// 用户注册
exports.register = async (req, res) => {
try {
const { username, email, password } = req.body;
// 检查必填字段
if (!username || !email || !password) {
return res.status(400).json({
message: '用户名、邮箱和密码都是必需的'
});
}
// 检查用户是否已存在
const existingUser = await User.findOne({
$or: [{ email }, { username }]
});
if (existingUser) {
return res.status(400).json({
message: '用户名或邮箱已被使用'
});
}
// 创建新用户
const user = new User({
username,
email,
password
});
await user.save();
// 生成 token
const token = generateToken(user._id);
res.status(201).json({
message: '用户注册成功',
token,
user: {
id: user._id,
username: user.username,
email: user.email
}
});
} catch (error) {
res.status(500).json({
message: '注册失败',
error: error.message
});
}
};
// 用户登录
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
// 检查必填字段
if (!email || !password) {
return res.status(400).json({
message: '邮箱和密码都是必需的'
});
}
// 查找用户
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({
message: '邮箱或密码错误'
});
}
// 验证密码
const isMatch = await user.comparePassword(password);
if (!isMatch) {
return res.status(401).json({
message: '邮箱或密码错误'
});
}
// 生成 token
const token = generateToken(user._id);
res.json({
message: '登录成功',
token,
user: {
id: user._id,
username: user.username,
email: user.email
}
});
} catch (error) {
res.status(500).json({
message: '登录失败',
error: error.message
});
}
};
// 获取当前用户信息
exports.getCurrentUser = async (req, res) => {
try {
const user = await User.findById(req.user.id).select('-password');
res.json(user);
} catch (error) {
res.status(500).json({
message: '获取用户信息失败',
error: error.message
});
}
};
controllers/postController.js - 文章控制器
const Post = require('../models/Post');
// 创建文章
exports.createPost = async (req, res) => {
try {
const { title, content, tags } = req.body;
// 检查必填字段
if (!title || !content) {
return res.status(400).json({
message: '标题和内容都是必需的'
});
}
// 创建文章
const post = new Post({
title,
content,
tags: tags || [],
author: req.user.id
});
await post.save();
// 填充作者信息
await post.populate('author', 'username email');
res.status(201).json({
message: '文章创建成功',
post
});
} catch (error) {
res.status(500).json({
message: '创建文章失败',
error: error.message
});
}
};
// 获取所有文章
exports.getAllPosts = async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;
// 查询条件
const query = {};
if (req.query.published === 'true') {
query.published = true;
}
// 获取文章列表
const posts = await Post.find(query)
.populate('author', 'username')
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
// 获取总数
const total = await Post.countDocuments(query);
res.json({
posts,
pagination: {
current: page,
pages: Math.ceil(total / limit),
total
}
});
} catch (error) {
res.status(500).json({
message: '获取文章列表失败',
error: error.message
});
}
};
// 获取单篇文章
exports.getPostById = async (req, res) => {
try {
const post = await Post.findById(req.params.id)
.populate('author', 'username email');
if (!post) {
return res.status(404).json({
message: '文章不存在'
});
}
res.json(post);
} catch (error) {
res.status(500).json({
message: '获取文章失败',
error: error.message
});
}
};
// 更新文章
exports.updatePost = async (req, res) => {
try {
const { title, content, tags, published } = req.body;
// 查找文章
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({
message: '文章不存在'
});
}
// 检查权限(只有作者可以更新)
if (post.author.toString() !== req.user.id) {
return res.status(403).json({
message: '无权修改此文章'
});
}
// 更新文章
post.title = title || post.title;
post.content = content || post.content;
post.tags = tags || post.tags;
if (published !== undefined) {
post.published = published;
}
await post.save();
// 填充作者信息
await post.populate('author', 'username email');
res.json({
message: '文章更新成功',
post
});
} catch (error) {
res.status(500).json({
message: '更新文章失败',
error: error.message
});
}
};
// 删除文章
exports.deletePost = async (req, res) => {
try {
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({
message: '文章不存在'
});
}
// 检查权限(只有作者可以删除)
if (post.author.toString() !== req.user.id) {
return res.status(403).json({
message: '无权删除此文章'
});
}
await Post.findByIdAndDelete(req.params.id);
res.json({
message: '文章删除成功'
});
} catch (error) {
res.status(500).json({
message: '删除文章失败',
error: error.message
});
}
};
middleware/auth.js - 认证中间件
const jwt = require('jsonwebtoken');
const User = require('../models/User');
// 认证中间件
const auth = async (req, res, next) => {
try {
// 从请求头获取 token
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
message: '访问被拒绝,未提供认证令牌'
});
}
// 验证 token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'default_secret');
// 查找用户
const user = await User.findById(decoded.id).select('-password');
if (!user) {
return res.status(401).json({
message: '认证失败,用户不存在'
});
}
// 将用户信息添加到请求对象
req.user = user;
next();
} catch (error) {
res.status(401).json({
message: '认证令牌无效'
});
}
};
module.exports = auth;
routes/users.js - 用户路由
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const auth = require('../middleware/auth');
// 注册路由 POST /api/users/register
router.post('/register', userController.register);
// 登录路由 POST /api/users/login
router.post('/login', userController.login);
// 获取当前用户信息 GET /api/users/me (需要认证)
router.get('/me', auth, userController.getCurrentUser);
module.exports = router;
routes/posts.js - 文章路由
const express = require('express');
const router = express.Router();
const postController = require('../controllers/postController');
const auth = require('../middleware/auth');
// 创建文章 POST /api/posts (需要认证)
router.post('/', auth, postController.createPost);
// 获取所有文章 GET /api/posts
router.get('/', postController.getAllPosts);
// 获取单篇文章 GET /api/posts/:id
router.get('/:id', postController.getPostById);
// 更新文章 PUT /api/posts/:id (需要认证)
router.put('/:id', auth, postController.updatePost);
// 删除文章 DELETE /api/posts/:id (需要认证)
router.delete('/:id', auth, postController.deletePost);
module.exports = router;
三、常用 API 详解
3.1 Express 核心 API
应用级方法
// 创建 Express 应用
const express = require('express');
const app = express();
// GET 请求
app.get('/', (req, res) => {
res.send('Hello World!');
});
// POST 请求
app.post('/users', (req, res) => {
res.send('Create a user');
});
// PUT 请求
app.put('/users/:id', (req, res) => {
res.send('Update a user');
});
// DELETE 请求
app.delete('/users/:id', (req, res) => {
res.send('Delete a user');
});
// 所有 HTTP 方法
app.all('/secret', (req, res, next) => {
console.log('Accessing the secret section ...');
next(); // 传递控制权到下一个处理器
});
路由参数
// 基本路由参数
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(req.params); // { userId: '123', bookId: '456' }
});
// 正则表达式路由参数
app.get('/user/:userId(\\d+)', (req, res) => {
res.send(`User ID: ${req.params.userId}`);
});
中间件使用
// 应用级中间件
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 路径特定中间件
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// 错误处理中间件(必须有4个参数)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
3.2 文件系统 (fs) API
读取文件
const fs = require('fs');
// 异步读取文件
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 同步读取文件
try {
const data = fs.readFileSync('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
// Promise 方式读取文件
const fsPromises = require('fs').promises;
async function readFileAsync() {
try {
const data = await fsPromises.readFile('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
}
写入文件
const fs = require('fs');
// 异步写入文件
fs.writeFile('message.txt', 'Hello Node.js', (err) => {
if (err) throw err;
console.log('文件已保存!');
});
// 同步写入文件
try {
fs.writeFileSync('message.txt', 'Hello Node.js');
console.log('文件已保存!');
} catch (err) {
console.error(err);
}
// 追加内容到文件
fs.appendFile('message.txt', '追加的数据', (err) => {
if (err) throw err;
console.log('数据已追加到文件');
});
3.3 HTTP 模块 API
创建 HTTP 服务器
const http = require('http');
// 创建简单服务器
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(3000, '127.0.0.1', () => {
console.log('服务器运行在 http://127.0.0.1:3000/');
});
处理不同请求方法
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
const method = req.method;
// 设置响应头
res.setHeader('Content-Type', 'application/json');
if (method === 'GET' && path === '/api/users') {
res.statusCode = 200;
res.end(JSON.stringify({ message: 'Get all users' }));
} else if (method === 'POST' && path === '/api/users') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log(body);
res.statusCode = 201;
res.end(JSON.stringify({ message: 'User created' }));
});
} else {
res.statusCode = 404;
res.end(JSON.stringify({ message: 'Not Found' }));
}
});
server.listen(3000);
3.4 事件系统 (events) API
EventEmitter 基本使用
const EventEmitter = require('events');
// 创建事件发射器实例
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// 监听事件
myEmitter.on('event', () => {
console.log('事件被触发!');
});
// 发射事件
myEmitter.emit('event');
// 带参数的事件
myEmitter.on('data', (data) => {
console.log('接收到数据:', data);
});
myEmitter.emit('data', { name: '张三', age: 25 });
一次性监听器
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// 只会触发一次
myEmitter.once('firstConnection', () => {
console.log('第一次连接!');
});
myEmitter.emit('firstConnection'); // 输出: 第一次连接!
myEmitter.emit('firstConnection'); // 不输出任何内容
3.5 流 (stream) API
可读流
const fs = require('fs');
// 创建可读流
const readableStream = fs.createReadStream('large-file.txt');
readableStream.on('data', (chunk) => {
console.log(`接收到 ${chunk.length} 字节的数据`);
});
readableStream.on('end', () => {
console.log('数据读取完成');
});
readableStream.on('error', (err) => {
console.error('发生错误:', err);
});
可写流
const fs = require('fs');
// 创建可写流
const writableStream = fs.createWriteStream('output.txt');
writableStream.write('Hello ');
writableStream.write('World!\n');
writableStream.end();
writableStream.on('finish', () => {
console.log('写入完成');
});
管道流
const fs = require('fs');
// 使用管道将可读流连接到可写流
const readable = fs.createReadStream('input.txt');
const writable = fs.createWriteStream('output.txt');
readable.pipe(writable);
// 链式管道
const zlib = require('zlib');
const gzip = zlib.createGzip();
readable.pipe(gzip).pipe(fs.createWriteStream('output.txt.gz'));
四、总结
Node.js 是一个功能强大的 JavaScript 运行环境,适用于构建各种类型的服务器端应用程序。通过上述详细介绍和实际项目示例,我们可以看到:
- 核心概念清晰:事件驱动、非阻塞 I/O 是 Node.js 的核心优势
- 生态系统丰富:npm 提供了大量的第三方包
- 开发效率高:统一的语言栈减少上下文切换
- 性能优秀:适合 I/O 密集型应用
通过构建完整的博客系统项目,我们掌握了:
- RESTful API 设计原则
- 数据库集成(MongoDB)
- 用户认证与授权
- 错误处理机制
- 中间件模式的应用
这些知识点构成了 Node.js 开发的基础,为更复杂的项目开发打下了坚实的基础。
1945

被折叠的 条评论
为什么被折叠?



