路由中间件
首先看路由中间件的源码
先用
httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合然后把路由上下文作为参数,调用
IRouter.RouteAsync方法,该方法主要是进行路由匹配,匹配成功后给context.Handler赋值如果路由匹配成功,且handler不为空,说明已经有了后续处理消息的通道,就不用走下一个中间件了,否则消息处理交给下一个中间件
MVC流程就是从这里开始,路由匹配成功后,从handler进入MVC流程
namespace Microsoft.AspNetCore.Builder{ public class RouterMiddleware
{ private readonly ILogger _logger; private readonly RequestDelegate _next; private readonly IRouter _router; public RouterMiddleware(
RequestDelegate next,
ILoggerFactory loggerFactory,
IRouter router) {
_next = next;
_router = router;
_logger = loggerFactory.CreateLogger<RouterMiddleware>();
} public async Task Invoke(HttpContext httpContext) { var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router); await _router.RouteAsync(context); if (context.Handler == null)
{
_logger.RequestDidNotMatchRoutes(); await _next.Invoke(httpContext);
} else
{
httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
{
RouteData = context.RouteData,
}; await context.Handler(context.HttpContext);
}
}
}
}路由
IRouter接口仅定义了两个方法,其中路由的核心在于RouteAsync方法,该方法可用于路由匹配,返回处理委托RouteBase抽象类的的RouteAsync方法进行路由的匹配,Route类的RouteAsync方法仅仅是执行了构造函数传进来的routeBuilder.DefaultHandler路由的RouteAsync方法,DefaultHandler实际上也是继承自IRouterRouteHandler和MvcRouteHandler都可以作为routeBuilder.DefaultHandler,以提供Route类实例化需要的参数。RouteHandler的RouteAsync方法直接给context.Handler赋值从构造函数接收到的委托。MvcRouteHandler``RouteAsync方法则先根据匹配到的路由从已注册的控制器中适配方法,然后得到actionDescriptor,包含http上下文以及方法的基本信息,最后直接给context.Handler赋值,MVC流程从invoker.InvokeAsync()开始
public Task RouteAsync(RouteContext context) { if (context == null)
{ throw new ArgumentNullException(nameof(context));
} var candidates = _actionSelector.SelectCandidates(context); if (candidates == null || candidates.Count == 0)
{
_logger.NoActionsMatched(context.RouteData.Values); return Task.CompletedTask;
} var actionDescriptor = _actionSelector.SelectBestCandidate(context, candidates); if (actionDescriptor == null)
{
_logger.NoActionsMatched(context.RouteData.Values); return Task.CompletedTask;
}
context.Handler = (c) =>
{ var routeData = c.GetRouteData(); var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor); if (_actionContextAccessor != null)
{
_actionContextAccessor.ActionContext = actionContext;
} var invoker = _actionInvokerFactory.CreateInvoker(actionContext); if (invoker == null)
{ throw new InvalidOperationException(
Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(
actionDescriptor.DisplayName));
} return invoker.InvokeAsync();
}; return Task.CompletedTask;
}路由注册
最常见的注册方法
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});总结
路由实际上就是根据请求链接,遍历路由模板进行匹配,匹配到了返回一个
Handler用于后续处理消息其中的匹配过程,除了模板匹配,还要进行方法匹配,最后才进入业务处理流程
总的来说,路由中间件就是调用
IRouter实例的RouteAsync方法,得到Handler的话就执行,否则处理权交给下一个中间件。而路由实现,主要是匹配过程以及返回Handler。到这里,就可以发散思维,做各种有趣的事了以上是关于路由的知识梳理,看不懂没关系,这很正常,直接能看懂才怪了,进过实践,代码调试,都不能完全理解这个过程,而静下心来总结的时候,往往就能将零碎的知识点串联起来,打成一片,扫除盲点
持续更新,原文地址:https://www.cnblogs.com/xxred/p/9582200.html
共同學習,寫下你的評論
評論加載中...
作者其他優質文章