過濾器的理解
Filter就是過濾器,在WebForm中,各種管道事件就是相當於過濾器,在MVC中,過濾器是單獨的一種機制,分為方法過濾器和異常處理過濾器,方法過濾器實現的功能是在執行某一個請求得方法之前,先去執行以下其他的某些操作,當執行完成后再繼續去執行要執行的方法。這種執行的機制就是相當於在一個流程中間切了一刀,這種思想就是面想切面編程(AOP)。
過濾器可以實現在執行請求方法的時候做權限校驗、登錄校驗等,比如說只有登錄的用戶才可以訪問這個方法,需要進行Session的校驗。如果有很多的控制器中的方法都需要校驗session,后期維護也是非常的不方便的,所以只需要將這種校驗放在Filter中就可以了。
方法過濾器
1.首先自己手寫一個過濾器特性類,繼承自ActionFilterAttribute
2.然后自己手寫實現ActionFilterAttribute中的相應的方法。
3.將特性標簽加載相應的行為或者控制器上面就可以了
自定義過濾器:
public class MyDemoFilterAttribute:ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("我是后面"); } public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("我是前面"); } }
給相應的方法添加自定義特性 [MyDemoFilter] public ActionResult Index() { return View(); }
異常處理過濾器
1.首先自己創建一個異常處理了你,然后繼承自HandleErroAttribute
public class MyExceptionAttribute : HandleErrorAttribute { //如果很多用戶都出錯,同時將這些錯誤寫入到日志中,會造成日志文件的並發,所以將每個用戶的錯誤存儲在隊列中去,隊列操作是非常的迅速的 public static Queue<Exception> MyExceptionQueue = new Queue<Exception>(); public override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); Exception ex = filterContext.Exception; //接下來就是得加入到隊列中進行處理 MyExceptionQueue.Enqueue(ex); //跳轉到錯誤頁面 filterContext.HttpContext.Response.Redirect("/Error.html"); } }
2.然后在Global文件注冊一下,找到對應的注冊方法
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { // filters.Add(new HandleErrorAttribute()); filters.Add(new MyExceptionAttribute()); } }
3.這樣我們的HandleErrorFilter就可以使用了
補充:日志的處理
日志的處理需要單獨開一線程,一直處理,此時需要在Application_Start的管道開始的時候就加入開啟進程,然后將錯誤日志寫到日志文件
public void StartDealLog() { string filePath = Server.MapPath("/Log/"); ThreadPool.QueueUserWorkItem((a) => { while (true) { if (MyExceptionAttribute.MyExceptionQueue.Count > 0) { Exception ex = MyExceptionAttribute.MyExceptionQueue.Dequeue(); if (ex != null) { //將錯誤寫到日志中取 File.AppendAllText(filePath + DateTime.Now.ToString("yyyy-MM-dd")+".txt", ex.ToString(), System.Text.Encoding.UTF8); } else { Thread.Sleep(3000); } } else {//將當前線程掛起(就近) Thread.Sleep(3000); } } },filePath); }