天天看點

第五篇 基于.net搭建熱插拔式web架構(攔截器---請求管道)

  好了,前邊我們把核心内容介紹完了,接下來要做的就是攔截使用者的請求,并把請求轉向沙箱内。

  這裡我們準備通過實作一個HttpModule類來完成請求的攔截與轉發。建立一個HuberHttpModule類,并繼承IHttpModule。下面我們暫時隻處理Application_BeginRequest事件。

  先擷取request和response對象

HttpApplication application = sender as HttpApplication;
    HttpResponse respond = application.Response;
    HttpRequest request = application.Request;        
      

  接下來擷取目前請求的url:

string url = request.Url.AbsolutePath.ToString();
      

  我們做了一個約定,所有子產品都放在plugins目錄中,即需要判斷一下目前url是否以“/plugins/”開頭,再判斷一下是否為靜态檔案(通常情況下,我們的action命名是不允許包含“.”的)。

  接下來定義一個UrlPathEntity類,把url轉換成UrlPathEntity的執行個體對象,用來存放url對應的插件名稱、插件版本、controller、action。

  

public class UrlPathEntity
    {
        /// <summary>
        /// //插件名稱
        /// </summary>  
        public string pluginname { get; set; }
        /// <summary>
        /// //插件版本
        /// </summary>  
        public int pluginversion { get; set; }
        /// <summary>
        /// //控制器名稱(包含area)
        /// </summary>   
        public string controller { get; set; }
        /// <summary>
        /// //action名稱
        /// </summary>
        public string action { get; set; }
    }
      

  下面是url轉換方法:  

/// <summary>url解析成對象
        /// </summary>
        /// <param name="url"></param>
        /// <param name="isPlugin">是否為插件</param>
        /// <returns></returns>
        public static UrlPathEntity getUrlPathEntity(string url, bool isPlugin)
        {
            UrlPathEntity result = null;
            var matchs = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            if (isPlugin)
            {
                //var matchs = PluginRgx.Matches(url);
                if (matchs != null && matchs.Length > 0)
                {
                    int _index = 0;
                    result = new UrlPathEntity();
                    result.pluginname = matchs[_index++];//插件名稱
                    string _pluginversion = matchs[_index++];//插件版本
                    int pluginversion = -1;
                    int.TryParse(_pluginversion, out pluginversion);
                    result.pluginversion = pluginversion;
                    string urltemp = "/" + result.pluginname;
                    for (; _index < matchs.Length - 1;)
                    {
                        urltemp += "/" + matchs[_index++];
                    }
                    result.action = matchs[_index];//action名稱
                    urltemp += "/" + result.action;

                    CAModel controller = null;//控制器名稱(包含area)
                    UrlRefAction.TryGetValue(urltemp.ToLower(), out controller);
                    if (controller != null)
                    {
                        result.controller = controller.ControllerName.Replace("/", ".");
                        result.action = controller.ActionName;
                    }
                }
            }
            else
            {
                if (matchs != null && matchs.Length > 0)
                {
                    int _index = 0;
                    result = new UrlPathEntity();
                    result.controller = string.Empty;//控制器名稱(包含area)
                    for (; _index < matchs.Length - 1;)
                    {
                        result.controller += "." + matchs[_index++];
                    }
                    result.controller = result.controller.Substring(1);
                    result.action = matchs[_index];//action名稱
                }
            }
            return result;
        }
      

  擷取轉換後的對象:

var urlEntity = HuberPluginHandle.getUrlPathEntity(url.Substring(8), true);
      

  根據該對象找到對應的沙箱:

SandBoxDynamicLoader sandBox = HuberPluginHandle.getSandBox(urlEntity.pluginname, urlEntity.pluginversion);
      

  我們再把請求中攜帶的參數打包:

RefRequestEntity paras = new RefRequestEntity(); 
RequestHandle.FillCorRefEntity(paras, request);
      

  好了,準備工作做好了,最後一步,沙箱調用:  

var result = sandBox.InvokeMothod(urlEntity.controller, urlEntity.action, paras);
      

  這個result就是我們想要的結果了,接下來我們要做的就是把這個result傳回了

RequestHandle.ResposeResult(respond, result);
      

  至此,我們自定義的請求管道就算完成了,這其中為了防止通篇代碼帶來的反感,就省略了好多輔助業務,希望大家諒解。

 本來還想把權限管理什麼的些進來,後來想了想,這個系列主要是講架構的原理,而且權限那塊是基于sqlite寫的,不具有規模并發能力,代碼已經開源出來了,位址:https://github.com/Eric-zsp/Huber.net。

這個系列暫時先寫到這裡吧。

轉載請注明出處:http://www.cnblogs.com/eric-z/p/5108862.html