目录
1. Node.js基础
1.1 什么是Node.js
Node.js是基于Chrome V8引擎的JavaScript运行环境,让JavaScript能够在服务器端运行。
特点:
- 事件驱动、非阻塞I/O模型
- 单线程但高并发
- 跨平台
- 丰富的包生态系统(npm)
1.2 安装与环境配置
# 检查Node.js版本
node --version
# 检查npm版本
npm --version
# 创建新项目
mkdir my-node-app
cd my-node-app
npm init -y
1.3 第一个Node.js程序
// hello.js
console.log('Hello, Node.js!');
console.log('当前Node.js版本:', process.version);
console.log('当前工作目录:', process.cwd());
console.log('命令行参数:', process.argv);
# 运行程序
node hello.js
1.4 模块系统
CommonJS模块 (传统方式):
// math.js - 导出模块
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
// 导出方式1:逐个导出
exports.add = add;
exports.subtract = subtract;
// 导出方式2:整体导出
module.exports = {
add,
subtract,
multiply: (a, b) => a * b
};
// app.js - 导入模块
const math = require('./math');
// 或者使用解构赋值
const { add, subtract } = require('./math');
console.log(math.add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
ES6模块 (现代方式):
// math.mjs
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
// 默认导出
export default function multiply(a, b) {
return a * b;
}
// app.mjs
import multiply, { add, subtract } from './math.mjs';
console.log(add(5, 3)); // 8
console.log(multiply(5, 3)); // 15
2. 核心模块详解
2.1 path模块 - 路径处理
const path = require('path');
// 路径拼接
const fullPath = path.join('/users', 'john', 'documents', 'file.txt');
console.log(fullPath); // /users/john/documents/file.txt
// 路径解析
const filePath = '/home/user/documents/file.txt';
console.log('目录名:', path.dirname(filePath)); // /home/user/documents
console.log('文件名:', path.basename(filePath)); // file.txt
console.log('扩展名:', path.extname(filePath)); // .txt
// 路径规范化
const messyPath = '/home/user/../user/./documents//file.txt';
console.log('规范化路径:', path.normalize(messyPath));
// /home/user/documents/file.txt
2.2 url模块 - URL处理
const url = require('url');
const myUrl = 'https://www.example.com:8080/path/to/resource?name=john&age=30#section1';
// 解析URL
const parsedUrl = url.parse(myUrl, true);
console.log(parsedUrl);
/*
{
protocol: 'https:',
host: 'www.example.com:8080',
hostname: 'www.example.com',
port: '8080',
pathname: '/path/to/resource',
query: { name: 'john', age: '30' },
hash: '#section1'
}
*/
// 构建URL
const newUrl = url.format({
protocol: 'https:',
hostname: 'api.example.com',
port: 3000,
pathname: '/users',
query: { page: 1, limit: 10 }
});
console.log(newUrl); // https://api.example.com:3000/users?page=1&limit=10
2.3 querystring模块 - 查询字符串处理
const querystring = require('querystring');
// 解析查询字符串
const query = 'name=john&age=30&skills=js&skills=node';
const parsed = querystring.parse(query);
console.log(parsed);
// { name: 'john', age: '30', skills: ['js', 'node'] }
// 构建查询字符串
const obj = { name: 'jane', age: 25, city: 'New York' };
const queryStr = querystring.stringify(obj);
console.log(queryStr); // name=jane&age=25&city=New%20York
3. 文件系统操作
3.1 基本文件操作
const fs = require('fs');
const path = require('path');
// 同步读取文件
try {
const data = fs.readFileSync('example.txt', 'utf8');
console.log('文件内容:', data);
} catch (error) {
console.error('读取文件失败:', error.message);
}
// 异步读取文件
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err.message);
return;
}
console.log('文件内容:', data);
});
// Promise方式读取文件
const fsPromises = fs.promises;
async function readFileAsync() {
try {
const data = await fsPromises.readFile('example.txt', 'utf8');
console.log('文件内容:', data);
} catch (error) {
console.error('读取文件失败:', error.message);
}
}
3.2 文件写入操作
const fs = require('fs');
// 写入文件
const content = 'Hello, Node.js File System!';
// 异步写入
fs.writeFile('output.txt', content, 'utf8', (err) => {
if (err) {
console.error('写入失败:', err.message);
return;
}
console.log('文件写入成功!');
});
// 追加内容
fs.appendFile('output.txt', '\n追加的内容', 'utf8', (err) => {
if (err) {
console.error('追加失败:', err.message);
return;
}
console.log('内容追加成功!');
});
3.3 目录操作
const fs = require('fs');
const path = require('path');
// 创建目录
fs.mkdir('new-directory', { recursive: true }, (err) => {
if (err) {
console.error('创建目录失败:', err.message);
return;
}
console.log('目录创建成功!');
});
// 读取目录
fs.readdir('.', (err, files) => {
if (err) {
console.error('读取目录失败:', err.message);
return;
}
console.log('目录内容:');
files.forEach(file => {
const filePath = path.join('.', file);
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
console.log(`📁 ${file}/`);
} else {
console.log(`📄 ${file} (${stats.size} bytes)`);
}
});
});
3.4 文件流操作
const fs = require('fs');
const path = require('path');
// 创建可读流
const readStream = fs.createReadStream('large-file.txt', {
encoding: 'utf8',
highWaterMark: 1024 // 缓冲区大小
});
// 创建可写流
const writeStream = fs.createWriteStream('output-stream.txt');
// 流事件处理
readStream.on('data', (chunk) => {
console.log(`读取到 ${chunk.length} 字节数据`);
writeStream.write(chunk);
});
readStream.on('end', () => {
console.log('文件读取完成');
writeStream.end();
});
readStream.on('error', (err) => {
console.error('读取错误:', err.message);
});
// 使用管道简化流操作
const inputStream = fs.createReadStream('input.txt');
const outputStream = fs.createWriteStream('output-pipe.txt');
inputStream.pipe(outputStream);
4. HTTP服务器开发
4.1 基本HTTP服务器
const http = require('http');
const url = require('url');
const querystring = require('querystring');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const method = req.method;
const pathname = parsedUrl.pathname;
const query = parsedUrl.query;
// 设置响应头
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.setHeader('Access-Control-Allow-Origin', '*');
console.log(`${method} ${pathname}`);
// 路由处理
if (pathname === '/' && method === 'GET') {
res.statusCode = 200;
res.end(JSON.stringify({
message: '欢迎使用Node.js HTTP服务器!',
timestamp: new Date().toISOString()
}));
} else if (pathname === '/api/users' && method === 'GET') {
const users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
res.statusCode = 200;
res.end(JSON.stringify({ users }));
} else if (pathname === '/api/users' && method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
try {
const userData = JSON.parse(body);
// 这里应该保存到数据库
res.statusCode = 201;
res.end(JSON.stringify({
message: '用户创建成功',
user: { id: Date.now(), ...userData }
}));
} catch (error) {
res.statusCode = 400;
res.end(JSON.stringify({
error: '无效的JSON数据'
}));
}
});
} else {
res.statusCode = 404;
res.end(JSON.stringify({
error: '页面未找到'
}));
}
});
// 启动服务器
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}`);
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到SIGTERM信号,正在关闭服务器...');
server.close(() => {
console.log('服务器已关闭');
process.exit(0);
});
});
4.2 HTTPS服务器
const https = require('https');
const fs = require('fs');
// SSL证书配置
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem')
};
const server = https.createServer(options, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(`
<h1>HTTPS服务器</h1>
<p>这是一个安全的HTTPS连接</p>
<p>当前时间: ${new Date().toLocaleString()}</p>
`);
});
server.listen(443, () => {
console.log('HTTPS服务器运行在 https://localhost:443');
});
5. Express框架
5.1 Express基础
// 首先安装Express: npm install express
const express = require('express');
const app = express();
// 中间件配置
app.use(express.json()); // 解析JSON请求体
app.use(express.urlencoded({ extended: true })); // 解析URL编码请求体
app.use(express.static('public')); // 静态文件服务
// 基本路由
app.get('/', (req, res) => {
res.json({
message: '欢迎使用Express!',
version: '1.0.0'
});
});
// 路由参数
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.json({
message: `获取用户信息`,
userId: userId
});
});
// 查询参数
app.get('/search', (req, res) => {
const { q, page = 1, limit = 10 } = req.query;
res.json({
query: q,
page: parseInt(page),
limit: parseInt(limit),
results: []
});
});
// POST路由
app.post('/users', (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({
error: '姓名和邮箱不能为空'
});
}
// 模拟保存到数据库
const user = {
id: Date.now(),
name,
email,
createdAt: new Date()
};
res.status(201).json({
message: '用户创建成功',
user
});
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Express服务器运行在端口 ${PORT}`);
});
5.2 Express路由模块化
// routes/users.js
const express = require('express');
const router = express.Router();
// 用户数据模拟
let users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
// 获取所有用户
router.get('/', (req, res) => {
res.json({ users });
});
// 获取单个用户
router.get('/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({ error: '用户不存在' });
}
res.json({ user });
});
// 创建用户
router.post('/', (req, res) => {
const { name, email } = req.body;
const user = {
id: Math.max(...users.map(u => u.id)) + 1,
name,
email
};
users.push(user);
res.status(201).json({ user });
});
// 更新用户
router.put('/:id', (req, res) => {
const userId = parseInt(req.params.id);
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex === -1) {
return res.status(404).json({ error: '用户不存在' });
}
users[userIndex] = { ...users[userIndex], ...req.body };
res.json({ user: users[userIndex] });
});
// 删除用户
router.delete('/:id', (req, res) => {
const userId = parseInt(req.params.id);
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex === -1) {
return res.status(404).json({ error: '用户不存在' });
}
const deletedUser = users.splice(userIndex, 1)[0];
res.json({ message: '用户删除成功', user: deletedUser });
});
module.exports = router;
// app.js - 使用路由模块
const express = require('express');
const usersRouter = require('./routes/users');
const app = express();
app.use(express.json());
app.use('/api/users', usersRouter);
app.listen(3000, () => {
console.log('服务器运行在端口 3000');
});
5.3 Express中间件
const express = require('express');
const app = express();
// 日志中间件
const logger = (req, res, next) => {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] ${req.method} ${req.url}`);
next(); // 传递控制权给下一个中间件
};
// 认证中间件
const authenticate = (req, res, next) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: '缺少认证令牌' });
}
// 模拟令牌验证
if (token !== 'Bearer valid-token') {
return res.status(401).json({ error: '无效的令牌' });
}
req.user = { id: 1, name: 'Alice' }; // 设置用户信息
next();
};
// 错误处理中间件
const errorHandler = (err, req, res, next) => {
console.error(err.stack);
if (err.type === 'validation') {
return res.status(400).json({ error: err.message });
}
res.status(500).json({ error: '服务器内部错误' });
};
// 应用中间件
app.use(logger);
app.use(express.json());
// 公开路由
app.get('/', (req, res) => {
res.json({ message: '欢迎访问API' });
});
// 需要认证的路由
app.get('/profile', authenticate, (req, res) => {
res.json({
message: '用户资料',
user: req.user
});
});
// 触发错误的路由(用于测试错误处理)
app.get('/error', (req, res, next) => {
const error = new Error('这是一个测试错误');
error.type = 'validation';
next(error);
});
// 应用错误处理中间件(必须放在最后)
app.use(errorHandler);
app.listen(3000, () => {
console.log('服务器运行在端口 3000');
});
6. 数据库操作
6.1 MongoDB集成(使用Mongoose)
// 首先安装: npm install mongoose
const mongoose = require('mongoose');
const express = require('express');
// 连接MongoDB
mongoose.connect('mongodb://localhost:27017/nodeapp', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('MongoDB连接成功'))
.catch(err => console.error('MongoDB连接失败:', err));
// 定义用户模式
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, '姓名不能为空'],
trim: true,
maxlength: [50, '姓名不能超过50个字符']
},
email: {
type: String,
required: [true, '邮箱不能为空'],
unique: true,
lowercase: true,
match: [/^\w+@\w+\.\w+$/, '邮箱格式不正确']
},
age: {
type: Number,
min: [0, '年龄不能为负数'],
max: [120, '年龄不能超过120']
},
createdAt: {
type: Date,
default: Date.now
}
});
// 添加索引
userSchema.index({ email: 1 }, { unique: true });
// 实例方法
userSchema.methods.getFullInfo = function() {
return `${this.name} (${this.email})`;
};
// 静态方法
userSchema.statics.findByEmail = function(email) {
return this.findOne({ email });
};
const User = mongoose.model('User', userSchema);
const app = express();
app.use(express.json());
// 创建用户
app.post('/api/users', async (req, res) => {
try {
const user = new User(req.body);
await user.save();
res.status(201).json({
message: '用户创建成功',
user
});
} catch (error) {
if (error.name === 'ValidationError') {
const errors = Object.values(error.errors).map(e => e.message);
return res.status(400).json({ errors });
}
if (error.code === 11000) {
return res.status(400).json({ error: '邮箱已存在' });
}
res.status(500).json({ error: '服务器错误' });
}
});
// 获取所有用户
app.get('/api/users', async (req, res) => {
try {
const { page = 1, limit = 10, search } = req.query;
const query = search ?
{ $or: [
{ name: new RegExp(search, 'i') },
{ email: new RegExp(search, 'i') }
]} : {};
const users = await User.find(query)
.limit(limit * 1)
.skip((page - 1) * limit)
.sort({ createdAt: -1 });
const total = await User.countDocuments(query);
res.json({
users,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
});
} catch (error) {
res.status(500).json({ error: '服务器错误' });
}
});
// 获取单个用户
app.get('/api/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({ error: '用户不存在' });
}
res.json({ user });
} catch (error) {
res.status(500).json({ error: '服务器错误' });
}
});
app.listen(3000, () => {
console.log('服务器运行在端口 3000');
});
6.2 MySQL集成(使用mysql2)
// 首先安装: npm install mysql2
const mysql = require('mysql2/promise');
const express = require('express');
// 创建数据库连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'nodeapp',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// 数据库初始化
async function initDatabase() {
try {
await pool.execute(`
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
console.log('数据库表创建成功');
} catch (error) {
console.error('数据库初始化失败:', error);
}
}
initDatabase();
const app = express();
app.use(express.json());
// 创建用户
app.post('/api/users', async (req, res) => {
const { name, email, age } = req.body;
try {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
const [users] = await