第五节:管道中间件入门(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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2019-04-24 19:47 Yaopengfei 阅读(...) 评论(...) 编辑 收藏