Day10:ASP.NET Core 管道与中间件

一、今日学习目标

  1. 理解 请求管道 执行顺序
  2. 掌握 Use / Run / Map 区别
  3. 学会 自定义中间件
  4. 写两个企业常用中间件:
    • 请求日志中间件
    • 简单权限校验中间件

二、核心面试题 + 标准答案

1. 什么是 ASP.NET Core 管道?

答案: HTTP 请求从进入到响应离开,经过的一系列中间件组件 叫请求管道。请求依次经过中间件,响应原路返回,类似俄罗斯套娃

2. Use / Run / Map 区别(高频必问)

  • Use :注册中间件,可以交给下一个 (调用 await next()
  • Run终端中间件 ,执行后直接返回,不往后走
  • Map :按路径分支,匹配某个路径才执行

3. 中间件执行顺序?

**答案:**配置顺序 = 执行顺序。先注册的先接收请求,后响应。

4. 中间件 vs 过滤器?

  • 中间件:全局,针对所有请求,更底层
  • 过滤器:针对 Controller/Action,属于 MVC 框架
  • 性能:中间件更高

5. 中间件生命周期?

答案: 默认 Singleton ,所以不要在中间件里写 Scoped 服务 ,要用 IServiceProvider 手动创建作用域获取。

6. 自定义中间件两种方式?

  1. 匿名委托(app.Use
  2. 独立类(RequestMiddleware,标准企业写法)

三、核心语法速记

cs 复制代码
// 分支
app.Map("/test", builder => builder.Run(...));

// 短路
app.Run(async context => await context.Response.WriteAsync("end"));

// 标准中间件
app.Use(async (context, next) =>
{
    // 请求前
    await next();
    // 响应后
});

四、Day10 实战练习(必须完成)

练习 1:请求日志中间件

  • 记录:请求路径、方法、耗时、状态码
  • 输出到控制台 / Serilog

练习 2:简单权限校验中间件

  • 判断请求头是否包含 Token: admin
  • 没有则直接返回 401
  • 有则继续执行后续管道

四、练习代码

WeatherController.cs

cs 复制代码
[ApiController]
[Route("api/[controller]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok("正常接口数据");
    }

    [HttpPost("login")]
    public IActionResult Login()
    {
        return Ok("登录成功,返回 Token:admin");
    }
}

appsettings.json

cs 复制代码
"Serilog": {
  "MinimumLevel": {
    "Default": "Debug",
    "Override": {
      "Microsoft": "Warning",
      "System": "Warning"
    }
  },
  "WriteTo": [
    { "Name": "Console" },
    {
      "Name": "File",
      "Args": {
        //文件保存路径及文件名
        "path": "Logs/log-.txt",
        //滚动策略:以天为单位,每天生成一个新日志文件,如 log-20260410.log
        "rollingInterval": "Day",
        //输出模板:2026-04-10 12:54:27 [DBG] 调试日志:服务启动成功
        "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss}[{Level:u3}]{Message:lj}{NewLine}{Exception}"
      }
    }
  ]
}

Program.cs

cs 复制代码
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

// ==========================
// 1. 日志中间件(Use)
//  记录:请求路径、方法、耗时、状态码
//  输出到控制台 / Serilog
// ==========================
app.Use(async (context, next) =>
{
    // 请求前
    var path = context.Request.Path;
    var method = context.Request.Method;
    var start = DateTime.UtcNow;    //开始时间

    Console.WriteLine($"[请求进入] {method} {path}");

    await next();// 调用下一个中间件

    // 响应后
    var cost = (DateTime.UtcNow - start).TotalMilliseconds; //计算耗时
    var code = context.Response.StatusCode;                 //响应状态
    Console.WriteLine($"[请求结束] {method} {path} | 状态码:{code} | 耗时:{cost:F2}ms");
});

// ==========================
// 2. 权限校验中间件
//  判断请求头是否包含 Token: admin
//  没有则直接返回 401
//  有则继续执行后续管道
// ==========================
app.Use(async (context, next) =>
{
    var path = context.Request.Path;
    
    // 登录接口不校验
    if (path.StartsWithSegments("/api/weather/login"))  //StartsWithSegments:用于‌按路径段(segment)精确匹配 URL 前缀‌的方法,常用于中间件、路由或 API 版本控制等场景。
    {
        await next();
        return;
    }

    var token = context.Request.Headers["Token"].FirstOrDefault();

    if (token != "admin") 
    {
        context.Response.StatusCode = 401;
        await context.Response.WriteAsync("无权限,请在请求头带 Token:admin");
        return; //短路不往后走
    }
    await next();

});


// ==========================
// 3. Map 分支演示
// ==========================
app.Map("/begin", x =>
{
    x.Run(async c =>
    {
        await c.Response.WriteAsync("Hello from Map");
    });
});

// ==========================
// 4. Run 终端中间件
// ==========================
app.Map("/end", x =>
{
    x.Run(async c => await c.Response.WriteAsync("This is the end."));
});

app.MapControllers();
app.Run();
相关推荐
We་ct5 小时前
JS手撕:手写Koa中间件与Promise核心特性
开发语言·前端·javascript·中间件·node.js·koa·co
Meme Buoy3 天前
13.6其他架构评估方法-中间件
中间件·架构
我是李龙4 天前
第二十六章 全链路监控体系: 服务器资源、中间件状态与业务指标的可视化大屏开发
中间件
别抢我的锅包肉5 天前
FastAPI + Vue3 + Vite 跨域报错全解:从 `Access-Control-Allow-Origin missing` 到彻底修复
中间件·状态模式·fastapi
爱吃烤鸡翅的酸菜鱼5 天前
Java 事件发布-订阅机制全解析:从原生实现到主流中间件
java·中间件·wpf·事件·发布订阅
my_styles5 天前
linux系统下安装 tengine / 宝兰德等国产信创中间件和闭坑
linux·运维·服务器·spring boot·nginx·中间件
ZHENGZJM5 天前
Gin 鉴权中间件设计与实现
中间件·gin
开心码农1号5 天前
mq是什么,常用mq的使用场景有哪些?
中间件·rabbitmq
斌味代码5 天前
Next.js 14 App Router 完全指南:服务端组件、流式渲染与中间件实战
开发语言·javascript·中间件