ASP.NET Core 2.2 : 扒一扒新的Endpoint路由方案

2023-11-06 13:48

本文主要是介绍ASP.NET Core 2.2 : 扒一扒新的Endpoint路由方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的。上一篇ASP.NET Core;图解路由(2.1 earler)详细介绍了原版路由方案的运行机制,本文仍然通过一幅图来了解一下新版的运行机制,最后再总结一下二者的异同点。

一、概述

       此方案从2.2版本开始,被称作终结点路由(下文以“新版”称呼),它是默认开启的,若想采用原来的方案(<=2.1,下文以原版称呼),可以在AddMvc的时候进行设置

services.AddMvc(option=>option.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

EnableEndpointRouting 默认为true,也就是启用新的Endpoint方案,设置为false则采用旧版(<=2.1)的路由方案。

        在配置方法上来说,系统仍然采用在Startup中的use.Mvc()中配置,而实际上内部的处理中间件已由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware两个中间件处理,下面依旧通过一幅图来详细看一下:

 二、流程及解析

640?wx_fmt=png

                                                                            图一

为了方便查看,依然对几个“重点对象”做了颜色标识(点击图片可以看大图):

      1. 路由的初始化配置(图的前两个泳道) 

  1. ①  一切依然是从Startup开始,而且和旧版一样,是通过UseMvc方法进行配置,传入routes.MapRoute(...)这样的一个或多个配置, 不做赘述。

  1. 下面着重说一下后面的流程,看一下MvcApplicationBuilderExtensions中的UseMvc方法:

640?wx_fmt=png

② 第6行,这里会获取并判断设置的EnableEndpointRouting的值,若为false,则采用旧版路由,详见上一篇文章;该值默认为true,即采用新版路由。
 ③ 对应第9行,MvcEndpointDataSource在新版路由中是个非常非常重要的角色,在启动初始化阶段,它完成了路由表存储和转换,此处先用颜色重点标记一下,大家记住它,在后面的流程中详细介绍。
 ④ 对应第16行,同旧版的RouteBuilder一样,这里会new一个 endpointRouteBuilder,二者都是一个IRouteBuilder,所以也同样调用configureRoutes(endpointRouteBuilder)方法(也就是startup中的配置)获取了一个Route的集合(IList<IRouter>)赋值给endpointRouteBuilder.Routes,这里有个特别该注意的地方if (router is Route route && router.GetType() == typeof(Route)) ,也就是这里只接受route类型,终结点路由系统不支持基于 IRouter的可扩展性,包括从 Route继承。
⑤ 对应第20行,这里对刚获取到的endpointRouteBuilder.Routes进行遍历,转换成了一个MvcEndpointInfo的集和,赋值给mvcEndpointDataSource.ConventionalEndpointInfos。
⑥ 之后就是向管道塞中间件了,这里的处理中间件由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware。

  2.请求的处理(图的后两个泳道)

       请求的处理大部分功能在中间件EndpointRoutingMiddleware,他有个重要的属性_endpointDataSource保存了上文中初始化阶段生成的MvcEndpointDataSource,而中间件EndpointMiddleware的功能比较简单,主要是在EndpointRoutingMiddleware筛选出endpoint之后,调用该endpoint的endpoint.RequestDelegate(httpContext)进行请求处理。
 ⑦ InitializeAsync()方法主要是用于调用InitializeCoreAsync()创建一个matcher,而通过这个方法的代码可以看出它只是在第一次请求的时候执行一次。

640?wx_fmt=png

   ⑧ MvcEndpointDataSource一个重要的方法UpdateEndpoints(),作用是读取所有action,并将这个action列表与它的ConventionalEndpointInfos列表(见⑤)进行匹配,最终生成一个新的列表。如下图,我们默认情况下只配置了一个"{controller=Home}/{action=Index}/{id?}"这样的路由,默认的HomeController有三个action,添加了一个名为FlyLoloController的controller并添加了一个带属性路由的action,最终生成了7个Endpoint,这有点像路由与action的“乘积”。当然,这里只是用默认程序举了个简单的例子,实际项目中可能会有更多的路由模板注册、会有更多的Controller和Action以及属性路由等。

640?wx_fmt=png

                                                      图二

具体代码如下:

640?wx_fmt=png

640?wx_fmt=png

本质就是计算出一个个可能被请求的请求终结点,也就是Endpoint。由此可见,如上一篇文章那样想自定义一个handler来处理特殊模板的方式(如 routes.MapRoute("flylolo/{code}/{name}", MyRouteHandler.Handler);)将被忽略掉,因其无法生成 Endpoint,且此种方式完全可以自定义一个中间件来实现,没必要混在路由中。

            ⑨ 就是用上面生成的Matcher,携带Endpoint列表与请求URL做匹配,并将匹配到的Endpoint赋值给feature.Endpoint。
            ⑩ 获取feature.Endpoint,若存在则调用其RequestDelegate处理请求httpContext。

 三、新版与旧版的异同点总结

简要从应用系统启动和请求处理两个阶段对比说一下两个版本的区别:

1.启动阶段:

这个阶段大部分都差不多,都是通过Startup的app.UseMvc()方法配置一个路由表,一个Route的集合Routes(IList<IRouter>),然后将其简单转换一下

<=2.1:  将Routes转换为RouteCollection

2.2+ :   将Routes转换为List<MvcEndpointInfo>

二者区别不大,虽然名字不同,但本质上还是差不多,都仍可理解为Route的集合的包装。

2.请求处理阶段:

<=2.1:   1. 将请求的URL与RouteCollection中记录的路由模板进行匹配。

           2. 找到匹配的Route之后,再根据这个请求的URL判断是否存在对应的Controlled和Action。

           3. 若以上均通过,则调用Route的Handler对HttpContext进行处理。

2.2+ :   1. 第一次处理请求时,首先根据启动阶段所配置的路由集合List<MvcEndpointInfo>和_actions.ActionDescriptors.Items(所有的action的信息)做匹配,生成一个列表,这个列表存储了所有可能被匹配的URL模板,如图二,这个列表同样是List<MvcEndpointInfo>,记录了所有可能的URL模式,实际上是列出了一个个可以被访问的详细地址,已经算是最终地址了,即终结点,或许就是为什么叫Endpoint路由的原因。

            2.请求的Url和这个生成的表做匹配,找到对应的MvcEndpointInfo。

            3. 调用被匹配的MvcEndpointInfo的RequestDelegate方法对请求进行处理。

二者区别就是对于_actions.ActionDescriptors.Items(所有的action的信息)的匹配上,原版是先根据路由模板匹配后,再根据ActionDescriptors判断是否存在对应的Controller和action,而新版是先利用了action信息与路由模板匹配,然后再用请求的URL进行匹配,由于这样的工作只在第一次请求的时候执行,所以虽然没有做执行效率上的测试,但感觉应该是比之前快的。 

原文链接:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_16.html


 

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg


这篇关于ASP.NET Core 2.2 : 扒一扒新的Endpoint路由方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/356993

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

MySQL中闪回功能的方案讨论及实现

《MySQL中闪回功能的方案讨论及实现》Oracle有一个闪回(flashback)功能,能够用户恢复误操作的数据,这篇文章主要来和大家讨论一下MySQL中支持闪回功能的方案,有需要的可以了解下... 目录1、 闪回的目标2、 无米无炊一3、 无米无炊二4、 演示5、小结oracle有一个闪回(flashb

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Java嵌套for循环优化方案分享

《Java嵌套for循环优化方案分享》介绍了Java中嵌套for循环的优化方法,包括减少循环次数、合并循环、使用更高效的数据结构、并行处理、预处理和缓存、算法优化、尽量减少对象创建以及本地变量优化,通... 目录Java 嵌套 for 循环优化方案1. 减少循环次数2. 合并循环3. 使用更高效的数据结构4