当前位置: 首页 > news >正文

Node.js 开发实战:从入门到精通

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 博客系统架构图

系统整体架构

在这里插入图片描述

用户认证流程

ClientAuthMiddlewareUserControllerJWTDatabasePOST /api/users/register{username, email, password}检查用户是否存在返回检查结果创建新用户(密码自动加密)返回用户信息生成token返回token{token, user}POST /api/users/login{email, password}根据邮箱查找用户返回用户信息验证密码生成token返回token{token, user}GET /api/postsAuthorization: Bearer <token>验证token返回解码信息根据ID查找用户返回用户信息继续处理请求ClientAuthMiddlewareUserControllerJWTDatabase

文章操作流程

ClientPostControllerAuthMiddlewareDatabasePOST /api/posts{title, content, tags}验证通过创建文章(关联当前用户)返回文章信息{message, post}GET /api/posts?page=1&limit=10查询文章列表(分页, 填充作者信息)返回文章列表{posts, pagination}PUT /api/posts/:id{title, content}验证通过查找文章返回文章检查权限更新文章返回更新后的文章{message, post}DELETE /api/posts/:id验证通过查找文章返回文章检查权限删除文章删除成功{message: '删除成功'}ClientPostControllerAuthMiddlewareDatabase

Express 中间件执行顺序

graph LRA[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]

数据模型关系图

USERPOSTwrites

API 端点映射图

HTTP Methods
Users Routes
/api/users
Posts Routes
/api/posts
POST /register
用户注册
POST /login
用户登录
GET /me
获取当前用户信息
POST /
创建文章
GET /
获取文章列表
GET /:id
获取指定文章
PUT /:id
更新文章
DELETE /:id
删除文章
图例
需要认证: 橙色背景
公开接口: 绿色背景
认证接口: 蓝色背景

二、实战项目:简易博客系统

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();// 生成 tokenconst 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: '邮箱或密码错误'});}// 生成 tokenconst 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 {// 从请求头获取 tokenconst token = req.header('Authorization')?.replace('Bearer ', '');if (!token) {return res.status(401).json({message: '访问被拒绝,未提供认证令牌'});}// 验证 tokenconst 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 运行环境,适用于构建各种类型的服务器端应用程序。通过上述详细介绍和实际项目示例,我们可以看到:

  1. 核心概念清晰:事件驱动、非阻塞 I/O 是 Node.js 的核心优势
  2. 生态系统丰富:npm 提供了大量的第三方包
  3. 开发效率高:统一的语言栈减少上下文切换
  4. 性能优秀:适合 I/O 密集型应用

通过构建完整的博客系统项目,我们掌握了:

  • RESTful API 设计原则
  • 数据库集成(MongoDB)
  • 用户认证与授权
  • 错误处理机制
  • 中间件模式的应用

这些知识点构成了 Node.js 开发的基础,为更复杂的项目开发打下了坚实的基础。

http://www.dtcms.com/a/605030.html

相关文章:

  • 草莓病害智能识别与分类_Cascade-RCNN_HRNetV2p-W18-20e_COCO实现
  • 改造多模块!!无法使用三方依赖的异常处理
  • JMeter 自动化实战:自动生成文件并传参接口的完整方案
  • AutoSAR实战:RTA-OS Counters操作系统计数器详解
  • FCAF3D: Fully Convolutional Anchor-Free 3D Object Detection论文精读
  • 北京市轨道交通建设管理有限公司网站企业网站建设合同书模板
  • 做图表的网站大连关键词
  • Vue 3中集成GIS(地理信息系统)
  • 进程基本概念
  • Java模拟算法题目练习
  • Mac远程控制新篇章:UU远程被控端深度测评
  • WordPress插件--菜单登录后可见的插件
  • 电商数据分析报告
  • Rust与主流编程语言客观对比:特性、场景与实践差异
  • C语言编译器有哪些 | 选择最适合的编译器提高开发效率
  • 网站频道规划网站个人备案模版
  • 昆明公司建设网站制作上海seo外包
  • MySQL: 存储引擎选择策略:基于事务支持、备份需求、崩溃恢复及特性兼容性的综合指南
  • 学生成绩管理系统 基于java+springboot+vue实现前后端分离项目并附带万字文档(源码+数据库+万字详设文档+软件包+安装教程)
  • ios-WebP
  • 网站如何做网站解析品牌策划方案怎么做
  • 能源企业合同管理数智化转型解决方案
  • 国标新规下的零碳园区新基建:碳电表与智慧能源平台的协同赋能
  • 从MCU到Agent:嵌入式系统如何进化成AI能源体
  • Hadess入门到精通 - 如何管理Docker制品
  • 网站建设对于电子商务的意义可以做代发货源的网站
  • ⸢ 拾伍 ⸥⤳ 安全数智化概念及建设思路
  • UCOS-III笔记(六)
  • 企业小型网站要多少钱百度怎么做网站广告
  • macos HbuildX 使用cli脚本创建uniapp 运行时报错“cli项目运行依赖本地的Nodejs环境,请先安装并配置到系统环境变量后重试。”