一、概述

路由主要有两个主要功能:

1、将请求的URL与已定义的路由进行匹配,找到该URL对应的处理程序并传入该请求进行处理。

2、根据已定义的路由生成URL

这两个功能看起来这两个是相反的。

A.路由的配置

路由的两个功能都离不开一个基本的操作:路由的基本配置。在Startup中默认通过 routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}")定义,

当然我们还可以继续 routes.MapRoute(。。。);  这样就定义了一系列的路由匹配方式组成一个路由表,例如这样:

app.UseMvc(routes =>
{
routes.MapRoute(name: "test", template: "Hello");
routes.MapRoute("flylolo/{code}/{name}", MyRouteHandler.Handler);
routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});

每一个MapRoute会生成一个Route,第二个MapRoute看起来有些特殊,我们可以传入一个自定义的RequestDelegate(本例为MyRouteHandler.Handler)来处理“flylolo/{code}/{name}”这样的请求,

    public static class MyRouteHandler
{
public static async Task Handler(HttpContext context)
{
await context.Response.WriteAsync("MyRouteHandler");
}
}

它会被封装成一个RouteHandler(new RouteHandler(MyRouteHandler.Handler))赋值给Route的target属性,而对于另外两种没有指定的,Route的target属性默认会被指定为MvcRouteHandler ,如下图:

B.Handler的选择

当请求进入之后,根据此路由表对该URL进行逐一匹配,并将请求交给匹配到的路由的target(即MvcRouteHandler或RouteHandler),调用_target.RouteAsync(context); ,在这个方法中,若是MvcRouteHandler会对请求的Controller和Action验证,若验证成功,则对context(是一个RouteContext)的Handler属性赋值一个匿名方法;若是RouteHandler则会直接将其封装的RequestDelegate(本例为MyRouteHandler.Handler)赋值给RouteContext.Handler.

C.请求处理

经过Handler的选择后,若RouteContext.Handler不为空,则调用RouteContext.Handler(HttpContext)对请求进行处理。

D.其他

回想一下中间件,这个是不是和app.Map("/test", XXHandle)这样配置中间件的方式有点像,当请求路径是/test的时候,请求交由XXHandle处理,同样是Map,对比着更容易理解。

下面通过一张图看一下路由配置和请求处理的流程。

二、流程及解析

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

1、路由的初始化配置

一切从Startup开始,之前在中间件的文章中介绍过,一般是通过多个UseXXX的方式将多个中间件组成“请求处理管道”,而在这里通过UseMvc方法进行配置,传入routes.MapRoute(...)这样的一个或多个配置。接下来会New一个RouteBuilder,顾名思义就是一个Route的创建者,通过调用传进来的一个或多个routes.MapRoute()方法生成多个Route,并配置默认的Handler。

                var routes = new RouteBuilder(app)
{
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
}; configureRoutes(routes);//调用Startup中的routes.MapRoute(...)方法

①调用RouteBuilder的Build方法,生成一个RouteCollection。

        public IRouter Build()
{
var routeCollection = new RouteCollection(); foreach (var route in Routes)
{
routeCollection.Add(route);
} return routeCollection;
}

②RouteCollection实现IRouteCollection和IRouter接口,他是在Startup中的配置组成的集合。

③RouterMiddleWare就是专门用于进行路由处理的中间件,在此将RouteCollection作为中间件RouterMiddleWare的参数,并将这个中间件插入管道中。

    public class RouterMiddleware
{
private readonly IRouter _router; //就是RouteCollection public async Task Invoke(HttpContext httpContext); }

2. 请求处理流程

        ④请求的处理流程在RouterMiddleWare的invoke()方法中。

     ⑤请求首先会被封装成一个RouteContext,本质就是将httpContext、_router(也就是RouteCollection)包装到一个对象里。

  var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router);
public class RouteContext
{
private RouteData _routeData;
public RequestDelegate Handler ;
public HttpContext HttpContext;//简单的赋值
public RouteData RouteData;
}

⑥调用_router(也就是RouteCollection)的RouteAsync(context)方法,在其中遍历每一个路由

⑦若与请求URL匹配,则将对应的Handler赋值给context.Handler。

        public async virtual Task RouteAsync(RouteContext context)
{
// 快照备份
var snapshot = context.RouteData.PushState(null, values: null, dataTokens: null);
//遍历
for (var i = 0; i < Count; i++)
{
var route = this[i];
context.RouteData.Routers.Add(route); try
{
await route.RouteAsync(context);//若匹配,则给context.Handler赋值 if (context.Handler != null)
{
break;
}
}
finally
{
if (context.Handler == null)
{
snapshot.Restore();//通过快照还原
}
}
}
}

⑧在RouterMiddleWare的invoke()方法中,调用新赋值的context.Handler处理HttpContext;

httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
{
RouteData = context.RouteData,
}; await context.Handler(context.HttpContext);

Net core学习系列(六)——Net Core路由的更多相关文章

  1. 【.Net Core 学习系列】-- EF Core 实践(Code First)

    一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二解决方案: 新建项目: File --> New --> Project -->   ...

  2. 【.Net Core 学习系列】-- EF Core实践(DB First)

    一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二.准备数据: CREATE DATABASE [Blogging]; GO USE [Blogging ...

  3. EntityFramework Core 学习系列(一)Creating Model

    EntityFramework Core 学习系列(一)Creating Model Getting Started 使用Command Line 来添加 Package  dotnet add pa ...

  4. ASP.NET Core学习系列

    .NET Core ASP.NET Core ASP.NET Core学习之一 入门简介 ASP.NET Core学习之二 菜鸟踩坑 ASP.NET Core学习之三 NLog日志 ASP.NET C ...

  5. Net core学习系列(一)——Net Core介绍

    一.什么是Net Core .NET Core是适用于 windows.linux 和 macos 操作系统的免费.开源托管的计算机软件框架,是微软开发的第一个官方版本,具有跨平台 (Windows. ...

  6. Net core学习系列(八)——Net Core日志

    一.简介# 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Conso ...

  7. Net core学习系列(二)——Net Core项目文件简介

    一. ASP.NET Core 项目文件夹解读 ASP.NET Core 1.0 发布以来,相较于传统项目编码发布的行为,新项目中的操作已经有了很大的变化,如解析依赖,选择运行平台和Runtime等等 ...

  8. Net core学习系列(十)——Net Core配置

    一.前言 选项(Options)模式是对配置(Configuration)的功能的延伸.在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类.绑定至对 ...

  9. Net core学习系列(七)——Net Core中间件

    一.什么是中间件(Middleware)? 中间件是组装到应用程序管道中以处理请求和响应的软件. 每个组件: 选择是否将请求传递给管道中的下一个组件. 可以在调用管道中的下一个组件之前和之后执行工作. ...

随机推荐

  1. JQ实现购物车全选跟总计全选

    //GoodsCheck购物车每个店铺的checkBox//goods-check购物车所有的checkBox//ShopCheck店铺全选的按钮//commlistFrm店铺商品的模块//allCh ...

  2. Mysql慢查询日志以及优化

    慢查询日志设置 当语句执行时间较长时,通过日志的方式进行记录,这种方式就是慢查询的日志. 1.临时开启慢查询日志(如果需要长时间开启,则需要更改mysql配置文件) set global slow_q ...

  3. Celery:Next Steps

    参考文档:http://docs.celeryproject.org/en/latest/getting-started/next-steps.html#next-steps

  4. 在DoNetMVC中使用控制反转和依赖注入【DI】

    本次是在MVC5中使用Autofac 第一步:程序包管理器控制台 Install-Package Autofac.MVC5 引入nuget包 这样成功之后,会在引用中出现两个DLL,分别是Autofa ...

  5. Linux安装和配置MySQL5.7【修改密码、修改字符集等配置】(5.7.18+版本也可参考,我是5.7.22)

    本文是转载篇,这里是 原文原文原文. --------------------分割线------------------------------- 这下面内容讲述如何修改密码为简单密码(比如:1234 ...

  6. MySQL--使用mysqldump进行数据库版本升级

    在MySQL跨版本升级时,建议使用mysqldump方式导出用户权限和用户数据,即使是小版本升级,导出过程中也应忽略系统数据库,避免系统表不兼容. 导出用户数据库脚本和用户创建脚本 ##======= ...

  7. php框架路由美化后提示No input file specified

    此问题出现在.htaccess上 Apache按如下代码修改即可: RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond % ...

  8. angularcli 第八篇(router 路由)

    更多详细:https://segmentfault.com/a/1190000009265310 一.标题:页面有两个按钮(test1.test2),点击这两个按钮,跳转相应页面~ 注:可直接创建一个 ...

  9. video基础介绍&封装react-video基础组件,ES6

    好几个月没有写博客了,人都赖了,今天抽了一点时间把最近项目react中video整理了一下(感觉这个以后用的活比较多) 1.前三部部分详细归纳了video的基础知识,属性和功能: 2.第四部分是封装了 ...

  10. SpringBoot项目下的mvnw与mvnw.cmd

    Maven是一个常用的构建工具,但是Maven的版本和插件的配合并不是那么完美,有时候你不得不切换到一个稍微旧一些的版本,以保证所有东西正常工作. 而Gradle提供了一个Wrapper,可以很好解决 ...