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();
相关推荐
一拳一个娘娘腔20 小时前
【SRC漏洞挖掘系列】第13期:云安全与中间件 —— 站在云端的“上帝视角”
安全·中间件
我叫张小白。20 小时前
基于Redis与FastAPI的分布式共享会话体系
数据库·redis·分布式·缓存·中间件·fastapi·依赖注入
woniu_buhui_fei3 天前
常用分布式中间件一览
分布式·中间件
数据库小学妹3 天前
ProxySQL选型实战:从手写读写分离到中间件的踩坑全记录
数据库·sql·中间件
fengxin_rou3 天前
【后端配置模块实战】:索引、中间件与缓存架构全解析
缓存·中间件·架构
dinl_vin4 天前
FastAPI 系列 ·(九):中间件与错误处理:让服务更健壮
中间件·状态模式·fastapi
学无止境_永不停歇5 天前
从零手写高性能 C++ TCP 服务器框架(二):名词介绍
服务器·网络·c++·tcp/ip·中间件
学无止境_永不停歇6 天前
从零手写高性能 C++ TCP 服务器框架(一):项目介绍
linux·服务器·c++·中间件
哎呦,帅小伙哦7 天前
Nanomsg中间件utils中部分工具学习记录
学习·中间件·nanomsg