123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
-
- using Microsoft.Data.SqlClient;
- namespace OASystem.API.Middlewares
- {
- /// <summary>
- /// 全局异常捕获中间件
- /// </summary>
- public class ExceptionHandlingMiddleware
- {
- private readonly RequestDelegate _next; // 用来处理上下文请求
- private readonly ILogger<ExceptionHandlingMiddleware> _logger;
- private readonly SqlSugarClient _db;
- /// <summary>
- /// 初始化
- /// </summary>
- /// <param name="next"></param>
- /// <param name="logger"></param>
- /// <param name="db"></param>
- public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger, SqlSugarClient db)
- {
- _next = next;
- _logger = logger;
- _db = db;
- }
- /// <summary>
- /// 执行中间件
- /// </summary>
- /// <param name="httpContext"></param>
- /// <param name="db"></param>
- /// <returns></returns>
- public async Task InvokeAsync(HttpContext httpContext, SqlSugarClient db)
- {
- try
- {
- await _next(httpContext); //要么在中间件中处理,要么被传递到下一个中间件中去
- }
- catch (Exception ex)
- {
- await HandleExceptionAsync(httpContext, ex, db); // 捕获异常了 在HandleExceptionAsync中处理
- }
- }
- /// <summary>
- /// 自定义全局异常处理方法
- /// </summary>
- /// <param name="context"></param>
- /// <param name="exception"></param>
- /// <param name="db"></param>
- /// <returns></returns>
- private async Task HandleExceptionAsync(HttpContext context, Exception exception, SqlSugarClient db)
- {
- if (db.Ado != null && db.Ado.Transaction != null)
- {
- try
- {
- db.Ado.RollbackTran();
- }
- catch (Exception ex)
- {
- _logger.LogError("Error rolling back transaction: {ErrorMessage}", ex.Message);
- }
- }
- // 检查响应是否已开始
- if (!context.Response.HasStarted)
- {
- context.Response.ContentType = "application/json"; // 设置响应内容类型为 JSON
- var response = context.Response;
- var errorResponse = new JsonView
- {
- Code = StatusCodes.Status500InternalServerError,
- Data = ""
- };
- // 根据异常类型设置不同的响应状态码和消息
- switch (exception)
- {
- case SqlException sqlEx when sqlEx.Number == -2:
- response.StatusCode = StatusCodes.Status503ServiceUnavailable;
- errorResponse.Msg = "数据库连接超时,请稍后重试。";
- break;
- case SqlException sqlEx when sqlEx.Number == -4:
- response.StatusCode = StatusCodes.Status503ServiceUnavailable;
- errorResponse.Msg = "数据库连接池耗尽,请稍后重试。";
- break;
- case ApplicationException ex when ex.Message.Contains("Invalid token"):
- response.StatusCode = StatusCodes.Status403Forbidden;
- errorResponse.Msg = ex.Message;
- break;
- case ApplicationException ex:
- response.StatusCode = StatusCodes.Status400BadRequest;
- errorResponse.Msg = ex.Message;
- break;
- case KeyNotFoundException ex:
- response.StatusCode = StatusCodes.Status404NotFound;
- errorResponse.Msg = ex.Message;
- break;
- case SqlSugarException ex:
- response.StatusCode = ex.Message.Contains("timeout")
- ? StatusCodes.Status503ServiceUnavailable
- : StatusCodes.Status500InternalServerError;
- errorResponse.Msg = ex.Message.Contains("timeout")
- ? "数据库连接超时,请稍后重试。"
- : ex.Message;
- break;
- default:
- response.StatusCode = StatusCodes.Status500InternalServerError;
- errorResponse.Msg = "服务器内部错误"; // 不直接暴露异常详细信息
- break;
- }
- _logger.LogError(exception, "An exception occurred."); // 记录异常详细信息
- var result = JsonConvert.SerializeObject(errorResponse);
- await context.Response.WriteAsync(result); // 将错误响应写入客户端
- }
- else
- {
- // 如果响应已开始,记录日志但不做进一步处理
- _logger.LogError(exception, "An exception occurred after response started.");
- }
- }
- }
- }
|