ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件
雖然ASP.NET Core應(yīng)用的路由是通過RouterMiddleware這個(gè)中間件來完成的,但是具體的路由解析功能都落在指定的Router對象上,不過我們依然有必要以代碼實(shí)現(xiàn)的角度來介紹一下這個(gè)中間件。在這之前,我們先來認(rèn)識一個(gè)特殊的特性。[本文已經(jīng)同步到《ASP.NET Core框架揭秘》之中]
讓RouterMiddleware中間件委托Router完整整個(gè)路由工作之后,解析出來的路由參數(shù)會(huì)以一個(gè)RouteData對象的形式存儲在RouteContext上下文中。但是RouteContext是為Router的執(zhí)行建立的上下文,路由解析工作完成之后,這個(gè)上下文的生命周期也隨著結(jié)束,既然整個(gè)RouteContext上下文都不存在了,請求處理的后續(xù)步驟如何獲取這個(gè)RouteData對象呢?
通過《注冊URL模式與HttpHandler的映射關(guān)系》的實(shí)例演示我們知道可以調(diào)用HttpContext的擴(kuò)展方法GetRouteData來獲取這個(gè)包含素所有路由參數(shù)的RouteData對象,這個(gè)意味著原本依附于RouteContext上下文的RouteData最終會(huì)被附加到代表當(dāng)前請求上下文的HttpContext上,而具體承載這個(gè)RouteData的就是這個(gè)名為RoutingFeature的特性。RoutingFeature是我們對所有實(shí)現(xiàn)了IRoutingFeature接口的所有類型以及對應(yīng)對象的統(tǒng)稱。如下面的代碼片段所示,這個(gè)接口通過屬性RouteData來保存最終附加到HttpContext的RouteData。RoutingFeature類是這個(gè)接口的默認(rèn)實(shí)現(xiàn)者,我們的RouterMiddleware默認(rèn)情況下就是使用這個(gè)對象。
1: public interface IRoutingFeature 2: { 3: RouteData RouteData { get; set; } 4: } 5:? 6: public class RoutingFeature : IRoutingFeature 7: { 8: public RouteData RouteData { get; set; } 9: }如下所示的代碼片段體現(xiàn)了RouterMiddleware處理請求的完整邏輯。我們在創(chuàng)建一個(gè)RouterMiddleware對象的時(shí)候需要指定一個(gè)Router對象,以及一個(gè)用來創(chuàng)建Logger的LoggerFactory。當(dāng)這個(gè)中間件開始處理請求的時(shí)候,它會(huì)根據(jù)當(dāng)前HttpContext創(chuàng)建一個(gè)RouteContext上下文對象,并將其作為參數(shù)調(diào)用Router的RotueAsync方法進(jìn)行路由解析。如果在路由解析結(jié)束之后通過RouteContext的Handler屬性返回的請求處理存在,意味著當(dāng)前請求與注冊的路由匹配,在此情況下它會(huì)將當(dāng)前請求交給這個(gè)處理器做后續(xù)處理。在這之前它會(huì)從RouteContext上下文中提出出RouteData,然后據(jù)此創(chuàng)建一個(gè)RoutingFeature對象并附加到HttpContext上面。
1: public class RouterMiddleware 2: { 3: private ILogger _logger; 4: private RequestDelegate _next; 5: private IRouter _router; 6:? 7: public RouterMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IRouter router) 8: { 9: _next = next; 10: _logger = loggerFactory.CreateLogger<RouterMiddleware>(); 11: _router = router; 12: } 13:? 14: public async Task Invoke(HttpContext context) 15: { 16: RouteContext routeContext = new RouteContext(context); 17: routeContext.RouteData.Routers.Add(_router); 18: await _router.RouteAsync(routeContext); 19: if (null == routeContext.Handler) 20: { 21: _logger.LogDebug(1, "Request did not match any routes."); 22: await _next(context); 23: } 24: else 25: { 26: context.Features.Set<IRoutingFeature>(new RoutingFeature { RouteData = routeContext.RouteData}) 27: await routeContext.Handler(context); 28: } 29: } 30: }我們除了可以調(diào)用HttpContext的擴(kuò)展方法GetRouteData得到封裝了路由參數(shù)的RouteData對象之前,我們還可以調(diào)用另一個(gè)名為GetRouteValue發(fā)的擴(kuò)展方法直接獲取某個(gè)路由參數(shù)的值。在如下所示的代碼片段中,我們采用比較簡單代碼展示了這兩個(gè)擴(kuò)展放的實(shí)現(xiàn)。
1: public static class RoutingHttpContextExtensions 2: { 3: public static RouteData GetRouteData(this HttpContext context) 4: { 5: return context.Features.Get<IRoutingFeature>()?.RouteData; 6: } 7:? 8: public static object GetRouteValue(this HttpContext context, string key) 9: { 10: return context.GetRouteData()?.Values[key]; 11: } 12: }一般來說我們傾向于調(diào)用ApplicationBuilder的擴(kuò)展方法UseRouter來注冊RouterMiddleware中間件。具體來說,我們可以選擇如下兩個(gè)UseRouter方法重載。如果調(diào)用第一個(gè)重載,我們需要為注冊的RouterMiddleware中間件提供一個(gè)具體的Router對象。對于第二個(gè)重載來說,這個(gè)Router對象實(shí)際上是利用RouteBuilder創(chuàng)建的,我們在調(diào)用這個(gè)方法的時(shí)候需要以Action<IRouteBuilder>對象的形式利用這個(gè)RouteBuilder注冊所需的路由。
1: public static class RoutingBuilderExtensions 2: { 3: public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, IRouter router) 4: { 5: return builder.UseMiddleware<RouterMiddleware>(new object[] { router }); 6: } 7:? 8: public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, Action<IRouteBuilder> action) 9: { 10: RouteBuilder routeBuilder = new RouteBuilder(builder); 11: action(routeBuilder); 12: return builder.UseRouter(routeBuilder.Build()); 13: } 14: }?
ASP.NET Core的路由[1]:注冊URL模式與HttpHandler的映射關(guān)系
ASP.NET Core的路由[2]:路由系統(tǒng)的核心對象——Router
ASP.NET Core的路由[3]:Router的創(chuàng)建者——RouteBuilder
ASP.NET Core的路由[4]:來認(rèn)識一下實(shí)現(xiàn)路由的RouterMiddleware中間件
ASP.NET Core的路由[5]:內(nèi)聯(lián)路由約束的檢驗(yàn)
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows RabbitMQ 命令
- 下一篇: .NET开发作业调度(job sched