第五节:管道中间件入门(Use、Run、Map)
一. 简介
1.中间件是一种装配到应用管道以处理请求和响应的组件,每个组件可以选择是否把请求传递到管道中的下一个组件、可在管道中的下一个组件的前后执行工作.请求管道中的每一个组件负责调用管道中的下一个组件(或者使管道短路).
经典的管道请求图:
2.当中间件短路的时候,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。
3.顺序:向Startup.Configure方法中添加常用中间件组件,需要按照下面的顺序,从而保证安全性、性能、功能。
异常/错误处理→ HTTP 严格传输安全协议→HTTPS 重定向→静态文件服务器→Cookie 策略实施→身份验证→会话→MVC。
1 public void Configure(IApplicationBuilder app) 2 { 3 if (env.IsDevelopment()) 4 { 5 app.UseDeveloperExceptionPage(); 6 app.UseDatabaseErrorPage(); 7 } 8 else 9 { 10 app.UseExceptionHandler("/Error"); 11 app.UseHsts(); 12 } 13 14 // Use HTTPS Redirection Middleware to redirect HTTP requests to HTTPS. 15 app.UseHttpsRedirection(); 16 17 // Return static files and end the pipeline. 18 app.UseStaticFiles(); 19 20 // Use Cookie Policy Middleware to conform to EU General Data 21 // Protection Regulation (GDPR) regulations. 22 app.UseCookiePolicy(); 23 24 // Authenticate before the user accesses secure resources. 25 app.UseAuthentication(); 26 27 // If the app uses session state, call Session Middleware after Cookie 28 // Policy Middleware and before MVC Middleware. 29 app.UseSession(); 30 31 // Add MVC to the request pipeline. 32 app.UseMvc(); 33 }
4.中间件的三大核心方法,分别是:Use、Run、Map.
二. Use方法
1. 用途:Use可以将多个中间件连接在一起,实现在下一个中间件的前后执行操作,Use方法也可以使管道短路,即不调用next请求委托,此时和Run的作用一样。
2. 查看Use方法的源代码,参数为:Func<HttpContext, Func<Task>, Task> middleware,可以参考自己封装一个中间件, 如:MyMiddleware。
代码分享:
1 /// <summary> 2 /// 自定义一个中间件 3 /// </summary> 4 public class MyMiddleware 5 { 6 public Task DelegateMiddleware(HttpContext context, Func<Task> next) 7 { 8 context.Response.WriteAsync("MyOwinMiddle Start<br/>"); 9 next.Invoke(); 10 return context.Response.WriteAsync("MyOwinMiddle End<br/>"); 11 } 12 } 13 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 14 { 15 //1. Use用法 16 { 17 app.Use(async (context, next) => 18 { 19 await context.Response.WriteAsync("First Start<br/>"); 20 //调用下一个中间件 21 await next.Invoke(); 22 await context.Response.WriteAsync("First End<br/>"); 23 }); 24 app.Use(async (context, next) => 25 { 26 await context.Response.WriteAsync("Second Start<br/>"); 27 //调用下一个中间件 28 await next.Invoke(); 29 await context.Response.WriteAsync("Second End<br/>"); 30 }); 31 //调用封装后的中间件 32 MyMiddleware myMiddleware = new MyMiddleware(); 33 app.Use(myMiddleware.DelegateMiddleware); 34 35 //没有调用next,它在此处的作用是使管道短路 36 app.Use(async (context, next) => 37 { 38 await context.Response.WriteAsync("Third Start<br/>"); 39 await context.Response.WriteAsync("Third End<br/>"); 40 }); 41 42 } 43 }
运行结果及分析:执行到next.Invoke(),调用下一个中间件。
三. Run方法
1. Run是一种约定,在某些中间件的可公开的管道末尾运行Run[Middleware]方法,表示终止请求。
代码分享:
1 //2. Run用法 2 { 3 app.Run(async context => 4 { 5 await context.Response.WriteAsync("First Start<br/>"); 6 await context.Response.WriteAsync("First End<br/>"); 7 }); 8 //不能执行下面代码,因为第一个Run直接终止了管道 9 app.Run(async context => 10 { 11 await context.Response.WriteAsync("Second Start<br/>"); 12 await context.Response.WriteAsync("Second End<br/>"); 13 }); 14 }
运行结果:
四. Map和MapWhen方法
1. 当请求满足某种规则,执行某个中间件,下面分享Map和MapWhen的代码
代码分享:
1 //3. Map用法 2 { 3 //http://localhost:5000/map1 访问 4 app.Map("/map1", appBulider => appBulider.Run(async context => 5 { 6 await context.Response.WriteAsync("This is Map1<br/>"); 7 })); 8 //http://localhost:5000/map2 访问 9 app.Map("/map2", appBulider => appBulider.Run(async context => 10 { 11 await context.Response.WriteAsync("This is Map2<br/>"); 12 })); 13 //当没有map1和map2的时候,访问下面的中间件 14 app.Run(async context => 15 { 16 await context.Response.WriteAsync("Hello from non-Map delegate. <p>"); 17 }); 18 } 19 20 //4. MapWhen用法 21 { 22 //http://localhost:5000/?userName=ypf 访问 23 app.MapWhen(context => context.Request.Query.ContainsKey("userName"), 24 appBulider => appBulider.Run(async context => 25 { 26 var value = context.Request.Query["userName"]; 27 await context.Response.WriteAsync($"this value is {value}"); 28 })); 29 //没有拼接的时候访问下面 30 app.Run(async context => 31 { 32 await context.Response.WriteAsync("Hello from non-Map delegate. <p>"); 33 }); 34 }
运行结果分析:如上述代码中的描述。
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。