上篇我们谈了Host和Server的建立,但Host和Server无法产出任何有实际意义的内容,真正的内容来自于加载于Server的Middleware,本篇我们就着重介绍下Middleware的开发入门.
如果把HTTP交互理解为一次答题活动,那么Request是问题,Response就是答案,Server是课堂,Middleware就是参与者,注意我这里用的是参与而不是解答,因为我们允许有些Middleware不给出答案.
要参与答题活动就必须有知识,也就是资源.在OWIN规则中,所有Middleware只能获得并影响一个资源,这个就是OWIN Context,有一个Microsoft.Owin. IOwinContext接口定义了这个上下文的标准. 我们来看下这个里面有什么东西.
这个上下文接口中 提供的资源,是Middleware进行运作的关键:
简单来说,Middleware可以做什么怎么做可以归结为以下几点:
刚刚我们说了,Middleware不一定是问题的解答者, 他们有前后的顺序和各自回答问题的方式,根据他们的参与方式,我把他们分成3种情况:
创建一个的Middleware分以下几个步骤:
一个最为典型的实现如下
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就是我们上面所说的上下文信息.
剩下的工作,就是在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); }
这里提几个要点:
这里需要回到我的上一篇博文, Host和Server开发, 在那里面,我说到目前的Startup函数是空的,说明没有加载任何Middleware,而现在我们需要在那个函数里面加载我们开发的Middleware了,代码很简单:
private static void Startup(Owin.IAppBuilder app) { //加载Sample Middleware Console.WriteLine("Sample Middleware loaded..."); app.Use<SampleMiddleware>(); }
注意2点:
好了,联合上一篇博文的代码,编译运行.我们能够看到如下输出界面:
(注意:很多机器需要管理员权限运行VS,才能正常运行该程序)
打开浏览器,访问http://localhost:9000/tick
我们看到了一个tick. 这就是这个中间件返回的结果.而其他地址依然会没有任何返回,这是因为并没有任何其他Middleware来处理其他的情况.
当然,基于OWIN架设的体系,我们可以开发更加复杂的Middleware,下一篇,我将会进一步给出三个比较复杂的Middleware实现: StaticFile, Session, Logging; 来帮助大家进一步理解,解答者,参与者和监控者的概念.同时也深入理解Middleware的运作机制.