中间件是什么?什么场景使用?

🥷 一、什么是中间件?

中间件就像一条跑道上的检查点

  • 选手(请求 request)跑进来 → 先经过几个检查点(中间件)
  • 每个检查点都可以干点事:查身份证(鉴权)、量血压(数据校验)、拍个照(日志)
  • 最后才到达终点(业务逻辑 Controller)

👉 所以:中间件 = 在请求到达核心逻辑之前/之后插入的一段可复用的小程序


🚦 二、适用场景

中间件特别适合解决"通用但非业务"的问题(专业说法叫 横切关注点 cross-cutting concerns)。

常见的场景有:

  1. 安全保镖类 🛡️

    • 登录校验、权限验证
    • 限流(防止一个人疯狂刷接口)
  2. 服务员类 🍽️

    • 给数据配套餐具(格式化响应,比如统一返回 { code, data, message }
    • CORS 处理(跨域服务)
  3. 记录员类 📒

    • 日志打印(谁在什么时候访问了什么接口)
    • 性能监控(统计耗时)
  4. 修理工类 🔧

    • 捕获错误,统一返回用户友好的信息
    • 请求数据预处理(比如 JSON → 对象,表单 → 参数)

💻 三、代码举例(Express 中间件)

用 Node.js 的 Express 举例,超级直观:

scss 复制代码
const express = require('express');
const app = express();

// 1️⃣ 日志中间件:像"监控摄像头"
function logger(req, res, next) {
  console.log(`[LOG] ${req.method} ${req.url}`);
  next(); // 🚦 放行,交给下一个中间件
}

// 2️⃣ 鉴权中间件:像"门口保安"
function auth(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).json({ message: '❌ 未授权' });
  }
  console.log('✅ 授权通过');
  next();
}

// 3️⃣ 统一响应格式中间件:像"餐厅出菜时统一装盘"
function formatResponse(req, res, next) {
  // 重写 res.send 方法
  const oldSend = res.send;
  res.send = function (data) {
    oldSend.call(res, {
      code: 0,
      message: 'success',
      data: data
    });
  };
  next();
}

// 注册中间件(顺序很重要!)
app.use(logger);
app.use(auth);
app.use(formatResponse);

// 核心业务逻辑
app.get('/hello', (req, res) => {
  res.send({ greeting: 'Hello Middleware!' });
});

app.listen(3000, () => {
  console.log('🚀 Server running on http://localhost:3000');
});

执行流程

👉 请求 GET /hello 时:
logger → auth → formatResponse → /hello 控制器 → formatResponse 加工响应 → 返回客户端

就像一条流水线,每个工人(中间件)负责一道工序。


🎯 四、总结

  • 定义:中间件就是请求和业务之间的"拦截器 + 工具人",负责做通用的脏活累活。
  • 适用场景:日志、鉴权、数据预处理、错误捕获、统一响应、跨域......这些和业务没直接关系,但又少不了的地方。
  • 核心价值:让业务逻辑更干净,通用逻辑可复用,可插拔。

流程图(请求 → 多个中间件 → 控制器 → 响应) ,更直观地看到中间件像是"安检流程"的感觉 这就是中间件的流程图 🖼️:

明白啦 👍

我直接给你画出一张清晰的中间件执行流程图(请求和响应都有):

vbscript 复制代码
          ┌───────────────┐
          │   请求 Request │
          └───────┬───────┘
                  │
                  ▼
        ┌─────────────────┐
        │  中间件① 日志    │
        └───────┬─────────┘
                  │
                  ▼
        ┌─────────────────┐
        │  中间件② 鉴权    │
        └───────┬─────────┘
                  │
                  ▼
        ┌────────────────────┐
        │  中间件③ 格式化响应 │
        └───────┬────────────┘
                  │
                  ▼
        ┌───────────────────┐
        │   业务逻辑 Controller │
        └───────┬───────────┘
                  │
         (执行业务并生成响应)
                  │
                  ▼
        ┌────────────────────┐
        │  中间件③ 格式化响应 │
        └───────┬────────────┘
                  │
                  ▼
        ┌─────────────────┐
        │  中间件② 鉴权    │
        └───────┬─────────┘
                  │
                  ▼
        ┌─────────────────┐
        │  中间件① 日志    │
        └───────┬─────────┘
                  │
                  ▼
          ┌───────────────┐
          │   响应 Response │
          └───────────────┘

🔵 ①->③ 方向:请求进来时依次经过各个中间件 → 业务逻辑。

🔴 ③->① 方向:响应出来时再倒序经过中间件 → 返回给客户端。

这样可以看到中间件不仅能预处理请求 ,还能后处理响应

相关推荐
花花无缺8 小时前
`api`、`common`、`service`、`web` 分层架构设计
java·后端
Code_Artist8 小时前
说说恶龙禁区Unsafe——绕过静态类型安全检查&直接操作内存的外挂
java·后端·操作系统
二闹8 小时前
别再用错了!深入扒一扒Python里列表和元组那点事
后端·python
编程乐趣9 小时前
基于.Net开发的数据库导入导出的开源项目
后端
赵星星5209 小时前
别再搞混了!深入浅出理解Java线程中start()和run()的本质区别
java·后端
Ray669 小时前
FST
后端
白露与泡影9 小时前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端·sql
花花无缺9 小时前
接口(interface)中的常量和 类(class)中的常量的区别
java·后端
舒一笑10 小时前
利用Mybatis自定义排序规则实现复杂排序
后端·排序算法·mybatis