zoukankan      html  css  js  c++  java
  • webapi框架搭建-webapi异常处理

    webapi框架搭建系列博客

    前言

      上一篇我们已经完成了项目的日志管理,在项目开发中日志会经常记录程序中的异常,供后续问题排查使用。本篇讲如何在webapi里加入异常处理机制。

    目的和原则

      1、程序任何地方都不能catch掉异常,如果要catch也请重新throw异常或是将异常记录到日志里。避免异常被“吃掉“,导致无法排查程序的bug。

      2、webapi接口的”请求成功“和”请求失败“以一定的标准规范提供给外部

        我的规范为:

        所有的成功请求返回200(response的status为200),返回的结果以json封装

        所有的失败请求返回非200,错误以json返回,错误的内容为Message的值,如{"Message":"这里是异常的内容描述"}

      3、如果为已知异常(即我们代码里写的throw异常)可简单的记录到日志,但如果是未知异常(我们不知道是哪里抛出的异常,往往也是程序的bug)则记录到特殊的日志文件里,如上篇的log/error目录下。

    参考

    微软webapi异常处理:https://docs.microsoft.com/zh-cn/aspnet/web-api/overview/error-handling/

    步骤如下

    自定义异常类

      此异常类即是”已知“异常,约定程序里我们自己抛出的异常都用此类,Message属性记录异常的描述信息

    using System;
    using System.Runtime.Serialization;
    
    namespace webapi.Exceptions
    {
        public class KnownException : Exception
        {
            public KnownException():base()
            {
            }
    
            public KnownException(string message) : base(message)
            {
            }
    
            public KnownException(string message, Exception innerException) : base(message, innerException)
            {
            }
    
            protected KnownException(SerializationInfo info, StreamingContext context) : base(info, context)
            {
            }
        }
    }
    

    创建webapi异常过滤器

      创建WebApiExceptionFilterAttribute类,代码如下

    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;
    using log4net;
    
    namespace webapi.Exceptions
    {
        public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute
        {
            public override void OnException(HttpActionExecutedContext actionExecutedContext)
            {
                var exception = actionExecutedContext.Exception;//获取产生的异常对象
                var exceptionMessage = exception.Message;
                var logMessage = 
                    $@"controller.action={actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName}.{actionExecutedContext.ActionContext.ActionDescriptor.ActionName}:exception="
                    + exception.Message;//异常内容
                ILog log = LogManager.GetLogger(actionExecutedContext.ActionContext.ControllerContext.Controller.GetType());
                if (exception is KnownException)
                {
                    log.Debug(logMessage);
                }
                else
                {
                    log.Error(logMessage, exception);
                }
                actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, exceptionMessage);
            }
    
        }
    }
    

      在webapi里使用异常过滤最简单的方法就是继承自ExceptionFilterAttribute类,并重写OnException方法并写入自己的异常处理逻辑

    将异常过滤器加到webapi里

    修改之前的WebApiConfig.OwinWebApiConfiguration方法,代码如下

    /// <summary>
            /// 返回webapi的httpconfiguration配置
            /// 用于webapi应用于owin技术时使用
            /// </summary>
            /// <returns></returns>
            public static HttpConfiguration OwinWebApiConfiguration(HttpConfiguration config)
            {
                config.MapHttpAttributeRoutes();//开启属性路由
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
                config.Filters.Add(new WebApiExceptionFilterAttribute());
                return config;
            }
    

      增加的只是config.Filters.Add(new WebApiExceptionFilterAttribute());这一句

    测试结果

    创建用于测试的控制器,写两个接口分别模拟程序bug抛出的未知异常和自己抛出的已知异常

    using System;
    using System.Web.Http;
    using webapi.Exceptions;
    
    namespace webapi.example
    {
        [RoutePrefix("api/exceptionTest")]
        public class ExceptionTestController : ApiController
        {
            /// <summary>
            /// 模拟程序bug抛出的异常
            /// </summary>
            /// <returns></returns>
            [Route("unknown"),HttpGet]
            public IHttpActionResult UnKnow()
            {
                throw new Exception("未知的异常");
            }
            /// <summary>
            /// 模拟主动抛出的业务异常
            /// </summary>
            /// <returns></returns>
            [Route("known"), HttpGet]
            public IHttpActionResult Know()
            {
                throw new KnownException("已知的异常");
            }
        }
    }
    

      返问两个接口会得到内容为{"Message":"xxx"},status为400的respose,和我们的约定规则一样。

  • 相关阅读:
    职业的选择
    事务的隔离性理解
    浅谈CSS和JQuery实现鼠标悬浮图片放大效果
    jvm 类加载器
    jvm 类加载
    Spring 启动 Bean加载流程
    优雅的博客园客户端发布Forms版啦。
    Xamarin Forms中WebView的自适应高度
    2017回顾与2018目标
    优雅的博客园Android客户端
  • 原文地址:https://www.cnblogs.com/shengyu-kmust/p/8276737.html
Copyright © 2011-2022 走看看