第五篇 基於.net搭建熱插拔式web框架(攔截器---請求管道)
阿新 • • 發佈:2018-12-30
好了,前邊我們把核心內容介紹完了,接下來要做的就是攔截使用者的請求,並把請求轉向沙箱內。
這裡我們準備通過實現一個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。
這個系列暫時先寫到這裡吧。