Node.js后端框架Express.js

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. 优势总结

优点

  1. 简单易学 - API 简洁直观

  2. 灵活自由 - 无强制约束,可按需配置

  3. 生态丰富 - 海量中间件和插件

  4. 性能优秀 - 轻量级,开销小

  5. 社区活跃 - 大量教程和资源

  6. 易于扩展 - 模块化设计

注意事项

  1. 需要更多配置 - 相比全栈框架需要手动配置更多东西

  2. 架构依赖开发者 - 需要自己设计项目结构

  3. 安全性需要手动处理 - 需要安装和配置安全中间件

16. 适用场景

  • 🚀 RESTful API 开发

  • 🏢 微服务架构

  • 📱 后端服务

  • 🔧 需要高度自定义的项目

  • 🎓 学习 Node.js Web 开发

Express.js 是 Node.js 生态中最基础、最流行的 Web 框架,几乎所有的 Node.js 开发者都应该掌握它。

相关推荐
aini_lovee1 天前
Node.js 中的中间件机制与 Express 应用
中间件·node.js·express
桃子不吃李子5 天前
简单搭建express服务器
运维·服务器·express
书中自有妍如玉6 天前
Node.Js Express Sqlite3 接口开发
node.js·express
showmethetime7 天前
使用 Node.js 和 Express 构建 RESTful API
node.js·restful·express
2501_938780289 天前
《Node.js 面试考点精讲:Express 生态与常见问题解决方案》
面试·node.js·express
2501_938790079 天前
《Node.js 面试避坑:Express 常见问题误区与正确答案解析》
面试·node.js·express
2501_9387820911 天前
《Express 面试高频错题集:容易踩坑的 Node.js 后端问题解析》
面试·node.js·express
_光光13 天前
大文件上传服务实现(后端篇)
后端·node.js·express
正经教主16 天前
【Trae+AI】和Trae学习搭建App_03:后端API开发原理与实践(已了解相关知识的可跳过)
后端·express