过滤器的理解
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); }