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种情况:
- 解答者: 了解问题的内容(Request),给出最终答案(Response),一般不需要后续解答者的参与. 比较典型是解答者是WebApi和StaticFiles(静态文件).
- 参与者: 了解问题的内容,给出一定的资源(Environment)供其他参与者使用,本身一般不参与解答, 有可能在答案中加入一些附加信息.比较典型的有Session和Identity.它们一般会加入一些Cookie但不影响Response实体内容.
- 监控者: 在其他参与者开始处理或者处理完毕的时候对当前的Context中的信息进行处理,它也一般不参与解答,有可能在答案中加入一些附加信息. 比较典型的有Logging, Diagnostics.
如何创建Middleware
创建一个的Middleware分以下几个步骤:
- 引入Microsoft.Owin包
- 建立一个类
- 使这个类继承Microsoft.Owin.OwinMiddleware
- 实现这个类的构造函数
- 覆盖并实现父类的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 = ;
context.Response.Expires = DateTimeOffset.Now;
context.Response.Write(content);
//解答者告诉Server解答已经完毕,后续Middleware不需要处理
return Task.FromResult();
}
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的运作机制.
OWIN的理解和实践(三) –Middleware开发入门的更多相关文章
- Middleware开发入门
Middleware开发入门 上篇我们谈了Host和Server的建立,但Host和Server无法产出任何有实际意义的内容,真正的内容来自于加载于Server的Middleware,本篇我们就着重介 ...
- OWIN的理解和实践(二) – Host和Server的开发
对于开发人员来说,代码就是最好的文档,如上一篇博文所说,下面我们就会基于Kanata项目的一些具体调用代码,来进一步深入理解OWIN的实现和作用. 今天我们先针对Host和Server来实现一个简单的 ...
- OWIN的理解和实践(一) – 解耦,协作和开放
概述 OWIN的全称是Open Web Interface For .Net, 是MS在VS2013期间引入的全新的概念, 网上已经有不少的关于它的信息, 这里我就谈下我自己的理解: OWIN是一种规 ...
- 20145213《Java程序设计》实验三敏捷开发与XP实践
20145213<Java程序设计>实验三敏捷开发与XP实践 实验要求 1.XP基础 2.XP核心实践 3.相关工具 实验内容 1.敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法 ...
- 20145308刘昊阳 《Java程序设计》实验三 敏捷开发与XP实践 实验报告
20145308刘昊阳 <Java程序设计>实验三 敏捷开发与XP实践 实验报告 实验名称 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 统计的PSP(Personal ...
- 20145215实验三 敏捷开发与XP实践
20145215实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软 ...
- 2018-2019-20175205 实验三敏捷开发与XP实践《Java开发环境的熟悉》实验报告
2018-2019-20175205 实验三敏捷开发与XP实践<Java开发环境的熟悉>实验报告 实验要求 没有Linux基础的同学建议先学习<Linux基础入门(新版)>&l ...
- 20155324 《Java程序设计》实验三 敏捷开发与XP实践
20155324 <Java程序设计>实验三 敏捷开发与XP实践 实验内容 XP基础 1.XP核心实践 2.相关工具 实验步骤 敏捷开发与XP 1.敏捷开发(Agile Developme ...
- 20172328《程序设计与数据结构》实验三 敏捷开发与XP实践报告
20172328<程序设计与数据结构>实验三 敏捷开发与XP实践报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 李馨雨 学号:20172328 实验教师:王志强 ...
随机推荐
- 【openresty】获取post请求数据FormInputNginxModule模块
关于openresty的一些介绍看这里. 首先,实验背景为openresty作为后台来处理前台post传递的数据. 在openresty内,有一个FormInputNginxModule模块,作用是解 ...
- php 中遍历数组时使用引用出现的问题
今天在使用foreach遍历数组时发现,当使用&时会出现问题: $arr = array( array('id' => 100, 'error'=> 'aa'), array('i ...
- ASCII、Unicode、GBK和UTF-8字符编码的区别联系
转自http://dengo.org/archives/901 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称 ...
- 增强拉格朗日乘子法(Augmented Lagrange Method)
增强拉格朗日乘子法的作用是用来解决等式约束下的优化问题, 假定需要求解的问题如下: minimize f(X) s.t.: h(X)=0 其中,f:Rn->R; h:Rn->Rm 朴素拉格 ...
- How to copy remote computer files quickly to local computer
if we want copy file from VM(Remote VM) to local computer. Always can not easy copy file so easy. no ...
- JAVA求圆的面积
import java.text.DecimalFormat;import java.util.Scanner; public class TheAreaOfCircle { public stati ...
- java四种内部类
内部类有成员内部类,局部内部类,匿名内部类,静态内部类. 1,成员内部类package innerClass; public class InnerClassTest { String s1=&quo ...
- 学习codeIgniter的一点小感受
用CI好几天了,最终还是放弃用CI做完整的项目,感觉CI在前后端的交互上还比较差,比如说用户表单验证,仍然是需要把数据提交给服务器之后才能显示逻辑判断的结果.而这一点明显是相对落后了. 但不可否认CI ...
- 友盟错误日志分析(转自:COCOACHINA shemy )
在做的项目中,用到了友盟的组件,在没有禁用错误日志上传之前,收集了一些错误日志. 有一些朋友看到了错误日志,却不知道怎么定位到程序的的代码中,实际上,这一步是非常的简单.友盟没有集成.dSYM文件 ...
- Linux的.a、.so和.o文件
在说明Linux的.a..so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系 windows下obj,lib,dll,exe的关系 lib是和dll对应的.lib是静 ...