Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 518|回复: 0

asp.net MVC3 仿照博客园功能 异常处理

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-21 01:21:18 | 显示全部楼层 |阅读模式
    这几天感觉我自己比较懒,除了偶尔的写了一点博客以外,对于那个重要的仿照博客园功能的项目我竟然忘记更新了。失误了,天天脑子里的事太多了,有点乱,程序员,伤不起啊。

    还是不能不谦虚啊,今天继续项目的开发,不做那些费时的工作了,那个等我星期休息的时候再做,今天来做一个异常处理的功能。
        
    众所周知,在asp.net世界中,对于异常的处理就是try catch,当然这个是在方法内部,还有Page_Error 页面级别的错误,

    application_error 应用程序级别的错误,这几个地方可以用来处理异常信息。一般情况下,

    我们对于已知的可能出现的错误会直接在try  catch中捕获并且处理,但是对于那些我们没有考虑到的异常信息,我们就要采取别的办法了,

    比如定义一个基类,用来处理子类抛出的异常,然后在可能出现异常信息的地方继承该类,让父类处理子类中不能确定的并且是抛出的未处理的异常信息。

    这个和验证用户是否登陆的方式基本一样,对于某些资源,需要有权限的用户才能访问,我们就会定义一个基类,用来验证用户是否登陆,

    如果登陆才可以继续执行,否则就要跳转到登陆界面。

    当然,前面说的处理异常的方式是在web form时代我们(起码是我)常用的方式,但是在MVC 时代到临的时候,这些处理是否更容易呢?

    答案是肯定的,因为技术是在不断进步的嘛。

    在MVC中我们对于已知的异常信息仍然会采用try catch的方式,并且是很常用的方式,但是对于验证用户登陆或者catch未捕获的异常信息

    (当然我的意思是catch(exception ex)   在catch最后没有这一条,或者说有这一句,但是把异常信息进行了抛出处理),我们有了更容易实现的方式。

    下面让我们一起走进如何使用MVC处理异常信息。

    在软件架构不断发展的同时,设计模式也有了很多变种,AOP(面向切面编程或面向方面编程)就是一个变种的设计模式,对于设计模式的学习,

    我个人不推荐死记硬背,我希望可以了解每种模式的意义,然后在项目中不要刻意的去使用它,而是在重构的时候进行,

    这样我们可以更加深入的了解设计模式背后包含的含义。举个例子,单例模式是一个经典的设计模式,它可以保证类的实例只有一个,

    但是如果我们不正确的使用这种方式,有时候会带来负面效果,比如多线程同时访问,只有在保证加锁、解锁的情况下可以保证,

    但是在普通情况下就会出现意想不到的错误信息。

    面向对象编程具有继承性,这应该是面向对象三大特性之一,这是类的垂直方面的编程工作,有上下级或父子关系,AOP是水平方面的编程,

    它可以保证在开始之前或结束之后进行,不会破坏里面的结构。个人粗浅理解。

    在MVC 3中对AOP的支持就表现在filter  过滤器上,他可以保证在开始之前或结束之后进行。

    对于异常的处理我们采用的是自定义异常处理信息继承自IExceptionFilter,当然在MVC总内置了一个HandleErrorAttribute也可以用来捕获异常,

    但是我们自己来控制可能会更好一些。

     

    首先我们在HomeController的Index方法中抛出一个异常信息

     1  public ActionResult Index(int? id, int pageSize = 20)  2  {  3             List<BlogInfo> blogList = BlogServices.GetAllBlogList().ToPagedList<BlogInfo>(id == null ? 1 : Convert.ToInt32(id), pageSize);  4             ViewBag.BlogList = blogList;  5             if (Request.IsAjaxRequest())  6  {  7 
     8  }  9             
    10                 throw new HttpException(500, "");//抛出异常信息
    11             
    12 
    13             return View(blogList); 14  } 15   //404Not Found
    16         public ActionResult NotFound() 17  { 18             return View(); 19  } 20         //内部服务器错误 500
    21         public ActionResult InternalError() 22  { 23             return View(); 24         }

    2.设置自定义处理异常类

     1  public class CustomExceptionAttribute :FilterAttribute,IExceptionFilter   //HandleErrorAttribute
     2  {  3 
     4         public  void OnException(ExceptionContext filterContext)  5  {  6             if (filterContext.ExceptionHandled == true)  7  {  8                 HttpException httpExce = filterContext.Exception as HttpException;  9                 if (httpExce.GetHttpCode() != 500)//为什么要特别强调500 因为MVC处理HttpException的时候,如果为500 则会自动 10                     //将其ExceptionHandled设置为true,那么我们就无法捕获异常
    11  { 12                     return; 13  } 14  } 15             HttpException httpException = filterContext.Exception as HttpException; 16             if (httpException != null) 17  { 18                 filterContext.Controller.ViewBag.UrlRefer = filterContext.HttpContext.Request.UrlReferrer; 19                 if (httpException.GetHttpCode() == 404) 20  { 21                     filterContext.HttpContext.Response.Redirect("~/home/notfound"); 22  } 23                 else if (httpException.GetHttpCode() == 500) 24  { 25                     filterContext.HttpContext.Response.Redirect("~/home/internalError"); 26  } 27  } 28             //写入日志 记录
    29             filterContext.ExceptionHandled = true;//设置异常已经处理
    30  } 31     }
    在这里我要多说一句,有些园友可能遇到这么一个问题,就是抛出了一个500的内部服务器异常,但是在自定义异常信息中就是无法捕获到,是什么原因呢?

    其实就是MVC对500 的特殊照顾,在HttpException的httpCode为500的时候,MVC框架会自动的处理,然后将其ExceptionHandled设置为true。

    对于其他的异常状态码,比如404就没有这样的照顾,所以500我们要优先照顾呀。

    3.在设置好了自定义异常处理以后,我们可以在每个Action或Controller中进行注入,但是在MVC 3 中提供了另外一种可以全局注入的方式,那就是全局Filter,我一般叫做全局筛选器。这样就相当于我们在所有的Action上都进行了注入。

    在global.asax中,进行全局注册
    1  public static void RegisterGlobalFilters(GlobalFilterCollection filters) 2  { 3             filters.Add(new CustomExceptionAttribute(),1);//自定义的验证特性 4             filters.Add(new HandleErrorAttribute(),2); 5         }

     

    4.我们在设置了自定义异常处理以后,会跳转到对应的页面,里面的信息相信大家都可以自己定制了

     

    5.有图有证据  先来一个404异常处理信息

    我请求的页面是home/index,然后自动跳转到了notFound页面
    还有500错误,如果您不注意判断一个这个错误,那么你是不可能的

    总结一下,在MVC中处理异常有很多中方式,HandleErrorAttribute,自定义异常处理类(重写IExceptionFilter或者是HandleErrorAttribute 的OnException方法),传统的try catch方法,这些都可以,除去那个try catch,其实自定义异常处理就是Filter的体现,和登陆验证没有任何区别。
    还有一点就是HttpException的HttpCode为500的情况,ExceptionHandled会被自动设置为true,需要特殊照顾一下。
    在我们处理完了异常以后,一定要将其ExceptionHandled设置为true,这样可以避免父类或者更高一级的异常处理捕获处理该异常信息。
    MVC处理异常就是这么简单,Filter特性就是那么强大,让我们拥抱MVC,拥抱filter。
    我看到有位大牛的MVC 4 书籍已经可以预定了,先试读一下,可以的话买一本,支持国产大牛,丰富一下自己。不是做广告,是发牢骚,什么时候能轮到我出书呢。
     

     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-18 18:20 , Processed in 0.071979 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表