好了,前邊我們把核心内容介紹完了,接下來要做的就是攔截使用者的請求,并把請求轉向沙箱内。
這裡我們準備通過實作一個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