Skip to content

Express 框架学习笔记

Express 简介

Express 是 Node.js 最流行的 Web 应用框架,提供了构建 Web 应用和 API 的简洁而强大的功能。

安装 Express

bash
npm init -y
npm install express

创建第一个 Express 应用

javascript
const express = require('express');
const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
  res.send('Hello, Express!');
});

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

路由

基本路由

javascript
// GET 请求
app.get('/users', (req, res) => {
  res.send('获取用户列表');
});

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

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

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

路由参数

javascript
// 单个参数
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.send(`用户 ID: ${userId}`);
});

// 多个参数
app.get('/users/:userId/posts/:postId', (req, res) => {
  const { userId, postId } = req.params;
  res.send(`用户 ${userId} 的帖子 ${postId}`);
});

// 可选参数
app.get('/users/:id?', (req, res) => {
  const userId = req.params.id || 'all';
  res.send(`用户: ${userId}`);
});

查询字符串

javascript
// GET /search?q=nodejs&page=1
app.get('/search', (req, res) => {
  const query = req.query.q;
  const page = req.query.page || 1;
  res.send(`搜索: ${query}, 页码: ${page}`);
});

路由模块化

javascript
// 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);

中间件

什么是中间件

中间件是在请求和响应之间执行的函数,可以访问请求对象、响应对象和下一个中间件函数。

自定义中间件

javascript
// 日志中间件
const logger = (req, res, next) => {
  console.log(`${req.method} ${req.url} - ${new Date()}`);
  next(); // 调用下一个中间件
};

app.use(logger);

// 时间戳中间件
app.use((req, res, next) => {
  req.requestTime = Date.now();
  next();
});

app.get('/', (req, res) => {
  res.send(`请求时间: ${req.requestTime}`);
});

内置中间件

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

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

// 提供静态文件
app.use(express.static('public'));

// 示例:处理 POST 请求
app.post('/users', express.json(), (req, res) => {
  const userData = req.body;
  res.json({ message: '用户创建成功', user: userData });
});

第三方中间件

javascript
// 安装: npm install morgan
const morgan = require('morgan');
app.use(morgan('dev')); // 日志中间件

// 安装: npm install cors
const cors = require('cors');
app.use(cors()); // 跨域中间件

// 安装: npm install helmet
const helmet = require('helmet');
app.use(helmet()); // 安全中间件

错误处理中间件

javascript
// 错误处理中间件(必须放在最后)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    error: '服务器内部错误',
    message: err.message
  });
});

// 使用示例
app.get('/error', (req, res, next) => {
  const err = new Error('测试错误');
  next(err); // 传递给错误处理中间件
});

请求和响应对象

请求对象(req)

javascript
app.get('/example', (req, res) => {
  // 请求方法
  console.log(req.method); // GET
  
  // 请求 URL
  console.log(req.url); // /example
  console.log(req.path); // /example
  console.log(req.originalUrl); // /example?query=value
  
  // 请求头
  console.log(req.headers);
  console.log(req.get('Content-Type'));
  
  // 查询参数
  console.log(req.query);
  
  // 路由参数
  console.log(req.params);
  
  // 请求体(需要中间件解析)
  console.log(req.body);
  
  // IP 地址
  console.log(req.ip);
});

响应对象(res)

javascript
app.get('/response', (req, res) => {
  // 发送文本
  res.send('Hello');
  
  // 发送 JSON
  res.json({ message: 'Success' });
  
  // 设置状态码
  res.status(404).send('Not Found');
  
  // 设置响应头
  res.set('Content-Type', 'text/plain');
  res.set({
    'X-Custom-Header': 'value',
    'Another-Header': 'another-value'
  });
  
  // 重定向
  res.redirect('/other-route');
  res.redirect(301, '/permanent-redirect');
  
  // 发送文件
  res.sendFile('/path/to/file.html');
  
  // 下载文件
  res.download('/path/to/file.pdf');
  
  // 设置 Cookie
  res.cookie('name', 'value', { maxAge: 900000 });
  
  // 清除 Cookie
  res.clearCookie('name');
});

模板引擎

使用 EJS

bash
npm install ejs
javascript
// 设置模板引擎
app.set('view engine', 'ejs');
app.set('views', './views');

// 渲染模板
app.get('/', (req, res) => {
  res.render('index', {
    title: '首页',
    users: ['John', 'Jane', 'Bob']
  });
});
html
<!-- 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>

文件上传

使用 multer

bash
npm install multer
javascript
const multer = require('multer');
const path = require('path');

// 配置存储
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({ storage: storage });

// 单文件上传
app.post('/upload', upload.single('avatar'), (req, res) => {
  res.json({ message: '文件上传成功', file: req.file });
});

// 多文件上传
app.post('/upload-multiple', upload.array('photos', 10), (req, res) => {
  res.json({ message: '文件上传成功', files: req.files });
});

RESTful API 示例

javascript
// 模拟数据
let users = [
  { id: 1, name: 'John', email: 'john@example.com' },
  { id: 2, name: 'Jane', email: 'jane@example.com' }
];

// 获取所有用户
app.get('/api/users', (req, res) => {
  res.json(users);
});

// 获取单个用户
app.get('/api/users/: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);
});

// 创建用户
app.post('/api/users', express.json(), (req, res) => {
  const { name, email } = req.body;
  const newUser = {
    id: users.length + 1,
    name,
    email
  };
  users.push(newUser);
  res.status(201).json(newUser);
});

// 更新用户
app.put('/api/users/:id', express.json(), (req, res) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (!user) {
    return res.status(404).json({ error: '用户不存在' });
  }
  Object.assign(user, req.body);
  res.json(user);
});

// 删除用户
app.delete('/api/users/:id', (req, res) => {
  const index = users.findIndex(u => u.id === parseInt(req.params.id));
  if (index === -1) {
    return res.status(404).json({ error: '用户不存在' });
  }
  users.splice(index, 1);
  res.status(204).send();
});

最佳实践

项目结构

project/
├── app.js
├── package.json
├── routes/
│   ├── index.js
│   ├── users.js
│   └── posts.js
├── controllers/
│   ├── userController.js
│   └── postController.js
├── models/
│   ├── User.js
│   └── Post.js
├── middleware/
│   ├── auth.js
│   └── errorHandler.js
└── public/
    ├── css/
    ├── js/
    └── images/

环境变量

bash
npm install dotenv
javascript
// .env
PORT=3000
NODE_ENV=development
DB_URL=mongodb://localhost:27017/mydb

// app.js
require('dotenv').config();
const PORT = process.env.PORT || 3000;

总结

Express 框架核心要点:

  • 路由:定义 HTTP 方法和路径处理
  • 中间件:处理请求和响应的函数
  • 请求响应:req 和 res 对象的使用
  • 模板引擎:渲染动态页面
  • 文件上传:使用 multer 处理文件
  • RESTful API:构建 RESTful 风格的 API