1. 程式人生 > >Linux.NET學習手記(8)

Linux.NET學習手記(8)

上一回合中,我們講解了Linux.NET面對OWIN需要做出的準備,以及介紹瞭如何將兩個支援OWIN協議的框架:SignalR以及NancyFX以OwinHost的方式部署到Linux.NET當中。這一章,我們將對框架與OwinHost之間怎麼通過OWIN協議作出解析。

本章我們將討論學習:

  (1)、連線兩世界之門——“Middleware“

  (2)、轉動大門的鑰匙,開啟無盡的財寶

  (3)、介面卡?轉換插頭

相關示例程式碼,可以點選這裡進行下載。

1、充當”門“的”Middleware“

英文名”Middleware“,中文名”中介軟體“,要了解什麼是Middleware,我們先看看OWIN協議中的分層。

上圖為OWIN分層的一個簡圖。最下的一層是我們的作業系統,Linux、Windows、Unix、Mac或其他;對上一層則是運行於作業系統中的OwinHost;再往上一層也就是紫色那層是基於OWIN協議建立的基礎框架;而最頂層則是我們基於這些OWIN協議的框架所誕生的應用程式(直接操作OWIN字典的暫不記錄在圖中)。

拋開最頂和最底兩層不管,當用戶從客戶端發起一請求,經過漫長的網路,到達目標主機時,請求將被並且僅能被OwinHost捕獲,因為只有OwinHost在持續的不斷監聽埠。雖然請求已經被OwinHost捕獲,但是OwinHost並沒有能力對這個剛捕獲的請求做出處理(這裡特指需要經過OWIN框架及相關應用程式處理的請求)即使它知道自身有請求需要處理。

同樣的,我們再把目光轉到OWIN框架,它是我們的”處理中樞“,它能夠對我們把我們的輸入通過適當的計算之後把正確的答案輸出來,但是它也有一個缺點,那就是它自身沒有辦法收集”相關資訊“,也就是它自己並不能產生出”輸入“。

這就好比人的大腦與其他器官,OWIN框架是我們的”大腦“,OwinHost則是我們的”器官“,沒有了大腦我們的其他器官也無法正常執行(當然咯,有點功能不需要大腦,就像有些OwinHost處理靜態資源不需要經過OWIN框架一樣),沒有了其他“器官”的支援“大腦”也無法發揮作用甚至會死亡(沒有宿主,OWIN框架也無法執行)。

因此,我們需要有相應的“神經”來連通我們的“器官”與“大腦”之間的通訊。而Middleware發揮的就是這種作用,它是連線OwinHost與OWIN框架的門,OwinHost把捕獲到的請求通過自身的處理後通過這扇門推送到OWIN框架中;而OWIN框架也自己對請求計算後得出的響應通過這扇門返回到OwinHost中,再由OwinHost推送到使用者手上。

而事實上,Middleware作為一扇連線OwinHost與OWIN框架的門,讓這兩個世界得以交流以外,還發揮著另外一個作用,那就是規定了統一的資訊出入口,所有的請求響應均只能夠通過這扇門傳遞,這或者可以更方便的對一些敏感資訊、惡意程式碼之流的資料進行攔截與過濾。

2、轉動我們手中的鑰匙

正如上一節中最後所講到的一樣,Middleware作為OWIN框架與OwinHost的唯一通道,這意味著無論是SignalR、NancyFX、Webapi、FubuMVC或是其他,它們所站立的起點高度都是一致的,我們只要把能握住Middleware,就相當於把握住了大門的鑰匙,我們也可以做出我們自己的框架出來。這也是我在上一回閤中所提到OWIN協議給我們帶來的好處中的第二點:“它給鼓勵了一批人把自己的想法變成現實”。

本節我們將簡述如何直接操作OWIN字典,直接和OwinHost進行通訊。

首先我們需要在Visual Studio中建立我們的專案,然後通過NuGet獲得OWIN:

然後我們新建一個類,並以它作為我們的Middleware:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace Demo1
{
    using AppFun = Func<IDictionary<string, object>, Task>;
    public class MyMiddleware
    {
        private readonly AppFun _env;

        public MyMiddleware(AppFun env)
        {
            if (env == null) throw new ArgumentNullException("OWIN環境引數為空");
            this._env = env;
        }

        public Task Invoke(IDictionary<string, object> env)
        {
            var responseBody = "Linux.NET 學習手記(8)&nbsp;        --小蝶驚鴻";
            var responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);
            ((IDictionary<string, string[]>)env["owin.ResponseHeaders"]).Add("Content-Type", new string[] { "text/html; charset=utf-8" });
            ((Stream)env["owin.ResponseBody"]).Write(responseBodyBytes, 0, responseBodyBytes.Length);
            return this._env(env);
        }
    }
}
MyMiddleware

這裡要對程式碼進行一番的解析:
  (1)、這是我們的Middleware,所有來自於OwinHost的請求資料以及OWIN框架響應的資料都要通過這個類來進行統一中轉處理。  

  (2)、IDictionary<string, object>實則為OWIN字典,裡面包含了基於OWIN協議的用於OwinHost與OWIN框架之間通訊的資料資訊。

  (3)、程式啟動時,OwinHost會先例項化這個類(實則呼叫Startup中的Configuration,然後例項化這個類,稍後我們會對此進行講述),繼而執行這個類的建構函式對Environment(也就是那個env)進行初始化。

  (4)、每次OwinHost捕獲到請求之後,會呼叫Invoke,OWIN字典會攜帶請求進入該方法,程式處理完成之後,OWIN字典則會攜帶OWIN框架的響應離開該方法。

建立好我們的Middleware之後,我們需要在專案的根目錄新建一個名為“Startup”的類,並在此類裡面建立一個名為“Configuration”的方法。

namespace Demo1
{
    using Owin;
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use(typeof(MyMiddleware));
            
        }
    }
}
Startup.cs

這裡也要為這個類作出一番解析:
OwinHost嘗試驅動OWIN框架時,它會嘗試尋找Startup,並激活裡面的Configuration,繼而啟用我們自定義的Middleware。OwinHost啟用我們的Middleware之後,OwinHost與OWIN框架之間就建立了連線,連線這兩個世界的“門”也就打開了。

在示例程式碼中,Demo1為講解如何通過簡單的操作OWIN字典獲取並返回我們想要輸出的結果。

Demo2則是模擬ASP.NET MVC的路由功能,OwinHost啟用Startup時,程式會對自身的程式集進行反射,找出所有以“Controller”結尾的類,並把裡面的方法註冊到路由字典中。當有來自於使用者的請求,程式則會自動的拆解URL並在路由字典中判斷是否存在改頁面,存在則繼而啟用相應的方法(Action),不存在則導向到404頁面。其效果如下圖所示:

成功的路由導向到Home/Index 頁面

訪問一個不存在的地址,路由導向到一個404的小動畫。

事實上,由於我們是基於OWIN協議直接操作OWIN字典所誕生的小Demo,因此我們是可以以一種無障礙的方式直接將專案釋出到Linux.NET中執行。

3、充當轉換插頭角色的介面卡

可能有細心而又愛動腦筋的讀者不禁問到,關於那兩個Demo(也能泛指其他所有的OWIN框架),OwinHost已經有了(Katana或者Jexus或其他),Middleware也由我們自行提供,不是OwinHost就可以與OWIN框架之間作出通訊了嗎?上一回閤中所出現的介面卡又是怎麼回事?為什麼沒有見到Windows版的介面卡?

在解析這個之前,我先上一張能夠很恰當比喻介面卡的圖片:

這是我隨手從網上找來的圖片,用過它的讀者很容易就能夠分辨出來它是一個轉換插頭,它能夠把各種型別的原插口轉換成通用的插口。對的,沒錯,如果以簡單的方式來理解,介面卡所起的所用正式OwinHost與OWIN框架之間的轉換插頭,它把OwinHost中所提供的原始資料格式化成OWIN字典供OWIN框架使用。這就是簡單的理解方式。

更深入的方式來理解,介面卡發揮著兩個重要的作用,除了簡單理解中所講述的作用以外,它還充當著讓OwinHost成功驅動Startup並激活Configuration的關鍵。有興趣的讀者可以開啟Jexus針對於OWIN框架的介面卡,你會發現原來它也是通過反射尋找Startup類並激活裡面的Configuration來建立Middleware並建立連線的,瞭解了這一點之後,我們可以通過修改介面卡的原始碼來更改OwinHost嘗試驅動OWIN框架時最先啟用的類,我們可以根據自己的愛好把“Startup”這個名字改為“Breakdown”、“Sunday”或者“ILoveChina”甚至“ILoveXiaodiejinghong”,也可以把“Configuration”改為其他……總之你喜歡的。

至於為何Katana沒有介面卡,我這裡只能說:“可能已經內建了吧”(具體還需要各位讀者檢視原始碼,我沒有檢視過,因此沒有發言權)。

好的,兩回合文章我們簡單的認知了一些關於OWIN的事情,OWIN作為微軟提出一套重要協議具有重大的戰略意義。不多說了,我們下回再見吧。謝謝。