1. 什么是 Express.js?
Express.js 是一个最小且灵活的 Node.js Web 应用框架,为构建 Web 和移动应用提供了一系列强大的特性。
# 创建 Express 项目
mkdir my-express-app
cd my-express-app
npm init -y
npm install express
2. 核心特性
主要特点
-
极简且无约束
-
中间件架构
-
路由系统强大
-
模板引擎支持
-
错误处理机制
-
高性能
3. 基础应用结构
最小应用示例
// app.js
const express = require('express')
const app = express()
const port = 3000
// 基础路由
app.get('/', (req, res) => {
res.send('Hello World!')
})
// 启动服务器
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`)
})
标准项目结构
my-express-app/
├── src/
│ ├── app.js # 应用入口
│ ├── routes/ # 路由文件
│ │ ├── index.js
│ │ ├── users.js
│ │ └── api.js
│ ├── controllers/ # 控制器
│ ├── models/ # 数据模型
│ ├── middleware/ # 中间件
│ ├── public/ # 静态文件
│ ├── views/ # 模板文件
│ └── utils/ # 工具函数
├── package.json
└── .env
4. 应用对象 (Application)
创建 Express 应用
const express = require('express')
const app = express()
// 应用配置
app.set('view engine', 'ejs') // 模板引擎
app.set('views', './views') // 模板目录
app.set('port', process.env.PORT || 3000) // 端口设置
常用应用方法
// 静态文件服务
app.use(express.static('public'))
// 解析请求体
app.use(express.json()) // JSON 解析
app.use(express.urlencoded({ extended: true })) // URL编码解析
// 设置环境变量
app.set('env', 'production')
5. 路由系统 (Routing)
基础路由
// GET 请求
app.get('/users', (req, res) => {
res.send('获取用户列表')
})
// POST 请求
app.post('/users', (req, res) => {
const userData = req.body
res.json({ message: '用户创建成功', data: userData })
})
// PUT 请求
app.put('/users/:id', (req, res) => {
const userId = req.params.id
res.send(`更新用户 ${userId}`)
})
// DELETE 请求
app.delete('/users/:id', (req, res) => {
const userId = req.params.id
res.send(`删除用户 ${userId}`)
})
路由参数
// 路径参数
app.get('/users/:userId/books/:bookId', (req, res) => {
res.json({
userId: req.params.userId,
bookId: req.params.bookId
})
})
// 查询参数
app.get('/search', (req, res) => {
const { q, page = 1 } = req.query
res.json({ query: q, page: parseInt(page) })
})
路由模块化
// routes/users.js
const express = require('express')
const router = express.Router()
// GET /users
router.get('/', (req, res) => {
res.send('用户列表')
})
// POST /users
router.post('/', (req, res) => {
res.send('创建用户')
})
// GET /users/:id
router.get('/:id', (req, res) => {
res.send(`用户详情: ${req.params.id}`)
})
module.exports = router
在主应用中挂载路由
// app.js
const userRoutes = require('./routes/users')
const apiRoutes = require('./routes/api')
app.use('/users', userRoutes)
app.use('/api', apiRoutes)
6. 中间件 (Middleware)
自定义中间件
// 日志中间件
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`)
next()
})
// 认证中间件
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization
if (!token) {
return res.status(401).json({ error: '未提供认证令牌' })
}
// 验证 token...
next()
}
// 使用中间件
app.use('/api/protected', authMiddleware)
错误处理中间件
// 404 处理
app.use((req, res, next) => {
res.status(404).json({ error: '路由不存在' })
})
// 全局错误处理
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).json({
error: '服务器内部错误',
message: process.env.NODE_ENV === 'development' ? err.message : undefined
})
})
7. 请求和响应对象
请求对象 (Request)
app.post('/users', (req, res) => {
// 请求体数据
console.log(req.body)
// 查询参数
console.log(req.query)
// 路径参数
console.log(req.params)
// 请求头
console.log(req.headers)
// Cookies
console.log(req.cookies)
// 文件上传
console.log(req.files)
})
响应对象 (Response)
app.get('/api/data', (req, res) => {
// 发送 JSON
res.json({ message: 'Hello' })
// 发送状态码 + JSON
res.status(201).json({ id: 1, name: 'John' })
// 设置响应头
res.set('Content-Type', 'application/json')
// 重定向
res.redirect('/new-path')
// 下载文件
res.download('/path/to/file.pdf')
// 渲染模板
res.render('index', { title: '首页' })
})
8. 模板引擎
配置 EJS 模板
// 设置 EJS
app.set('view engine', 'ejs')
app.set('views', './views')
// 渲染模板
app.get('/', (req, res) => {
res.render('index', {
title: '我的网站',
users: ['张三', '李四', '王五']
})
})
EJS 模板示例
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1>欢迎来到 <%= title %></h1>
<ul>
<% users.forEach(user => { %>
<li><%= user %></li>
<% }) %>
</ul>
</body>
</html>
9. 静态文件服务
// 提供静态文件
app.use(express.static('public'))
// 多个静态目录
app.use(express.static('public'))
app.use(express.static('uploads'))
// 虚拟路径前缀
app.use('/static', express.static('public'))
10. 错误处理
同步错误处理
app.get('/error', (req, res) => {
throw new Error('测试错误')
})
异步错误处理
app.get('/async-error', async (req, res, next) => {
try {
const data = await someAsyncOperation()
res.json(data)
} catch (error) {
next(error)
}
})
自定义错误类
class AppError extends Error {
constructor(message, statusCode) {
super(message)
this.statusCode = statusCode
this.isOperational = true
Error.captureStackTrace(this, this.constructor)
}
}
// 使用自定义错误
app.get('/protected', (req, res, next) => {
if (!req.user) {
return next(new AppError('请先登录', 401))
}
res.send('受保护的内容')
})
11. 数据库集成
MongoDB + Mongoose
const mongoose = require('mongoose')
// 连接数据库
mongoose.connect('mongodb://localhost:27017/myapp')
// 定义模型
const UserSchema = new mongoose.Schema({
name: String,
email: String,
age: Number
})
const User = mongoose.model('User', UserSchema)
// 在路由中使用
app.get('/api/users', async (req, res) => {
try {
const users = await User.find()
res.json(users)
} catch (error) {
res.status(500).json({ error: error.message })
}
})
MySQL + mysql2
const mysql = require('mysql2/promise')
// 创建连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
})
// 在路由中使用
app.get('/api/products', async (req, res) => {
try {
const [rows] = await pool.execute('SELECT * FROM products')
res.json(rows)
} catch (error) {
res.status(500).json({ error: error.message })
}
})
12. 安全最佳实践
安全中间件
const helmet = require('helmet')
const rateLimit = require('express-rate-limit')
const cors = require('cors')
// 安全头设置
app.use(helmet())
// CORS 配置
app.use(cors({
origin: ['https://example.com', 'http://localhost:3000'],
credentials: true
}))
// 速率限制
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100 // 限制每个IP 100次请求
})
app.use('/api', limiter)
// 数据清理
const mongoSanitize = require('express-mongo-sanitize')
app.use(mongoSanitize())
13. 生产环境配置
环境变量管理
// .env
NODE_ENV=production
PORT=3000
DB_URL=mongodb://localhost:27017/myapp
JWT_SECRET=your-secret-key
// app.js
require('dotenv').config()
const PORT = process.env.PORT || 3000
const DB_URL = process.env.DB_URL
进程管理
// package.json
{
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"production": "pm2 start app.js -i max"
}
}
14. 完整示例项目
项目结构
project/
├── src/
│ ├── app.js
│ ├── config/
│ │ └── database.js
│ ├── routes/
│ │ ├── index.js
│ │ ├── users.js
│ │ └── auth.js
│ ├── middleware/
│ │ ├── auth.js
│ │ └── errorHandler.js
│ ├── models/
│ │ └── User.js
│ └── controllers/
│ └── userController.js
├── public/
├── views/
├── .env
└── package.json
主应用文件
// src/app.js
const express = require('express')
const cors = require('cors')
const helmet = require('helmet')
const morgan = require('morgan')
const app = express()
// 中间件
app.use(helmet())
app.use(cors())
app.use(morgan('combined'))
app.use(express.json())
app.use(express.static('public'))
// 路由
app.use('/', require('./routes/index'))
app.use('/api/users', require('./routes/users'))
app.use('/api/auth', require('./routes/auth'))
// 错误处理
app.use(require('./middleware/errorHandler'))
// 404 处理
app.use('*', (req, res) => {
res.status(404).json({ error: '路由不存在' })
})
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`)
})
module.exports = app
15. 优势总结
优点
-
简单易学 - API 简洁直观
-
灵活自由 - 无强制约束,可按需配置
-
生态丰富 - 海量中间件和插件
-
性能优秀 - 轻量级,开销小
-
社区活跃 - 大量教程和资源
-
易于扩展 - 模块化设计
注意事项
-
需要更多配置 - 相比全栈框架需要手动配置更多东西
-
架构依赖开发者 - 需要自己设计项目结构
-
安全性需要手动处理 - 需要安装和配置安全中间件
16. 适用场景
-
🚀 RESTful API 开发
-
🏢 微服务架构
-
📱 后端服务
-
🔧 需要高度自定义的项目
-
🎓 学习 Node.js Web 开发
Express.js 是 Node.js 生态中最基础、最流行的 Web 框架,几乎所有的 Node.js 开发者都应该掌握它。