电子政务网站建设/网站优化公司怎么选
文章目录
- 中间件:掌控请求处理过程的关键
- 1. 中间件
- 1.1 中间件工作原理
- 1.2 中间件核心对象
- 2.异常处理中间件:区分真异常和逻辑异常
- 2.1 处理异常的方式
- 2.1.1 日常错误处理--定义错误页的方法
- 2.1.2 使用代理方法处理异常
- 2.1.3 异常过滤器 IExceptionFilter
- 2.1.4 特性过滤 ExceptionFilterAttribute
- 2.1.5 异常处理技巧总结
- 3 静态文件中间件: 前后端分离开发合并部署
- 3.1 静态文件中间件的能力
- 3.2 注册使用非www.root目录
- 4 文件提供程序:将文件放在任何地方
- 4.1 文件提供程序核心类型
- 4.2 内置文件提供程序
中间件:掌控请求处理过程的关键
1. 中间件
1.1 中间件工作原理
1.2 中间件核心对象
- IApplicationBuilder
- RequestDelegate
IApplicationBuilder可以通过委托方式注册中间件,委托的入参也是委托,这就可以将这些委托注册成一个链,如上图所示;最终会调用Builder方法返回一个委托,这个委托就是把所有的中间件串起来后合并成的一个委托方法,Builder的委托入参是HttpContext(实际上所有的委托都是对HttpContext进行处理);
RequestDelegate是处理整个请求的委托。
中间件的执行顺序和注册顺序是相关的
//注册委托方式,注册自己逻辑// 对所有请求路径app.Use(async (context, next) =>{await next();await context.Response.WriteAsync("Hello2");});// 对特定路径指定中间件,对/abc路径进行中间件注册处理app.Map("/abc", abcBuilder =>{// Use表示注册一个完整的中间件,将next也注册进去abcBuilder.Use(async (context, next) =>{await next();await context.Response.WriteAsync("abcHello");});});// Map复杂判断,判断当前请求是否符合某种条件app.MapWhen(context =>{return context.Request.Query.Keys.Contains("abc");}, builder =>{// 使用Run表示这里就是中间件的执行末端,不再执行后续中间件builder.Run(async context =>{await context.Response.WriteAsync("new abc");});});
应用程序一旦开始向Response进行write时,后续的中间件就不能再操作Head,否则会报错
可以通过context.Resopnse.HasStarted方法判断head是否已经被操作
- 设计自己的中间件
中间件的设计时才有的约定的方式,即在方法中包含Invoke或者InvokeAsync,如下:
public class MyMiddleware{private readonly RequestDelegate next;private readonly ILogger<MyMiddleware> logger;public MyMiddleware(RequestDelegate next,ILogger<MyMiddleware> logger){this.next = next;this.logger = logger;}public async Task InvokeAsync(HttpContext context){using (logger.BeginScope("TraceIndentifier:{TraceIdentifier}",context.TraceIdentifier)){logger.LogDebug("Start");await next(context);logger.LogDebug("End");}}}public static class MyBuilderExtensions
{public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app){return app.UseMiddleware<MyMiddleware>();}
}// 中间件使用
app.UseMyMiddleware();
2.异常处理中间件:区分真异常和逻辑异常
2.1 处理异常的方式
- 异常处理页
- 异常处理匿名委托方法
- IExceptionFilter
- ExceptionFilterAttribute
// startup中的Configureif (env.IsDevelopment()){app.UseDeveloperExceptionPage();// 开发环境下的异常页面,生产环境下是需要被关闭,页面如下图所示app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "LoggingSerilog v1"));
}
2.1.1 日常错误处理–定义错误页的方法
// startup中的Configure
app.UseExceptionHandler("/error");// 控制器
public class ErrprController : Controller
{[Route("/error")]public IActionResult Index(){// 获取上下文中的异常var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();var ex = exceptionHandlerPathFeature?.Error;var knowException = ex as IKnowException;if(knowException == null){var logger = HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();logger.LogError(ex,ex.Message);knowException = KnowException.Unknow;}else{knowException = KnowException.FromKnowException(knowException);}return View(knowException);}
}// 定义接口
public interface IKnowException
{public string Message {get;}public int ErrorCode {get;}public object[] ErrorData {get;}
}// 定义实现
public class KnowException : IKnowException
{public string Message {get;private set;}public int ErrorCode {get;private set;}public object[] ErrorData {get;private set;}public readonly static IKnowException Uknow = new KnowException{Message = "未知错误",ErrorCode = 9999};public static IKnowException FromKnowException(IKnowException exception){return new KnowException{Message = exception.Message,ErrorCode = exception.ErrorCode,ErrorData = exception.ErrorData};}
}// 需要定义一个错误页面 index.html,输出错误Message和ErrorCode
2.1.2 使用代理方法处理异常
// startup中的Configure
app.UseExceptionHandler(errApp =>
{errApp.Run(async context =>{var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();var ex = exceptionHandlerPathFeature?.Error;var knowException = ex as IKnowException;if(knowException == null){var logger = HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();logger.LogError(exceptionHandlerPathFeature.Error,exceptionHandlerPathFeature.Error.Message);knowException = KnowException.Unknow;context.Response.StatusCode = StatusCodes.Status500InternalServerError;}else{knowException = KnowException.FromKnowException(knowException);context.Response.StatusCode = StatusCodes.Status200OK;}var jsonOptions = context.RequestServices.GetService<Options<JsonOptions>>();context.Response.ContextType = "application/json";charset=utf-8";await context.Response.WriteAsync(System.Text.Json.JsonSerializer(knowException,jsonOptions.Value));});
});
- 未知异常输出Http500响应,已知异常输出Http200
因为监控系统会对Http响应码进行识别,如果返回的500比率比较高的时候,会认为系统的可用性有问题,告警系统会发出警告。对已知异常进行200响应能够让告警系统正常运行,能够正确识别系统一些未知的错误,使告警系统更加灵敏,避免了业务逻辑的异常干扰告警系统
2.1.3 异常过滤器 IExceptionFilter
异常过滤器是作用在整个MVC框架体系之下,在MVC整个声明周期中发生作用,也就是说它只能工作早MVC Web Api的请求周期里面
// 自定义异常过滤器
public class MyException : IExceptionFilter
{public void OnException(ExceptionContext context){IKnowException knowException = context.Exception as IKnowException;if(knowException == null){var loger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();logger.LogError(context.Exception,context.Exception.Message);knowException = KnowException.UnKnow;context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;}else{knowException = KnowException.FromKnowException(knowException);context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;}context.Result = new JsonResult(knowException){ContextType = "application/json:charset=utf-8"}}
}// startup注册
public void ConfigureServices(IServiceCollection services)
{services.AddMvc(mvcoption => {mvcOptions.Filters.Add<MyExceptionFilter>();}).AddJsonOptions(jsonOptions => {jsonOptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscapt});
}
2.1.4 特性过滤 ExceptionFilterAttribute
public class MyExceptionFilterAttriburte : ExceptionFilterAttribute
{public override void OnException(ExceptionContext context){IKnowException knowException = context.Exception as IKnowException;if(knowException == null){var logger = context.HttpContext.RequestServices.GetServices<ILogger<MyExceptionFilterAttribute>>();logger.LogError(context.Exception,context.Exception.Message);knowException = KnowException.UnKnow;context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;}else{knowException = KnowException.FromKnowException(knowException);context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;}context.Result = new JsonResult(knowException){ContextType = "application/json:charset=utf-8"}}
}// 使用方式
在Controller控制器上方标注[MyExceptionFilter]
或者在 startup中ConfigureServices注册
services.AddMvc(mvcoption => {mvcOptions.Filters.Add<MyExceptionFilterAttribute>();});
2.1.5 异常处理技巧总结
- 用特定的异常类或接口表示业务逻辑异常
- 为业务逻辑异常定义全局错误码
- 为未知异常定义定义特定的输出信息和错误码
- 对于已知业务逻辑异常响应HTTP 200(监控系统友好)
- 对于未预见的异常响应HTTP 500
- 为所有的异常记录详细的日志
3 静态文件中间件: 前后端分离开发合并部署
3.1 静态文件中间件的能力
- 支持指定相对路径
- 支持目录浏览
- 支持设置默认文档
- 支持多目录映射
// startup的Configure方法中
app.UseDefaultFiles();// 设置默认访问根目录文件index.html
app.UseStaticFiles();// 将www.root目录映射出去
如果需要浏览文件目录,需要如下配置
// startup中的ConfigureServices中配置
services.AddDirectoryBrowser();// startup的Configure方法中
app.UseDirectoryBrowser();
app.UseStaticFiles();
3.2 注册使用非www.root目录
// startup的Configure方法中
app.UseStaticFiles();app.UseStaticFiles(new StaticFileOptions
{// 将程序中名为file文件目录注入RequestPath = "/files",// 设置文件指定访问路径,将文件目录映射为指定的Url地址FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"file"))
});
实际生产中会遇到将非api请求重定向到指定目录,采用如下配置
// startup的Configure方法中
app.MapWhen(context =>
{return !context.Request.Path.Value.StartWith("/api");
},appBuilder =>
{var option = new RewriteOptions();option.AddRewrite(".*","/index.html",true);appBuilder.UseRewriter(option);appBuilder.UseStaticFiles();
});
4 文件提供程序:将文件放在任何地方
4.1 文件提供程序核心类型
- IFileProvider
- IFileInfo
- IDirectoryContexts
4.2 内置文件提供程序
- PhysicalFileProvider⇒ 物理文件提供程序
- EmbeddedFileProvider ⇒ 嵌入式文件提供程序
- CompositeFileProvoder ⇒ 组合文件提供程序,将各种文件程序组合成一个目录
// 映射指定目录文件- 物理文件
IFileProvider provider1 = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);
// 获取文件目录下内容
var contents = provider1.GetDirectoryContents("/");
// 输出文件信息
foreach (var item in contents)
{var stream = item.CreateReadStream();// 获取文件流Console.WriteLine(item.Name);
}// 嵌入式文件
IFileProvider fileProvider2 = new EmbeddedFileProvider(typeof(Program).Assembly);
var html = fileProvider2.GetFileInfo("file.html");// file.html文件属性设置为嵌入的资源// 组合文件提供程序
IFileProvider fileProvider3 = new CompositeFileProvider(provider1,fileProvider2);
var contexts3 = fileProvider3.GetDirectoryContents("/");
相关文章:

【NetCore】09-中间件
文章目录 中间件:掌控请求处理过程的关键1. 中间件1.1 中间件工作原理1.2 中间件核心对象 2.异常处理中间件:区分真异常和逻辑异常2.1 处理异常的方式2.1.1 日常错误处理--定义错误页的方法2.1.2 使用代理方法处理异常2.1.3 异常过滤器 IExceptionFilter2.1.4 特性过…...

机器学习深度学习——BERT(来自transformer的双向编码器表示)
👨🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——transformer(机器翻译的再实现) 📚订阅专栏:机器学习&am…...

Datawhale Django后端开发入门 Vscode TASK02 Admin管理员、外键的使用
一.Admin管理员的使用 1、启动django服务 使用创建管理员之前,一定要先启动django服务,虽然TASK01和TASK02是分开的,但是进行第二个流程的时候记得先启动django服务,注意此时是在你的项目文件夹下启动的,时刻注意要执…...

【ES5和ES6】数组遍历的各种方法集合
一、ES5的方法 1.for循环 let arr [1, 2, 3] for (let i 0; i < arr.length; i) {console.log(arr[i]) } // 1 // 2 // 32.forEach() 特点: 没有返回值,只是针对每个元素调用func三个参数:item, index, arr ;当前项&#…...

学科在线教育元宇宙VR虚拟仿真平台落实更高质量的交互学习
为推动教育数字化,建设全民终身学习的学习型社会、学习型大国,元宇宙企业深圳华锐视点深度融合VR虚拟现实、数字孪生、云计算和三维建模等技术,搭建教育元宇宙平台,为学生提供更加沉浸式的学习体验,提高学习效果和兴趣…...

[python爬虫] 爬取图片无法打开或已损坏的简单探讨
本文主要针对python使用urlretrieve或urlopen下载百度、搜狗、googto(谷歌镜像)等图片时,出现"无法打开图片或已损坏"的问题,作者对它进行简单的探讨。同时,作者将进一步帮你巩固selenium自动化操作和urllib…...

vue项目预览pdf功能(解决动态文字无法显示的问题)
最近,因为公司项目需要预览pdf的功能,开始的时候找了市面上的一些pdf插件,都能用,但是,后面因为pdf变成了需要根据内容进行变化的,然后,就出现了需要动态生成的文字不显示了。换了好多好多的插件…...

vue3 样式穿透:deep不生效
初学vue3,今天需要修改el-input组件的属性(去掉border和文字居右) 网上搜了一下,大致都是采用:deep 样式穿透来修改el-input的属性 <div class"input-container"><el-input placeholder"请输入111&qu…...

云原生反模式
通过了解这些反模式并遵循云原生最佳实践,您可以设计、构建和运营更加强大、可扩展和成本效益高的云原生应用程序。 1.单体架构:在云上运行一个大而紧密耦合的应用程序,妨碍了可扩展性和敏捷性。2.忽略成本优化:云服务可能昂贵&am…...

【2023年11月第四版教材】《第5章-信息系统工程(合集篇)》
《第5章-信息系统工程(合集篇)》 章节说明1 软件工程1.1 架构设计1.2 需求分析1.3 软件设计1.4 软件实现[补充第三版教材内容] 1.5 部署交付 2 数据工程2.1 数据建模2.2 数据标准化2.3 数据运维2.4 数据开发利用2.5 数据库安全 3 …...

【qiankun】微前端在项目中的具体使用
1、安装qiankun npm install qiankun --save2、主应用中注册和配置qiankun 在主应用的入口文件main.ts中,引入qiankun的注册方法: import { registerMicroApps, start } from qiankun;创建一个数组,用于配置子应用的相关信息。每个子应用都…...

云安全与多云环境管理:讨论在云计算和多云环境下如何保护数据、应用程序和基础设施的安全
随着云计算和多云环境的广泛应用,企业正面临着数据、应用程序和基础设施安全的新挑战。在这个数字化时代,保护敏感信息和业务运作的连续性变得尤为重要。本文将深入探讨在云计算和多云环境下如何有效地保护数据、应用程序和基础设施的安全。 章节一&…...

npm install ffi各种失败,换命令npm i ffi-napi成功
网上各种帖子安装ffi,基本上到了windows build tools这里会卡住。 使用命令npm install --global --production windows-build-tools 安装报错信息如下: PS E:\codes\nodejsPath\tcpTest> npm install --global --production windows-build-tools …...

0.flink学习资料
论文: (1)google dataflow model 下载链接:p1792-Akidau.pdf (vldb.org) Akidau T, Bradshaw R, Chambers C, et al. The dataflow model: a practical approach to balancing correctness, latency, and cost in massive-scal…...

C语言:字符函数和字符串函数
往期文章 C语言:初识C语言C语言:分支语句和循环语句C语言:函数C语言:数组C语言:操作符详解C语言:指针详解C语言:结构体C语言:数据的存储 目录 往期文章前言1. 函数介绍1.1 strlen1.…...

基于.Net Core开发的医疗信息LIS系统源码
SaaS模式.Net Core版云LIS系统源码 医疗信息LIS系统是专为医院检验科设计的一套实验室信息管理系统,能将实验仪器与计算机组成网络,使病人样品登录、实验数据存取、报告审核、打印分发,实验数据统计分析等繁杂的操作过程实现了智能化、自动化…...

部署工业物联网可以选择哪些通信方案?
部署工业物联网有诸多意义,诸如提升生产效率,降低管理成本,保障生产品质稳定,应对长期从业劳动力变化趋势等。针对不同行业、场景,工业物联网需要选择不同的通信方案,以达到成本和效益的最佳平衡。本篇就简…...

flutter-移动端适配
不同屏幕之间的尺寸适配 使用插件 flutter_screenutil flutter_screenutil flutter 屏幕适配方案,用于调整屏幕和字体大小的flutter插件,让你的UI在不同尺寸的屏幕上都能显示合理的布局! 安装 # add flutter_screenutil flutter_screenutil: ^5.8.4 o…...

MySQL 常用函数
一、数学函数 1、ABS(x) 返回绝对值。 mysql> select abs(-4); --------- | abs(-4) | --------- | 4 | --------- 1 row in set (0.00 sec) 2、PI() 返回圆周率,并四舍五入保留五位小数。 mysql> select pi(); ----------…...

动态路由的实现—正则表达式
文章目录 前言一、什么是正则表达式?二、正则表达式在动态路由中的作用三、实现一个简单的路由调度器总结 前言 动态路由有很多种实现方式,支持的规则、性能等有很大的差异。例如开源的路由实现gorouter支持在路由规则中嵌入正则表达式,例如…...

Android实现超出固定行数折叠文字“查看全文“、“收起全文“
先上效果图 分析问题 网上有很多关于这个的代码,实现都过于复杂了,github上甚至还看到一篇文章600多行代码,结果一跑起来全是bug。还是自己写吧!!! 如果我们需要换行的"查看全文"、"收起全…...

Python上楼梯问题:递归解法探究(斐波那契变种)(记忆化递归)
文章目录 上楼梯问题:递归解法探究问题定义解决方案1. 递归2. 记忆化递归关于python memo{}默认参数和字典的语法语法功能版本信息注意事项 结论 上楼梯问题:递归解法探究 在这篇文章中,将对上楼梯问题进行深入探讨。上楼梯问题是一种常见的…...

AI重新定义音视频生产力“新范式”
// 编者按:AIGC无疑是当下的热门话题和场景。面对AI带来的技术变革和算力挑战,该如何应对?LiveVideoStackCon 2023上海站邀请到了网心科技副总裁武磊为我们分享网心在面对AI应用场景和业务需求下的实践经验。 文/武磊 编辑/LiveVideoStack …...

Jmeter生成可视化的HTML测试报告
Jmeter也是可以生成测试报告的。 性能测试工具Jmeter由于其体积小、使用方便、学习成本低等原因,在现在的性能测试过程中,使用率越来越高,但其本身也有一定的缺点,比如提供的测试结果可视化做的很一般。 不过从3.0版本开始&…...

5G技术与其对智能城市、物联网和虚拟现实领域的影响
随着第五代移动通信技术(5G)的到来,我们即将迈向一个全新的数字化世界。5G技术的引入将带来更高的速度、更低的延迟和更大的连接性,推动了智能城市、物联网和虚拟现实等领域的发展。 首先,5G技术将带来超越以往的网络速…...

leetcode做题笔记88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意:最终,合并后数组…...

stm32开关控制led灯泡(附Proteus电路图)
说明:我的灯泡工作电压2V,电流设置为10um,注意了不是10毫安时微安啊,要不然电流太小亮不起来的。 2:我用的开关不是按钮button而是switch, 3:PB0,PB1默认都是低电平,采用了PULLDOWN模式,如果设…...

win10 wsl ubuntu 更换版本为18.04 apt换国内源Python换国内源;默认root
控制面板里面应用模块找到Ubuntu,可以卸载或者移动到其他盘。 Microsoft 应用程序 - ubuntu https://apps.microsoft.com/store/search/ubuntu?hlzh-cn&glcn&rtc1 选择想要的版本安装。 cp /etc/apt/sources.list /etc/apt/sources.list.bak nano /etc/ap…...

C++ Primer 第1章 开始
C Primer 第1章 开始 1.1 编写一个简单的C程序1.1.1 编译、运行程序一、程序源文件命名约定二、从命令行运行编译器 练习 1.2 初识输入输出一、标准输入输出对象二、一个使用IO库的程序三、向流写入数据四、使用标准库中的名字五、从流读取数据六、完成程序 1.3 注释简介一、C中…...

【STM32 学习】电源解析(VCC、VDD、VREF+、VBAT)
VCC电源电压GND电源供电负电压(通常接地)VDD模块工作正电压VSS模块工作负电压VREFADC参考正电压VREF-ADC参考负电压VBAT电池或其他电源供电VDDA模拟供电正电压VSSA模拟供电负电压 一、VCC(供电电压) VCC是指芯片的电源电压&#…...