OWIN的理解和实践(三) –Middleware开发入门

简介: 原文:OWIN的理解和实践(三) –Middleware开发入门上篇我们谈了Host和Server的建立,但Host和Server无法产出任何有实际意义的内容,真正的内容来自于加载于Server的Middleware,本篇我们就着重介绍下Middleware的开发入门.
原文: OWIN的理解和实践(三) –Middleware开发入门

上篇我们谈了Host和Server的建立,但Host和Server无法产出任何有实际意义的内容,真正的内容来自于加载于Server的Middleware,本篇我们就着重介绍下Middleware的开发入门.

Middleware是什么

如果把HTTP交互理解为一次答题活动,那么Request是问题,Response就是答案,Server是课堂,Middleware就是参与者,注意我这里用的是参与而不是解答,因为我们允许有些Middleware不给出答案.

Middleware有什么资源

要参与答题活动就必须有知识,也就是资源.在OWIN规则中,所有Middleware只能获得并影响一个资源,这个就是OWIN Context,有一个Microsoft.Owin. IOwinContext接口定义了这个上下文的标准. 我们来看下这个里面有什么东西.

 

这个上下文接口中 提供的资源,是Middleware进行运作的关键:

  • Authentication : 获取可在当前请求上使用的身份验证(Identity)中间件功能。通过这个属性可以非常便捷在任何Middleware中访问当前的Identity信息.当然至少一个Identity中间件需要被加载,否则这个属性中的内容没有意义.
  • Environment: 获取已包装的 OWIN 环境。它本质是一个数据字典,一个Middleware利用Key放入一个信息,而另外一个Middleware根据Key拿出来使用. 和Session异曲同工.
  • Request: 获取可公开特定于请求的属性的包装。Middleware从这里了解我们的提问者(Request)提供了那些信息.
  • Response : 获取可公开特定于响应的属性的包装。Middleware通过这个属性可以给出,影响或者改变我们的Response(答案),当然它也可以不做任何调整.

Middleware到底做什么,怎么做

简单来说,Middleware可以做什么怎么做可以归结为以下几点:

  • 获得OWIN Context和它内部封装的所有信息.
  • 从Request中获取请求的所有信息.
  • 从Environment中获取其他Middleware共享的资源,以便于和其他Middleware交互,或者使用其他Middleware提供的功能.
  • 从Authentication中获取当前的身份验证信息和结果.
  • 通过Response给出,影响,甚至改变Server即将发出的”答案”

Middleware有哪几种类型

刚刚我们说了,Middleware不一定是问题的解答者, 他们有前后的顺序和各自回答问题的方式,根据他们的参与方式,我把他们分成3种情况:

 

  1. 解答者: 了解问题的内容(Request),给出最终答案(Response),一般不需要后续解答者的参与. 比较典型是解答者是WebApi和StaticFiles(静态文件).
  2. 参与者: 了解问题的内容,给出一定的资源(Environment)供其他参与者使用,本身一般不参与解答, 有可能在答案中加入一些附加信息.比较典型的有Session和Identity.它们一般会加入一些Cookie但不影响Response实体内容.
  3. 监控者: 在其他参与者开始处理或者处理完毕的时候对当前的Context中的信息进行处理,它也一般不参与解答,有可能在答案中加入一些附加信息. 比较典型的有Logging, Diagnostics.

如何创建Middleware

创建一个的Middleware分以下几个步骤:

  1. 引入Microsoft.Owin包
  2. 建立一个类
  3. 使这个类继承Microsoft.Owin.OwinMiddleware
  4. 实现这个类的构造函数
  5. 覆盖并实现父类的Invoke函数

一个最为典型的实现如下

    using Microsoft.Owin;
    using System.Threading.Tasks;

    /// <summary>
    /// Middleware类必须继承Microsoft.Owin.OwinMiddleware
    /// </summary>

    public class SampleMiddleware : OwinMiddleware
   {
       public SampleMiddleware(OwinMiddleware next)
          : base(next)
        {
            //构造函数
        }

        public override Task Invoke(IOwinContext context)
        {
            //中间件的实现代码
            return Next.Invoke(context);
        }
}

 

 

绝大部分Middleware需要预设一些属性,这些属性可以通过改造构造函数来实现:

        object m_Options;
        public SampleMiddleware(OwinMiddleware next,object options)
            : base(next)
        {
            //引入参数类,并可以再类中使用
            m_Options = options;
        }

当然类似的options参数可以有多个.

以上的Middleware实现其实是没有意义的,因为没有做任何事情,下面我将给出一个”给出答案”的简单实现,根据上面的描述,我在下面仅仅给出Invoke函数的内容.

这里再插一句,上述代码中的next或Next指的是排在这个Middleware之后的另一个Middleware,而context就是我们上面所说的上下文信息.

一个简单的Middleware范例

剩下的工作,就是在Invoke函数中实现当前Middleware的功能,这里给出一个非常简单的实现,来做出一个最简单的功能: 输入结尾为\tick的URL,返回一个纯文本的Response,里面包含当前服务器时间的Tick信息.

 

       public override Task Invoke(IOwinContext context)
      {
            PathString tickPath = new PathString("/tick");
            //判断Request路径为/tick开头
            if (context.Request.Path.StartsWithSegments(tickPath))
            {
                string content = DateTime.Now.Ticks.ToString();
                //输出答案--当前的Tick数字
                context.Response.ContentType = "text/plain";
                context.Response.ContentLength = content.Length;
                context.Response.StatusCode = 200;
                context.Response.Expires = DateTimeOffset.Now;
                context.Response.Write(content);
                //解答者告诉Server解答已经完毕,后续Middleware不需要处理
                return Task.FromResult(0);
            }
            else
             //如果不是/tick路径,那么交付后续Middleware处理
            return Next.Invoke(context);

        }

 

这里提几个要点:

  • PathString是Miscrosoft.Owin下一个类,封装了URL处理的一些功能.
  • Task.FromResult(0) 表示一个空的Task,说明该Middleware在某些情况下不再触发后续的Middleware运行—也就是”到此为止”.
  • 最后Next.Invoke(context)是一个非常标准的实现,把上下文交付下一个Middleware继续处理—相当于”交出接力棒”.
  • 这个Middleware是一个标准的解答者.它给出了”/tick”这个问题的最终答案.

如何使用Middleware

这里需要回到我的上一篇博文, Host和Server开发, 在那里面,我说到目前的Startup函数是空的,说明没有加载任何Middleware,而现在我们需要在那个函数里面加载我们开发的Middleware了,代码很简单:

 

        private static void Startup(Owin.IAppBuilder app)
        {
            //加载Sample Middleware
            Console.WriteLine("Sample Middleware loaded...");
            app.Use<SampleMiddleware>();
        }

 

注意2点:

  • 保证已经加入了 using Owin;
  • SampleMiddleware的构造函数是仅有一个OwinMiddleware参数的版本,如果有附加参数,请加到Use函数的参数列表里面去.

好了,联合上一篇博文的代码,编译运行.我们能够看到如下输出界面:

 

(注意:很多机器需要管理员权限运行VS,才能正常运行该程序)

打开浏览器,访问http://localhost:9000/tick

我们看到了一个tick. 这就是这个中间件返回的结果.而其他地址依然会没有任何返回,这是因为并没有任何其他Middleware来处理其他的情况.

        当然,基于OWIN架设的体系,我们可以开发更加复杂的Middleware,下一篇,我将会进一步给出三个比较复杂的Middleware实现:  StaticFile, Session, Logging; 来帮助大家进一步理解,解答者,参与者和监控者的概念.同时也深入理解Middleware的运作机制.

目录
相关文章
|
7月前
|
中间件 程序员 开发工具
Django实践-08中间件的应用
Django实践-08中间件的应用
Django实践-08中间件的应用
|
4月前
|
前端开发 中间件 索引
Django入门到放弃之中间件
Django入门到放弃之中间件
|
4月前
|
存储 中间件 PHP
Python编程入门:从零到一的代码实践深入理解 PHP 中的中间件模式
【8月更文挑战第28天】本文旨在通过浅显易懂的方式,向初学者介绍Python编程的基础知识,并结合具体代码示例,带领读者一步步实现从零基础到能够独立编写简单程序的转变。文章将围绕Python语言的核心概念进行讲解,并通过实例展示如何应用这些概念解决实际问题。无论你是编程新手还是希望扩展技能的专业人士,这篇文章都将为你打开编程世界的大门。 【8月更文挑战第28天】在PHP的世界中,设计模式是构建可维护和可扩展软件的重要工具。本文将通过浅显易懂的语言和生动的比喻,带领读者深入理解中间件模式如何在PHP应用中发挥魔力,实现请求处理的高效管理。我们将一步步揭开中间件的神秘面纱,从它的定义、工作原理到
|
5月前
|
JSON 中间件 数据处理
实践出真知:通过项目学习Python Web框架的路由与中间件设计
【7月更文挑战第19天】探索Python Web开发,掌握Flask或Django的关键在于理解路由和中间件。路由连接URL与功能,如Flask中@app.route()定义请求响应路径。中间件在请求处理前后执行,提供扩展功能,如日志、认证。通过实践项目,不仅学习理论,还能提升构建高效Web应用的能力。示例代码展示路由定义及模拟中间件行为,强调动手实践的重要性。
62 1
|
5月前
|
设计模式 中间件 测试技术
PHP中的中间件模式解析与实践
【7月更文挑战第11天】在现代Web开发中,中间件模式已成为设计高效、可维护应用程序的关键。本文深入探讨了PHP环境下中间件模式的实现方法,并提供了一个实际示例来演示如何利用中间件优化请求处理流程。
46 1
|
5月前
|
运维 中间件 PHP
深入理解PHP中的中间件模式自动化运维之脚本编程实践##
【7月更文挑战第31天】在PHP开发中,中间件模式是一种强大的设计模式,它允许开发者在请求处理流程中注入自定义的处理逻辑。本文将通过实际代码示例来探讨如何在PHP项目中实现和使用中间件,以及这种模式如何提升应用程序的可维护性和扩展性。 【7月更文挑战第31天】 在现代IT运维管理中,自动化不再是可选项,而是提高生产效率、确保服务质量的必需品。本文将通过Python脚本编程的角度,探讨如何利用代码简化日常运维任务,提升工作效率。我们将从实际案例出发,逐步剖析自动化脚本的设计思路、实现过程及其带来的益处。 ##
37 0
|
JSON JavaScript 中间件
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
300 9
【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件
|
SQL 关系型数据库 中间件
postgresql从入门到精通 - 第35讲:中间件PgBouncer部署
postgresql技术大讲堂,从入门到精通 - 第35讲:中间件PgBouncer部署
289 1
|
消息中间件 存储 Java
消息中间件第一讲:RocketMQ从入门到精通
消息中间件第一讲:RocketMQ从入门到精通
534 2
|
消息中间件 Java Linux
消息中间件系列教程(02) -ActiveMQ -安装&入门案例
消息中间件系列教程(02) -ActiveMQ -安装&入门案例
65 0