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();
相关推荐
运维全栈笔记2 天前
Linux安装配置Tomcat保姆级教程:从部署到性能调优
linux·服务器·中间件·tomcat·apache·web
许长安2 天前
protobuf 使用详解
c++·经验分享·笔记·中间件
jeCA EURG4 天前
docker离线安装及部署各类中间件(x86系统架构)
docker·中间件·系统架构
许彰午5 天前
CacheSQL:一个面向政务系统的内存缓存数据库中间件
java·数据库·缓存·中间件·面试·开源软件·政务
亿牛云爬虫专家6 天前
Go爬虫进阶:如何优雅地在Colly框架中实现无缝代理切换?
爬虫·中间件·golang·爬虫代理·colly框架·代理切换·api提取
SuperherRo6 天前
服务攻防-中间件安全&Apache&Tomcat&Jetty&Weblogic&AJP协议&反序列化&CVE漏洞
中间件·tomcat·apache·jetty·weblogic
空中海6 天前
第四篇:进阶篇 — 缓存、消息队列、安全与常用中间件
安全·缓存·中间件
逍遥德7 天前
MQTT教程详解-03. 高级知识点
java·物联网·中间件·信息与通信·iot·iotdb
前端小超人rui7 天前
【Node.js Express中间件理解及中间件分类和作用】
中间件·node.js·express
前端小超人rui7 天前
封装Express 自定义中间件
中间件·node.js·express