系列目录

循序渐进学.Net Core Web Api开发系列目录

本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi

一、概述

本篇介绍如何使用中间件(Middleware)。

二、初步演练

先写几个中间件

public class DemoAMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger; public DemoAMiddleware(RequestDelegate next, ILogger<DemoAMiddleware> logger)
{
_next = next;
_logger = logger;
} public async Task Invoke(HttpContext context)
{
_logger.LogInformation("(1) DemoAMiddleware.Invoke front");
await _next(context);
_logger.LogInformation("[1] DemoAMiddleware:Invoke back");
}
} public class DemoBMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger; public DemoBMiddleware(RequestDelegate next, ILogger<DemoBMiddleware> logger)
{
_next = next;
_logger = logger;
} public async Task Invoke(HttpContext context)
{ _logger.LogInformation("(2) DemoBMiddleware.Invoke part1");
await _next(context);
_logger.LogInformation("[2] DemoBMiddleware:Invoke part2");
}
} public class RequestRecordMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger; public RequestRecordMiddleware(RequestDelegate next, ILogger<RequestRecordMiddleware> logger)
{
_next = next;
_logger = logger;
} public async Task Invoke(HttpContext context)
{
_logger.LogInformation("(3) RequestRecordMiddleware.Invoke"); String URL = context.Request.Path.ToString();
_logger.LogInformation($"URL : {URL}"); await _next(context); _logger.LogInformation("[3] RequestRecordMiddleware:Invoke next");
_logger.LogInformation($"StatusCode : {context.Response.StatusCode}");
}
}

以上中间件前两个没有做什么正经工作,就打印一些日志信息,第三个干了一点工作,它打印了用户输入的url,同时打印了返回给客户端的状态码。

要使中间件工作,需要启用中间件。

   public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseUnifyException(); app.UseMiddleware<DemoAMiddleware>();
app.UseMiddleware<DemoBMiddleware>();
app.UseMiddleware<RequestRecordMiddleware>(); app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}

通过扩展方法,我们对中间件的启用代码进行改造:

public static class RequestRecordMiddlewareExtensions
{
public static IApplicationBuilder UseRequestRecord(this IApplicationBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException("builder is null");
} return builder.UseMiddleware<RequestRecordMiddleware>();
}
}

此时启用代码由:app.UseMiddleware<RequestRecordMiddleware>();

可以修改为:   app.UseRequestRecord();

实现效果没有变化。可见下面代码都是中间件的使用。

app.UseStaticFiles();
app.UseMvcWithDefaultRoute();

  

我的理解,中间件类似车间流水线上的工人,操作的零件就是HttpContext,每个人负责两道工序,我把它们定义为“前道工序”和“后道工序”,通过代码 _next(context); 把两道工序隔离开,处理的顺序需要特别注意,按照中间件注册的顺序依次处理“前道工序”,处理完成后,再按相反的顺序处理“后道工序”,如果某个中间件没有调用_next(context),那么就不会调用后续的中间件,所以中间件启用的顺序是需要特别考虑的。

以上代码中三个中间件输出到控制台的信息顺序如下:

(1)

(2)

(3)

【3】

【2】

【1】

个人认为,“前道工序”应重点处理Request,“后道工序”应重点处理Response。

三、做一个类似MVC的中间件

我们做一个中间件,让其返回一些内容给客户端:

public class MyMvcMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger; public MyMvcMiddleware(RequestDelegate next, ILogger<DemoAMiddleware> logger)
{
_next = next;
_logger = logger;
} public async Task Invoke(HttpContext context)
{ var str = "hello,world!";
await context.Response.WriteAsync(str);
}
}

这个中间件只是返回固定的字符串,我们还可以调用某个Controller的提供的方法。

   public class MyMvcMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger; public MyMvcMiddleware(RequestDelegate next, ILogger<DemoAMiddleware> logger)
{
_next = next;
_logger = logger;
} public async Task Invoke(HttpContext context)
{
var obj = context.RequestServices.GetRequiredService<ArticleController>().GetArticleList();
var str = JsonConvert.SerializeObject(obj);
await context.Response.WriteAsync(str);
}
}
ArticleController的定义如下:
    public class ArticleController : Controller
{
private readonly SalesContext _context;
private readonly ILogger _logger;
private readonly IMemoryCache _cache; public ArticleController(SalesContext context, ILogger<ArticleController> logger, IMemoryCache memoryCache)
{
_context = context;
_logger = logger;
_cache = memoryCache;
} [HttpGet]
public ResultObject GetArticleList()
{
_logger.LogInformation("==GetArticleList=="); List<Article> articles = _context.Articles
.AsNoTracking()
.ToList(); return new ResultObject
{
result = articles
};
}
}

要在中间件中通过依赖使用该Controller,需要将其注册到DI容器:

 public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ArticleController>();
}

以上中间件实现了一个文章信息查询的功能,如果在此中间件内先判断路径,再根据不同的路径调用不同的Contorller提供的服务,就可以形成一个简单的MVC中间件了。

四、中间件的用途

中间件的使用体现了AOP(面向切片)的编程思想,在不修改现有代码的情况下,通过增加一些中间件实现一些特定逻辑,可以做的事情很多,比如:

URL重写

缓存处理

异常处理

用户认证

五、中间件的注册顺序

前文提到中间件的注册顺序是比较重要的,建议的顺序如下:

1. 异常/错误处理
2. 静态文件服务器
3. 身份验证
4. MVC

循序渐进学.Net Core Web Api开发系列【13】:中间件(Middleware)的更多相关文章

  1. 循序渐进学.Net Core Web Api开发系列【0】:序言与目录

    一.序言 我大约在2003年时候开始接触到.NET,最初在.NET framework 1.1版本下写过代码,曾经做过WinForm和ASP.NET开发.大约在2010年的时候转型JAVA环境,这么多 ...

  2. 循序渐进学.Net Core Web Api开发系列【16】:应用安全续-加密与解密

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 应用安全除 ...

  3. 循序渐进学.Net Core Web Api开发系列【15】:应用安全

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍W ...

  4. 循序渐进学.Net Core Web Api开发系列【14】:异常处理

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍异 ...

  5. 循序渐进学.Net Core Web Api开发系列【12】:缓存

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如 ...

  6. 循序渐进学.Net Core Web Api开发系列【11】:依赖注入

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如 ...

  7. 循序渐进学.Net Core Web Api开发系列【10】:使用日志

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.本篇概述 本篇介 ...

  8. 循序渐进学.Net Core Web Api开发系列【9】:常用的数据库操作

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇描述一 ...

  9. 循序渐进学.Net Core Web Api开发系列【8】:访问数据库(基本功能)

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇讨论如 ...

随机推荐

  1. java Random.nextInt()方法

    转: java Random.nextInt()方法 lic int nextInt(int n) 该方法的作用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含 ...

  2. 函数和常用模块【day06】:logging模块(八)

    本节内容 1.简述 2.简单用法 3.复杂日志输出 4.handler详解 5.控制台和文件日志共同输出 一.简述 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误 ...

  3. Knowledge Tracing -- 基于贝叶斯的学生知识点追踪(BKT)

    目前,教育领域通过引入人工智能的技术,使得在线的教学系统成为了智能教学系统(ITS),ITS不同与以往的MOOC形式的课程.ITS能够个性化的为学生制定有效的 学习路径,通过根据学生的答题情况追踪学生 ...

  4. html5 canvas从圆开始

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. HTML5页面开发的基础性模板

    分享一个HTML5页面开发的基础性模板,包含了两个版本: 开发版本 注释版本 开发版本 <!DOCTYPE html> <html> <head> <meta ...

  6. 【译】使用OpenVAS 9进行漏洞扫描

    本文译自Vulnerability Scanning with OpenVAS 9 part 1: Installation & Setup系列,本文将融合目前已经发表的四个部分. Part ...

  7. 树莓派编译安装opencv3 (2019.1.6更新)

    一.更新系统 sudo apt-get update sudo apt-get upgrade sudo rpi-update #重启系统 sudo reboot 二.安装依赖库及程序 sudo ap ...

  8. day16作业

    一.填空题 1.Integer Character 2.String s = "123";Integer i = new Integer(s);System.out.println ...

  9. C++字符串完全指引

    引言 毫无疑问,我们都看到过像 TCHAR, std::string, BSTR 等各种各样的字符串类型,还有那些以 _tcs 开头的奇怪的宏.你也许正在盯着显示器发愁.本指引将总结引进各种字符类型的 ...

  10. Linux学习笔记:常用命令grep、iconv、cp、mv、rm

    本篇记录一些近期常用的命令. 一.grep过滤 grep过滤 不包含某些字符串 cat test.txt | grep -v '.jpg' 过滤jpg结尾的图片 cat test.txt | grep ...