当定义多个中间件
标签:
web框架中间件比拟编程语言都有所差别,各个语言解决同一类问题而设计的框架,,确有共通之处,终究是解决同一类问题,面临的挑战大抵不异,好比身份验证,api授权等等,在下对node.js,golang,.net core有所涉猎,对各自的web框架进行学习的过程中发明了确实有相似之处。下面即对node.js的koa、golang的gin与.net core的asp.net core三种差此外web后端框架的中间件做一个分析比拟
Node-Koa.js 应用级中间件 //如果不写next,就不会向下匹配--匹配任何一个路由 app.use(async(ctx,next)=>{ console.log(new Date()) await next(); }) 路由级中间件 router.get('/news',async(ctx,next)=>{ console.log("this is news") await next(); }) 错误措置惩罚惩罚中间件 app.use(async(ctx,next)=>{ //应用级中间件 都需要执行 /* 1.执行若干代码 */ next();//2.执行next() 匹配其他路由 //4.再执行 if(ctx.status==404){ ctx.status=404 ctx.body="这是一个404" }else{ console.log(ctx.url) } }) //3.匹配下面的路由 router.get('/news',async(ctx)=>{ console.log("this is news") ctx.body="这是一个新闻页面" }) 第三方中间件静态资源中间件为例:静态资源地点没有路由匹配,盲目引入静态资源,会报404.
//安置 npm install koa-static --save //使用 //引入 const static=require('koa-static') //使用 app.use(static('static')) //去static文件目录中将中找文件,如果能找到对应的文件,找不到就next() app.use(static(__dirname+'/static')) app.use(static(__dirname+'/public')) 中间件执行挨次洋葱执行:从上到下依次执行,匹配路由响应,再返回至中间件进行执行中间件,【先从外向内,然后再从内向外】
Golang-Gin钩子(Hook)函数,中间件函数
界说中间件 package main import( "github.com/gin-gonic/gin" ) func main(){ r:=gin.Default() r.GET("/index",func(c *gin.Context){ //... }) r.Run() } func m1(c *gin.Context){ fmt.Println("中间件m1") c.Next()//挪用后续的措置惩罚惩罚函数 //c.Abort()//阻止挪用后续的措置惩罚惩罚函数 fmt.Println("m1 out...") } 注册中间件 全局注册-某个路由单独注册-路由组注册 package main import( "github.com/gin-gonic/gin" ) func main(){ r:=gin.Default() r.GET("/index",func(c *gin.Context){ //... }) //某个路由单独注册--也可以取名为路由级注册中间件 r.GET("/test1",m1,func(c *gin.Context){ //... }) //路由组注册 xxGroup:=r.Group("/xx",m1) { xxGroup.GET("/index",func(c *gin.Context){ //... }) } xx2Group:=r.Group("/xx2") xx2Group.Use(m1) { xxGroup.GET("/index",func(c *gin.Context){ //... }) } r.Run() r.GET("/index",m1) } func m1(c *gin.Context){ fmt.Println("中间件m1") c.Next()//挪用后续的措置惩罚惩罚函数 //c.Abort()//阻止挪用后续的措置惩罚惩罚函数 //return 连下方的fmt.Println都不执行了,当即返回 fmt.Println("m1 out...") } r.Use(m1)//全局注册 //多其中间件注册 r.Use(m1,m2) 中间件执行挨次与koa中间件执行挨次一致
中间件凡是写法-闭包 func authMiddleware(doCheck bool) gin.HandlerFunc{ //连接数据库 //或筹备事情 return func(c *gin.Context){ //是否登录判断 //if是登录用户 //c.Next() //else //c.Abort() } } 中间件通信 func m1(c *gin.Context){ fmt.Println("m1 in ...") start := time.Now() c.Next() cost:=time.Since(start) fmt.Printf("cost:%v\n",cost) fmt.Println("m1 out...") } func m2(c *gin.Context){ fmt.Println("m2 in...") //中间件存值 c.Set("name","carfield") fmt.Println("m2 out...") //其他中间件取值 // c.Get // c.MustGet } 中间件中使用goroutine当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context) 必需使用其只读副本c.Copy(),否则会呈现线程安适问题。
.Net Core-Asp.net core 创建中间件管道使用IApplicationBuilder 创建中间件管道
//Run public class Startup { public void Configure(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Hello, World!"); }); } } //Use - Run public class Startup { public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); } } //这个Use是不是跟koa的应用级中间件很像 创建中间件管道分支Map 扩展用作约定来创建管道分支。 Map 基于给定请求路径的匹配项来创建请求管道分支。 如果请求路径以给定路径开头,则执行分支。koa和gin中路由匹配就是map这种,当不使用内置的mvc模板路由,我临时称它为自界说路由
public class Startup { private static void HandleMapTest1(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 1"); }); } private static void HandleMapTest2(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 2"); }); } public void Configure(IApplicationBuilder app) { app.Map("/map1", HandleMapTest1); app.Map("/map2", HandleMapTest2); app.Run(async context => { await context.Response.WriteAsync("Hello from non-Map delegate. <p>"); }); } //请求会匹配 map1...map2...没匹配到路由的统统会执行app.Run } //像golang的gin一样,map也撑持嵌套 app.Map("/level1", level1App => { level1App.Map("/level2a", level2AApp => { // "/level1/level2a" processing }); level1App.Map("/level2b", level2BApp => { // "/level1/level2b" processing }); }); public class Startup { private static void HandleMultiSeg(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map multiple segments."); }); } public void Configure(IApplicationBuilder app) { app.Map("/map1/seg1", HandleMultiSeg); app.Run(async context => { await context.Response.WriteAsync("Hello from non-Map delegate."); }); } } //MapWhen 基于给定谓词的功效创建请求管道分支。 Func<HttpContext, bool> 类型的任何谓词均可用于将请求映射到管道的新分支。 在以下示例中,谓词用于检测盘问字符串变量 branch 是否存在: public class Startup { private static void HandleBranch(IApplicationBuilder app) { app.Run(async context => { var branchVer = context.Request.Query["branch"]; await context.Response.WriteAsync($"Branch used = {branchVer}"); }); } public void Configure(IApplicationBuilder app) { app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch); app.Run(async context => { await context.Response.WriteAsync("Hello from non-Map delegate. <p>"); }); } } //UseWhen 也是基于给定谓词的功效创建请求管道分支。 与 MapWhen 差此外是,如果这个分支产生短路或包罗终端中间件,则会从头插手主管道: public class Startup { private readonly ILogger<Startup> _logger; public Startup(ILogger<Startup> logger) { _logger = logger; } private void HandleBranchAndRejoin(IApplicationBuilder app) { app.Use(async (context, next) => { var branchVer = context.Request.Query["branch"]; _logger.LogInformation("Branch used = {branchVer}", branchVer); // Do work that doesn't write to the Response. await next(); // Do other work that doesn't write to the Response. }); } public void Configure(IApplicationBuilder app) { app.UseWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranchAndRejoin); app.Run(async context => { await context.Response.WriteAsync("Hello from main pipeline."); }); } } 内置中间件 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { //开发人员异常页中间件 呈报应用运行时错误 app.UseDeveloperExceptionPage(); //数据库错误页中间件呈报数据库运行时错误 app.UseDatabaseErrorPage(); } else { //异常措置惩罚惩罚措施中间件 app.UseExceptionHandler("/Error"); //http严格传输安适协议中间件 app.UseHsts(); } //HTTPS重定向中间件 app.UseHttpsRedirection(); //静态文件中间件 app.UseStaticFiles(); //Cookie计谋中间件 app.UseCookiePolicy(); //路由中间件 app.UseRouting(); //身份验证中间件 app.UseAuthentication(); //授权中间件 app.UseAuthorization(); //会话中间件-如果使用session,就需要把cookie计谋中间件先使用了,再引入session中间件,再引入mvc中间件,终究session是依赖cookie实现的 app.UseSession(); //终结点路由中间件 app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); } 自界说中间件 在Configure中直接写 //在Startup.Configure直接编码 public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { //做一些操纵 // Call the next delegate/middleware in the pipeline await next(); }); app.Run(async (context) => { await context.Response.WriteAsync( $"Hello world"); }); } 中间件类+中间件扩展要领+UseXX温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30589.html