<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Util應(yīng)用框架基礎(chǔ)(五) - 異常處理

      本節(jié)介紹Util應(yīng)用框架如何處理系統(tǒng)錯(cuò)誤.

      概述

      系統(tǒng)在運(yùn)行過(guò)程中可能發(fā)生錯(cuò)誤.

      系統(tǒng)錯(cuò)誤可以簡(jiǎn)單分為兩類:

      • 系統(tǒng)異常

        系統(tǒng)本身出現(xiàn)的錯(cuò)誤.

      • 業(yè)務(wù)異常

        不滿足業(yè)務(wù)規(guī)則出現(xiàn)的錯(cuò)誤.

      如何處理系統(tǒng)異常

      如果發(fā)生系統(tǒng)異常,大多數(shù)情況下,你除了記錄異常日志外,可能無(wú)法處理它們.

      一個(gè)例外是并發(fā)異常.

      當(dāng)發(fā)生并發(fā)異常,可以通過(guò)重試再次提交,有可能成功處理.

      另外一個(gè)問(wèn)題,是否應(yīng)該將系統(tǒng)異常消息返回給客戶端?

      系統(tǒng)異常消息與技術(shù)相關(guān),客戶無(wú)法理解它們.

      而且系統(tǒng)異常消息可能包含敏感信息,返回給客戶端可能更易受到攻擊.

      如何處理業(yè)務(wù)異常

      業(yè)務(wù)異常表明沒(méi)有滿足某些業(yè)務(wù)規(guī)則,通常也無(wú)法自動(dòng)處理.

      如果能夠自動(dòng)處理的業(yè)務(wù)異常,應(yīng)定義專用異常類型.

      對(duì)于業(yè)務(wù)異常,除了記錄異常日志外,還應(yīng)把業(yè)務(wù)異常消息返回給客戶端,以指示用戶調(diào)整操作.

      基礎(chǔ)用法

      .Net 使用異常 Exception 及派生異常來(lái)處理系統(tǒng)異常,但沒(méi)有明確規(guī)定處理業(yè)務(wù)異常的類型.

      Warning 業(yè)務(wù)異常

      Util應(yīng)用框架定義了 Util.Exceptions.Warning 異常類型,Warning 從 Exception 派生,代表業(yè)務(wù)異常.

      當(dāng)你拋出 Exception 或派生異常類型時(shí),異常消息僅在開(kāi)發(fā)階段返回給客戶端.

      一旦發(fā)布到生產(chǎn)環(huán)境,系統(tǒng)異常消息將被屏蔽,客戶端收到消息: 系統(tǒng)忙,請(qǐng)稍后再試 .

      throw new Exception( "未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例" );
      

      對(duì)于業(yè)務(wù)規(guī)則導(dǎo)致的錯(cuò)誤,你需要拋出 Warning 異常.

      Warning 拋出的異常消息將返回到客戶端,提示用戶進(jìn)行修改.

      throw new Warning( "必須填寫(xiě)姓名" );
      

      GetMessage 工具方法

      Warning 除了代表業(yè)務(wù)異常外,還提供了一個(gè)靜態(tài)工具方法 GetMessage.

      異常可能被其它異常包裹,要獲得異常真正的消息,需要使用遞歸.

      Warning.GetMessage 工具方法傳入異常實(shí)例,遞歸獲取異常消息,

      var message = Warning.GetMessage( exception );
      

      ConcurrencyException 并發(fā)異常

      Util應(yīng)用框架定義了并發(fā)異常 Util.Exceptions.ConcurrencyException.

      不同的 .Net 組件拋出的并發(fā)異常類型可能不同, Util使用 ConcurrencyException 進(jìn)行統(tǒng)一包裝.

      可以通過(guò)重試的方式來(lái)解決并發(fā)異常.

      下面是Util應(yīng)用框架Dapr集成事件增加計(jì)數(shù)時(shí)并發(fā)處理的代碼片斷.

      public virtual async Task IncrementAsync( CancellationToken cancellationToken = default ) {
          try {
              await Store.IncrementAsync( cancellationToken );
          }
          catch ( ConcurrencyException ) {
              Log.LogDebug( "更新集成事件計(jì)數(shù)出現(xiàn)并發(fā)異常,即將重試" );
              await IncrementAsync( cancellationToken );
          }
          catch ( Exception exception ) {
              Log.LogError( exception, "更新集成事件計(jì)數(shù)失敗" );
          }
      }
      

      全局錯(cuò)誤日志記錄

      Util應(yīng)用框架使用 ErrorLogFilterAttribute 過(guò)濾器來(lái)記錄全局錯(cuò)誤日志.

      已在 Web Api控制器基類 WebApiControllerBase 設(shè)置 [ErrorLogFilter] 過(guò)濾器.

      全局異常處理

      Util應(yīng)用框架使用 ExceptionHandlerAttribute 過(guò)濾器來(lái)處理全局異常.

      已在 Web Api控制器基類 WebApiControllerBase 設(shè)置 [ExceptionHandler] 過(guò)濾器.

      [ExceptionHandler] 過(guò)濾器對(duì)異常消息進(jìn)行處理,只有 Warning 異常消息才會(huì)返回給客戶端.

      源碼解析

      Warning 業(yè)務(wù)異常

      Warning 代表業(yè)務(wù)異常,它的異常消息會(huì)返回給客戶端.

      GetMessage 方法使用遞歸獲取內(nèi)部異常消息.

      /// <summary>
      /// 應(yīng)用程序異常
      /// </summary>
      public class Warning : Exception {
          /// <summary>
          /// 初始化應(yīng)用程序異常
          /// </summary>
          /// <param name="exception">異常</param>
          public Warning( Exception exception )
              : this( null, exception ) {
          }
      
          /// <summary>
          /// 初始化應(yīng)用程序異常
          /// </summary>
          /// <param name="message">錯(cuò)誤消息</param>
          /// <param name="exception">異常</param>
          /// <param name="code">錯(cuò)誤碼</param>
          /// <param name="httpStatusCode">Http狀態(tài)碼</param>
          public Warning( string message, Exception exception = null, string code = null, int? httpStatusCode = null )
              : base( message ?? "", exception ) {
              Code = code;
              HttpStatusCode = httpStatusCode;
              IsLocalization = true;
          }
      
          /// <summary>
          /// 錯(cuò)誤碼
          /// </summary>
          public string Code { get; set; }
      
          /// <summary>
          /// Http狀態(tài)碼
          /// </summary>
          public int? HttpStatusCode { get; set; }
      
          /// <summary>
          /// 是否本地化異常消息
          /// </summary>
          public bool IsLocalization { get; set; }
      
          /// <summary>
          /// 獲取錯(cuò)誤消息
          /// </summary>
          /// <param name="isProduction">是否生產(chǎn)環(huán)境</param>
          public virtual string GetMessage( bool isProduction = false ) {
              return GetMessage( this );
          }
      
          /// <summary>
          /// 獲取錯(cuò)誤消息
          /// </summary>
          public static string GetMessage( Exception ex ) {
              var result = new StringBuilder();
              var list = GetExceptions( ex );
              foreach( var exception in list )
                  AppendMessage( result, exception );
              return result.ToString().Trim( Environment.NewLine.ToCharArray() );
          }
      
          /// <summary>
          /// 添加異常消息
          /// </summary>
          private static void AppendMessage( StringBuilder result, Exception exception ) {
              if( exception == null )
                  return;
              result.AppendLine( exception.Message );
          }
      
          /// <summary>
          /// 獲取異常列表
          /// </summary>
          public IList<Exception> GetExceptions() {
              return GetExceptions( this );
          }
      
          /// <summary>
          /// 獲取異常列表
          /// </summary>
          /// <param name="ex">異常</param>
          public static IList<Exception> GetExceptions( Exception ex ) {
              var result = new List<Exception>();
              AddException( result, ex );
              return result;
          }
      
          /// <summary>
          /// 添加內(nèi)部異常
          /// </summary>
          private static void AddException( List<Exception> result, Exception exception ) {
              if( exception == null )
                  return;
              result.Add( exception );
              AddException( result, exception.InnerException );
          }
      }
      

      ConcurrencyException 并發(fā)異常

      ConcurrencyException 表示并發(fā)異常,統(tǒng)一包裝其它組件產(chǎn)生的并發(fā)異常,并處理異常消息.

      /// <summary>
      /// 并發(fā)異常
      /// </summary>
      public class ConcurrencyException : Warning {
          /// <summary>
          /// 消息
          /// </summary>
          private readonly string _message;
      
          /// <summary>
          /// 初始化并發(fā)異常
          /// </summary>
          public ConcurrencyException()
              : this( "" ) {
          }
      
          /// <summary>
          /// 初始化并發(fā)異常
          /// </summary>
          /// <param name="exception">異常</param>
          public ConcurrencyException( Exception exception )
              : this( "", exception ) {
          }
      
          /// <summary>
          /// 初始化并發(fā)異常
          /// </summary>
          /// <param name="message">錯(cuò)誤消息</param>
          /// <param name="exception">異常</param>
          /// <param name="code">錯(cuò)誤碼</param>
          /// <param name="httpStatusCode">Http狀態(tài)碼</param>
          public ConcurrencyException( string message, Exception exception = null, string code = null, int? httpStatusCode = null )
              : base( message, exception, code, httpStatusCode ) {
              _message = message;
          }
      
          /// <inheritdoc />
          public override string Message => $"{R.ConcurrencyExceptionMessage}.{_message}";
      
          /// <inheritdoc />
          public override string GetMessage( bool isProduction = false ) {
              if( isProduction )
                  return R.ConcurrencyExceptionMessage;
              return GetMessage(this);
          }
      }
      

      ErrorLogFilterAttribute 錯(cuò)誤日志過(guò)濾器

      [ErrorLogFilter] 錯(cuò)誤日志過(guò)濾器記錄全局異常日志.

      /// <summary>
      /// 錯(cuò)誤日志過(guò)濾器
      /// </summary>
      public class ErrorLogFilterAttribute : ExceptionFilterAttribute {
          /// <summary>
          /// 異常處理
          /// </summary>
          public override void OnException( ExceptionContext context ) {
              if( context == null )
                  return;
              var log = context.HttpContext.RequestServices.GetService<ILogger<ErrorLogFilterAttribute>>();
              var exception = context.Exception.GetRawException();
              if( exception is Warning warning ) {
                  log.LogWarning( warning, exception.Message );
                  return;
              }
              log.LogError( exception, exception.Message );
          }
      }
      

      ExceptionHandlerAttribute 異常處理過(guò)濾器

      [ExceptionHandler] 過(guò)濾器處理全局異常.

      Exception 的擴(kuò)展方法 GetPrompt 獲取客戶端友好的異常消息.

      對(duì)于生產(chǎn)環(huán)境, Exception 異常消息將被替換為 系統(tǒng)忙,請(qǐng)稍后再試.

      [ExceptionHandler] 過(guò)濾器還對(duì)異常消息的本地化進(jìn)行了處理.

      /// <summary>
      /// 異常處理過(guò)濾器
      /// </summary>
      public class ExceptionHandlerAttribute : ExceptionFilterAttribute {
          /// <summary>
          /// 異常處理
          /// </summary>
          public override void OnException( ExceptionContext context ) {
              context.ExceptionHandled = true;
              var message = context.Exception.GetPrompt( Web.Environment.IsProduction() );
              message = GetLocalizedMessages( context, message );
              var errorCode = context.Exception.GetErrorCode() ?? StateCode.Fail;
              var httpStatusCode = context.Exception.GetHttpStatusCode() ?? 200;
              context.Result = GetResult( context, errorCode, message, httpStatusCode );
          }
      
          /// <summary>
          /// 獲取本地化異常消息
          /// </summary>
          protected virtual string GetLocalizedMessages( ExceptionContext context, string message ) {
              var exception = context.Exception.GetRawException();
              if ( exception is Warning { IsLocalization: false } ) 
                  return message;
              var stringLocalizerFactory = context.HttpContext.RequestServices.GetService<IStringLocalizerFactory>();
              if ( stringLocalizerFactory == null )
                  return message;
              var stringLocalizer = stringLocalizerFactory.Create( "Warning",null );
              var localizedString = stringLocalizer[message];
              if ( localizedString.ResourceNotFound == false )
                  return localizedString.Value;
              stringLocalizer = context.HttpContext.RequestServices.GetService<IStringLocalizer>();
              if ( stringLocalizer == null )
                  return message;
              return stringLocalizer[message];
          }
      
          /// <summary>
          /// 獲取結(jié)果
          /// </summary>
          protected virtual IActionResult GetResult( ExceptionContext context, string code, string message, int? httpStatusCode ) {
              var options = GetJsonSerializerOptions( context );
              var resultFactory = context.HttpContext.RequestServices.GetService<IResultFactory>();
              if ( resultFactory == null )
                  return new Result( code, message, null, httpStatusCode, options );
              return resultFactory.CreateResult( code, message, null, httpStatusCode, options );
          }
      
          /// <summary>
          /// 獲取Json序列化配置
          /// </summary>
          private JsonSerializerOptions GetJsonSerializerOptions( ExceptionContext context ) {
              var factory = context.HttpContext.RequestServices.GetService<IJsonSerializerOptionsFactory>();
              if( factory != null )
                  return factory.CreateOptions();
              return new JsonSerializerOptions {
                  PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                  Encoder = JavaScriptEncoder.Create( UnicodeRanges.All ),
                  DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
                  Converters = {
                      new DateTimeJsonConverter(),
                      new NullableDateTimeJsonConverter()
                  }
              };
          }
      }
      
      /// <summary>
      /// 異常擴(kuò)展
      /// </summary>
      public static class ExceptionExtensions {
          /// <summary>
          /// 獲取異常提示
          /// </summary>
          /// <param name="exception">異常</param>
          /// <param name="isProduction">是否生產(chǎn)環(huán)境</param>
          public static string GetPrompt( this Exception exception, bool isProduction = false ) {
              if( exception == null )
                  return null;
              exception = exception.GetRawException();
              if( exception == null )
                  return null;
              if( exception is Warning warning )
                  return warning.GetMessage( isProduction );
              return isProduction ? R.SystemError : exception.Message;
          }
      
          /// <summary>
          /// 獲取Http狀態(tài)碼
          /// </summary>
          /// <param name="exception">異常</param>
          public static int? GetHttpStatusCode( this Exception exception ) {
              if ( exception == null )
                  return null;
              exception = exception.GetRawException();
              if ( exception == null )
                  return null;
              if ( exception is Warning warning )
                  return warning.HttpStatusCode;
              return null;
          }
      
          /// <summary>
          /// 獲取錯(cuò)誤碼
          /// </summary>
          /// <param name="exception">異常</param>
          public static string GetErrorCode( this Exception exception ) {
              if ( exception == null )
                  return null;
              exception = exception.GetRawException();
              if ( exception == null )
                  return null;
              if ( exception is Warning warning )
                  return warning.Code;
              return null;
          }
      }
      
      posted @ 2023-11-07 14:32  何鎮(zhèn)汐  閱讀(597)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产97色在线 | 免| 天天做天天爱夜夜爽导航| 日韩精品国产二区三区| 久久午夜无码鲁丝片直播午夜精品| 国产av仑乱内谢| 无码人妻精品一区二区三区东京热| 欧美一区二区三区成人久久片| 国产自在自线午夜精品| 国产成人午夜精品永久免费| 精品熟女日韩中文十区| 99精品国产成人一区二区| 亚洲日本乱码在线观看| 综合在线 亚洲 成人 欧美| 宽甸| 国产综合精品91老熟女| 久久国产精品久久久久久 | 奇米影视7777久久精品| 久久久久香蕉国产线看观看伊| 亚洲欧美综合精品成| 伊人中文在线最新版天堂| 伦伦影院午夜理论片| 熟女一区| 丝袜美腿亚洲综合第一页| 无码国产精品一区二区VR老人| 无码人妻精品一区二区三区下载| 四虎网址| 国产一区二区三区色噜噜| 亚洲人妻系列中文字幕| 亚洲精品国模一区二区| 综合色一色综合久久网| 国产精品中文一区二区| 亚洲精品国产精品乱码不| 亚洲av第三区国产精品| 亚洲国产精品综合久久2007| 成人免费无码大片A毛片抽搐色欲| 亚洲乱亚洲乱妇50p| 精品无码成人片一区二区| 左贡县| 黄色A级国产免费大片视频| 国产gaysexchina男外卖| 国产在线亚州精品内射|