JDWA 技术文档
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
  • 数据库

    • 数据库教程
    • MySQL免安装版使用指南
    • MySQL性能优化实践
    • Redis入门与实践
    • MinIO快速部署指南
    • MinIO基础使用教程
  • 前端开发

    • 前端开发教程
    • Vue.js开发最佳实践
    • CSS常用技巧与解决方案
    • JavaScript实用技巧与编程模式
    • CSS Grid布局教程
  • 后端开发

    • 后端开发教程
    • Spring Boot实战指南
    • Node.js Express 框架开发实战指南
    • Python Flask 框架开发指南
  • 开发工具

    • 开发工具教程
    • Git 基础教程
    • Git工作流实践指南
    • VS Code 全面使用指南
    • VS Code必装插件推荐
    • Docker基础入门
    • IntelliJ IDEA 使用技巧
    • Eclipse配置与优化
    • Sublime Text 高级技巧
    • Vim 从入门到精通
    • Maven 详解
    • Gradle 入门与进阶
    • Webpack 配置指南
    • npm 与 yarn 使用技巧
    • Makefile 编写指南
    • Navicat 使用指南
    • MCP本地部署教程
  • 虚拟化技术

    • JDWA虚拟化技术专题
    • KVM虚拟机去虚拟化技术详解
  • KVM显卡直通

    • KVM显卡GPU直通教程
  • FPGA仿真固件

    • FPGA仿真固件开发指南
    • 基础-完整设备仿真定制固件开发指南
    • 中级-完整设备仿真定制固件开发指南
    • 高级-完整设备仿真定制固件开发指南

Node.js Express 框架开发实战指南

前言

Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。作为 Node.js 最流行的 Web 框架,Express 提供了一套简洁而灵活的 API,可以帮助开发者快速构建各种 Web 应用和移动应用的后端。本文将全面介绍 Express 框架的核心概念、路由设计、中间件使用和项目最佳实践。

基础入门

环境准备

在开始之前,请确保已安装 Node.js(建议使用 LTS 版本)和 npm。

# 检查 Node.js 和 npm 版本
node -v
npm -v

# 创建项目目录
mkdir express-demo
cd express-demo

# 初始化项目
npm init -y

# 安装 Express
npm install express

创建第一个应用

创建一个名为 app.js 的文件,包含基本的 Express 应用:

// 引入 Express 模块
const express = require('express');

// 创建 Express 应用
const app = express();
const port = 3000;

// 定义根路由
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

运行应用并在浏览器中访问 http://localhost:3000:

node app.js

路由系统

基本路由

Express 的路由定义采用以下结构:

app.METHOD(PATH, HANDLER);
  • METHOD 是 HTTP 方法(如 get, post, put, delete 等)
  • PATH 是服务器上的路径
  • HANDLER 是当路由匹配时执行的函数
// 基本路由示例
app.get('/', (req, res) => {
  res.send('首页');
});

app.post('/users', (req, res) => {
  res.send('创建用户');
});

app.put('/users/:id', (req, res) => {
  res.send(`更新用户 ${req.params.id}`);
});

app.delete('/users/:id', (req, res) => {
  res.send(`删除用户 ${req.params.id}`);
});

路由参数

可以通过 req.params 对象访问路由参数:

// 路由参数示例
app.get('/users/:userId/books/:bookId', (req, res) => {
  res.send(`用户 ${req.params.userId} 的图书 ${req.params.bookId}`);
});

路由处理器

可以为一个路由提供多个回调函数:

// 多个回调函数
app.get('/example', 
  (req, res, next) => {
    console.log('第一个回调');
    next(); // 传递控制权给下一个回调
  },
  (req, res) => {
    res.send('第二个回调');
  }
);

路由模块化

随着应用规模扩大,应将路由分离到独立模块:

// routes/users.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('获取所有用户');
});

router.get('/:id', (req, res) => {
  res.send(`获取用户 ${req.params.id}`);
});

module.exports = router;

// app.js
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

中间件

中间件函数可以访问请求对象、响应对象和应用程序的请求-响应周期中的 next 函数。

应用级中间件

// 所有请求都会经过此中间件
app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});

// 特定路径的中间件
app.use('/users', (req, res, next) => {
  console.log('Request Type:', req.method);
  next();
});

常用内置中间件

// 解析 JSON 请求体
app.use(express.json());

// 解析 URL 编码的请求体
app.use(express.urlencoded({ extended: true }));

// 静态文件服务
app.use(express.static('public'));

错误处理中间件

错误处理中间件必须有四个参数:

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('服务器错误');
});

第三方中间件

Express 生态系统中有许多有用的第三方中间件:

// 安装第三方中间件
npm install morgan cors helmet

// 使用举例
const morgan = require('morgan');
const cors = require('cors');
const helmet = require('helmet');

app.use(morgan('dev')); // 请求日志
app.use(cors());        // 处理跨域
app.use(helmet());      // 安全相关 HTTP 头

请求和响应

Express 扩展了 Node.js 的 req 和 res 对象,提供了额外的方法和属性。

请求对象(req)

// 查询字符串参数
app.get('/search', (req, res) => {
  console.log(req.query.term);  // 获取查询参数 ?term=value
  res.send(`搜索: ${req.query.term}`);
});

// 请求体
app.post('/data', (req, res) => {
  console.log(req.body);  // 已通过 express.json() 或 express.urlencoded() 解析
  res.send('数据已接收');
});

// 请求头
app.get('/headers', (req, res) => {
  console.log(req.get('Content-Type'));  // 获取请求头
  res.send('请求头已处理');
});

响应对象(res)

// 发送响应
res.send('文本响应');
res.send({ user: 'John' });  // 自动转换为 JSON
res.json({ user: 'John' });  // 明确发送 JSON

// 设置状态码
res.status(201).send('资源已创建');
res.status(404).send('未找到资源');

// 重定向
res.redirect('/home');
res.redirect(301, '/new-page');  // 301 永久重定向

// 设置响应头
res.set('Content-Type', 'text/plain');
res.set({
  'Content-Type': 'text/plain',
  'X-Custom-Header': 'Custom Value'
});

// 渲染模板 (需要设置模板引擎)
res.render('index', { title: '首页', user: 'John' });

视图和模板引擎

Express 支持多种模板引擎,如 Pug, EJS, Handlebars 等。

// 安装 EJS 模板引擎
npm install ejs

// 配置模板引擎
app.set('view engine', 'ejs');
app.set('views', './views');  // 模板文件目录

// 创建视图 (views/index.ejs)
/*
<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
</head>
<body>
  <h1>Hello, <%= name %>!</h1>
</body>
</html>
*/

// 渲染视图
app.get('/', (req, res) => {
  res.render('index', { title: 'Express', name: 'World' });
});

数据库集成

Express 可以与多种数据库集成,包括 MongoDB, MySQL, PostgreSQL 等。

MongoDB 示例 (使用 Mongoose)

// 安装 Mongoose
npm install mongoose

// 连接到 MongoDB
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// 定义用户模型
const userSchema = new mongoose.Schema({
  name: String,
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  createdAt: { type: Date, default: Date.now }
});

const User = mongoose.model('User', userSchema);

// 创建用户
app.post('/users', async (req, res) => {
  try {
    const user = new User(req.body);
    await user.save();
    res.status(201).send(user);
  } catch (error) {
    res.status(400).send(error);
  }
});

// 获取所有用户
app.get('/users', async (req, res) => {
  try {
    const users = await User.find({});
    res.send(users);
  } catch (error) {
    res.status(500).send(error);
  }
});

SQL 数据库示例 (使用 Sequelize)

// 安装 Sequelize 和 MySQL 驱动
npm install sequelize mysql2

// 连接到 MySQL
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

// 定义用户模型
const User = sequelize.define('User', {
  name: DataTypes.STRING,
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false
  }
});

// 同步模型到数据库
(async () => {
  await sequelize.sync();
  console.log('数据库同步完成');
})();

// 创建用户
app.post('/users', async (req, res) => {
  try {
    const user = await User.create(req.body);
    res.status(201).send(user);
  } catch (error) {
    res.status(400).send(error);
  }
});

// 获取所有用户
app.get('/users', async (req, res) => {
  try {
    const users = await User.findAll();
    res.send(users);
  } catch (error) {
    res.status(500).send(error);
  }
});

身份验证与授权

使用 JWT (JSON Web Tokens) 实现身份验证:

// 安装依赖
npm install jsonwebtoken bcryptjs

// 用户登录
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

app.post('/login', async (req, res) => {
  try {
    // 查找用户
    const user = await User.findOne({ email: req.body.email });
    if (!user) return res.status(400).send('用户不存在');
    
    // 验证密码
    const validPassword = await bcrypt.compare(req.body.password, user.password);
    if (!validPassword) return res.status(400).send('密码错误');
    
    // 生成 token
    const token = jwt.sign({ id: user._id }, 'your_jwt_secret', { expiresIn: '2h' });
    
    res.send({ token });
  } catch (error) {
    res.status(500).send(error);
  }
});

// 验证令牌的中间件
function auth(req, res, next) {
  const token = req.header('x-auth-token');
  if (!token) return res.status(401).send('未提供令牌');
  
  try {
    const verified = jwt.verify(token, 'your_jwt_secret');
    req.user = verified;
    next();
  } catch (error) {
    res.status(400).send('无效的令牌');
  }
}

// 受保护的路由
app.get('/protected', auth, (req, res) => {
  res.send('这是受保护的资源');
});

文件上传

使用 multer 中间件处理文件上传:

// 安装 multer
npm install multer

// 配置文件上传
const multer = require('multer');
const path = require('path');

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    cb(null, `${Date.now()}-${file.originalname}`);
  }
});

const upload = multer({ 
  storage,
  limits: { fileSize: 1000000 }, // 限制 1MB
  fileFilter: (req, file, cb) => {
    // 检查文件类型
    const filetypes = /jpeg|jpg|png|gif/;
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = filetypes.test(file.mimetype);
    
    if (mimetype && extname) {
      return cb(null, true);
    } else {
      cb('错误:仅支持图片文件');
    }
  }
});

// 单文件上传
app.post('/upload', upload.single('image'), (req, res) => {
  res.send(`文件上传成功: ${req.file.path}`);
});

// 多文件上传
app.post('/upload-multiple', upload.array('images', 5), (req, res) => {
  res.send(`上传了 ${req.files.length} 个文件`);
});

API 设计最佳实践

RESTful API 设计

// 资源命名 - 使用复数名词
app.get('/api/users', ...);      // 获取所有用户
app.get('/api/users/:id', ...);  // 获取特定用户
app.post('/api/users', ...);     // 创建用户
app.put('/api/users/:id', ...);  // 更新用户
app.delete('/api/users/:id', ...); // 删除用户

// 嵌套资源
app.get('/api/users/:userId/posts', ...); // 获取用户的所有帖子
app.get('/api/users/:userId/posts/:postId', ...); // 获取用户的特定帖子

错误处理

// 处理异步错误
function asyncHandler(fn) {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
}

app.get('/users', asyncHandler(async (req, res) => {
  const users = await User.find({});
  res.send(users);
}));

// 集中式错误处理
app.use((err, req, res, next) => {
  // 记录错误
  console.error(err.stack);
  
  // 根据环境返回不同级别的错误信息
  if (process.env.NODE_ENV === 'production') {
    res.status(500).send('服务器错误');
  } else {
    res.status(500).send(`错误: ${err.message}\n${err.stack}`);
  }
});

版本控制

// 使用 URL 路径版本化
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);

// 或使用请求头版本化
app.use((req, res, next) => {
  const version = req.get('Accept-Version') || 'v1';
  req.apiVersion = version;
  next();
});

性能优化

压缩响应

// 安装 compression
npm install compression

// 启用压缩
const compression = require('compression');
app.use(compression());

缓存控制

// 设置缓存头
app.get('/api/data', (req, res) => {
  res.set('Cache-Control', 'public, max-age=300'); // 缓存5分钟
  res.send(data);
});

负载测试

# 使用 autocannon 进行负载测试
npm install -g autocannon
autocannon -c 100 -d 5 http://localhost:3000/api/users

部署与生产环境配置

环境变量管理

// 安装 dotenv
npm install dotenv

// 加载环境变量
require('dotenv').config();

const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;

app.listen(port, () => {
  console.log(`服务器运行在端口 ${port}`);
});

进程管理

# 安装 PM2
npm install -g pm2

# 启动应用
pm2 start app.js --name "my-api" -i max

# 监控
pm2 monit

# 日志查看
pm2 logs

安全最佳实践

// 安装安全相关中间件
npm install helmet cors rate-limiter-flexible

// 配置安全中间件
const helmet = require('helmet');
const cors = require('cors');
const { RateLimiterMemory } = require('rate-limiter-flexible');

// 使用 Helmet 设置安全相关 HTTP 头
app.use(helmet());

// 配置 CORS
app.use(cors({
  origin: ['https://yourapp.com', 'https://www.yourapp.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

// 设置速率限制
const rateLimiter = new RateLimiterMemory({
  points: 10, // 请求点数
  duration: 1, // 每秒
});

app.use(async (req, res, next) => {
  try {
    await rateLimiter.consume(req.ip);
    next();
  } catch {
    res.status(429).send('请求过多,请稍后再试');
  }
});

测试

单元测试

# 安装测试工具
npm install --save-dev mocha chai supertest

# 创建测试文件 (test/users.js)
const request = require('supertest');
const { expect } = require('chai');
const app = require('../app');

describe('User API', () => {
  it('should get all users', async () => {
    const res = await request(app).get('/api/users');
    expect(res.status).to.equal(200);
    expect(res.body).to.be.an('array');
  });
  
  it('should create a new user', async () => {
    const user = {
      name: 'Test User',
      email: 'test@example.com',
      password: 'password123'
    };
    
    const res = await request(app)
      .post('/api/users')
      .send(user);
      
    expect(res.status).to.equal(201);
    expect(res.body).to.have.property('_id');
    expect(res.body.name).to.equal(user.name);
  });
});

运行测试

npx mocha test

示例项目: RESTful API

完整的 Express.js RESTful API 示例:

// app.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
require('dotenv').config();

// 创建 Express 应用
const app = express();
const port = process.env.PORT || 3000;

// 中间件
app.use(helmet());
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 连接到数据库
mongoose.connect(process.env.DATABASE_URL)
  .then(() => console.log('已连接到 MongoDB'))
  .catch(err => console.error('数据库连接错误:', err));

// 路由
const usersRouter = require('./routes/users');
const authRouter = require('./routes/auth');

app.use('/api/users', usersRouter);
app.use('/api/auth', authRouter);

// 基础路由
app.get('/', (req, res) => {
  res.send('API 运行中');
});

// 错误处理
app.use((req, res, next) => {
  res.status(404).send('未找到资源');
});

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('服务器错误');
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

module.exports = app;

总结

Express.js 是一个功能强大且灵活的 Web 框架,非常适合构建 RESTful API 和 Web 应用。本文涵盖了 Express 开发中的核心概念和最佳实践,包括路由、中间件、数据库集成、身份验证和部署等方面。

通过掌握这些概念和技术,你可以使用 Express 构建出高性能、安全可靠的 Web 应用和 API 服务。随着应用规模的扩大,合理的项目结构和最佳实践将有助于维护代码质量和开发效率。

参考资料

  • Express.js 官方文档
  • Node.js Best Practices
  • RESTful API 设计最佳实践
  • Express.js Security Best Practices
Prev
Spring Boot实战指南
Next
Python Flask 框架开发指南