網(wǎng)站首頁 編程語言 正文
前言
ASP.NET Core 中 HTTP 管道使用中間件組合處理的方式,
換句人話來說,
對于寫代碼的人而言,一切皆中間件.
業(yè)務邏輯/數(shù)據(jù)訪問/等等一切都需要以中間件的方式來呈現(xiàn).
那么我們必須學會如何實現(xiàn)自定義中間件?這里劃重點,必考
這里我們介紹下中間件的幾種實現(xiàn)方式...
匿名函數(shù)
通常新建一個空的 ASP.NET Core Web Application,項目名字無所謂啦
在啟動類里可以看到這么一句:
// Startup.cs // ... app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); // ...
這就是一個匿名函數(shù)實現(xiàn)的中間件,雖然內(nèi)容比較少.
可以看到通過匿名函數(shù)實現(xiàn)的中間件是內(nèi)嵌在啟動類文件中的,因此通常也叫做內(nèi)聯(lián)中間件
接下來,我們通過匿名函數(shù)來實現(xiàn)內(nèi)聯(lián)中間件,以便加深理解.
然后修改啟動類代碼如下:
// Startup.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System; namespace WebApplication1 { public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 使用匿名函數(shù)實現(xiàn)一個內(nèi)聯(lián)中間件 app.Use(async (context, next) => { throw new NotImplementedException("一個使用匿名函數(shù),但未實現(xiàn)具體內(nèi)容的內(nèi)聯(lián)中間件"); }); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
這里我們在?app.Run
?之前使用?app.Use
?添加一個匿名函數(shù)實現(xiàn)的內(nèi)聯(lián)中間件,按照中間件的注冊順序,當發(fā)起請求時,會拋出一個異常?NotImplementedException("一個使用匿名函數(shù),但未實現(xiàn)具體內(nèi)容的內(nèi)聯(lián)中間件")
我們 F5 啟動下,看看頁面
嗯,符合預期.
我們再來調(diào)整下啟動類,代碼如下:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; namespace WebApplication1 { public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 使用匿名函數(shù)實現(xiàn)一個內(nèi)聯(lián)中間件 app.Use(async (context, next) => { // 這里不對 request 做任何處理,直接調(diào)用下一個中間件 await next.Invoke(); }); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
這里我們在?app.Run
?之前使用?app.Use
?添加一個匿名函數(shù)實現(xiàn)的內(nèi)聯(lián)中間件,該中間件沒有對 request 做任何處理,只是一個空的空間件,按照中間件的注冊順序,當發(fā)起請求時,頁面應該顯示?Hello World!
.
我們 F5 啟動,看看效果
嗯,符合預期.
個人覺得:匿名函數(shù)不是很直觀,但是用內(nèi)聯(lián)的方式可以快速開始一些開發(fā),不用新建一個中間件類,不用專門想個不一樣的名字,小場景下是非常方便實用的
實現(xiàn)接口
通過實現(xiàn)接口?IMiddleware
?編寫自定義中間件,這是一種強類型的方式,我們需要必須強制按照接口的定義來實現(xiàn).
IMiddleware
接口 IMiddleware 定義如下:
using System.Threading.Tasks; namespace Microsoft.AspNetCore.Http { public interface IMiddleware { Task InvokeAsync(HttpContext context, RequestDelegate next); } }
可以看到接口 IMiddleware 的命名空間是?Microsoft.AspNetCore.Http
,需要實現(xiàn)的方法是InvokeAsync()
,看起來不算太復雜,?嗯,看起來不算太復雜
嗯,重新開始,我們新建一個空的 ASP.NET Core Web Application
然后我們通過實現(xiàn)接口的方式來自定義一個中間件,代碼如下:
// 新建類 MyMiddleware.cs using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace WebApplication1 { public class MyMiddleware : IMiddleware { public Task InvokeAsync(HttpContext context, RequestDelegate next) { throw new NotImplementedException(); } } }
按照上面實現(xiàn)的中間件?MyMiddleware
,在執(zhí)行時應該會拋出?NotImplementedException
.
使用接口實現(xiàn)的中間件需要在先在服務容器中注冊
// Startup.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; namespace WebApplication1 { public class Startup { public void ConfigureServices(IServiceCollection services) { // 在服務容器中注冊自定義中間件 services.AddSingleton<MyMiddleware>(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 使用 UseMiddleware() 把自定義中間件添加到管道中 app.UseMiddleware<MyMiddleware>(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
然后 F5 啟動,頁面上可以看到如下結(jié)果:
符合我們上面的預期,拋出了一個?NotImplementedException
.
然后我們改造下?MyMiddleware
?中間件
// MyMiddleware.cs using Microsoft.AspNetCore.Http; using System.Threading.Tasks; namespace WebApplication1 { public class MyMiddleware : IMiddleware { public async Task InvokeAsync(HttpContext context, RequestDelegate next) { // 這里不對 request 做任何處理,直接調(diào)用下一個中間件 await next(context); } } }
這里相當于我們實現(xiàn)了一個叫做?MyMiddleware
?的中間件,但是并沒有對請求進行任何處理,頁面上應該正常顯示?Hello World!
?字符串.
然后我們 F5 啟動看看
嗯...符合預期.
個人覺得:這種方式最符合面向?qū)ο蟮奶匦?也符合面向接口的原則,少一些難以理解的魔法,反而有助于理解.
約定方式
編程世界有這么一句話,叫"約定大于配置".
那么編寫中間件的約定是什么呢?
重新開始,新建一個空的 ASP.NET Core Web Application
然后新建一個類,類名叫做?MyMiddleware
?好了,代碼如下:
// MyMiddleware.cs using Microsoft.AspNetCore.Http; using System; using System.Threading.Tasks; namespace WebApplication1 { public class MyMiddleware { // 1. 需要實現(xiàn)一個構造函數(shù),參數(shù)為 RequestDelegate public MyMiddleware(RequestDelegate next) { } // 2. 需要實現(xiàn)一個叫做 InvokeAsync 方法 public async Task InvokeAsync(HttpContext context) { throw new NotImplementedException("這是一個按照約定方式編寫的中間件,但未實現(xiàn)具體內(nèi)容"); } } }
約定的內(nèi)容,就是滿足2個需要...不滿足需要則異常.
然后我們把這個中間件,注冊到管道中,以便使用
// Startup.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; namespace WebApplication1 { public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 注冊自定義中間件 // 注冊順序=1 app.UseMiddleware<MyMiddleware>(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
然后 F5 啟動,來看看效果
嗯,符合預期.
然后我們來調(diào)整下中間件,讓請求能正常響應輸出?Hello World!
using Microsoft.AspNetCore.Http; using System; using System.Threading.Tasks; namespace WebApplication1 { public class MyMiddleware { private readonly RequestDelegate _next; // 需要實現(xiàn)一個構造函數(shù),參數(shù)為 RequestDelegate public MyMiddleware(RequestDelegate next) { _next = next; } // 需要實現(xiàn)一個叫做 InvokeAsync 方法 public async Task InvokeAsync(HttpContext context) { // 不處理任何 request, 直接調(diào)用下一個中間件 await _next.Invoke(context); } } }
然后 F5 啟動,看看效果
嗯,符合預期.
個人覺得:只能說一句,約定方式是目前用的最多的方式...
End
寫在最后
Tips: 有些內(nèi)容可能看起來還是不太容易理解,至少當下你是很難理解的,但是套路就在哪里,好比1+1=2,你知道1+1為什么=2么?但你一定會算會用1+1=2...
原文鏈接:https://www.cnblogs.com/taadis/p/12148859.html
相關推薦
- 2024-01-11 String數(shù)組轉(zhuǎn)List的三種方式
- 2023-01-14 ubuntu開機后ROS程序自啟動問題_Linux
- 2022-05-11 使用postman訪問k8s api
- 2022-07-06 React創(chuàng)建對話框組件的方法實例_React
- 2022-12-10 Android入門之日歷選擇與時間選擇組件的使用_Android
- 2022-03-30 C語言實現(xiàn)猜數(shù)字小項目_C 語言
- 2022-08-28 解決ffmpeg讀取視頻流時,報錯“Segmentation fault (core dumped)
- 2022-04-09 C#實現(xiàn)計算器精簡版_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支