Net core学习系列(六)——Net Core路由
一、概述
路由主要有两个主要功能:
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路由的更多相关文章
- 【.Net Core 学习系列】-- EF Core 实践(Code First)
一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二解决方案: 新建项目: File --> New --> Project --> ...
- 【.Net Core 学习系列】-- EF Core实践(DB First)
一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二.准备数据: CREATE DATABASE [Blogging]; GO USE [Blogging ...
- EntityFramework Core 学习系列(一)Creating Model
EntityFramework Core 学习系列(一)Creating Model Getting Started 使用Command Line 来添加 Package dotnet add pa ...
- ASP.NET Core学习系列
.NET Core ASP.NET Core ASP.NET Core学习之一 入门简介 ASP.NET Core学习之二 菜鸟踩坑 ASP.NET Core学习之三 NLog日志 ASP.NET C ...
- Net core学习系列(一)——Net Core介绍
一.什么是Net Core .NET Core是适用于 windows.linux 和 macos 操作系统的免费.开源托管的计算机软件框架,是微软开发的第一个官方版本,具有跨平台 (Windows. ...
- Net core学习系列(八)——Net Core日志
一.简介# 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Conso ...
- Net core学习系列(二)——Net Core项目文件简介
一. ASP.NET Core 项目文件夹解读 ASP.NET Core 1.0 发布以来,相较于传统项目编码发布的行为,新项目中的操作已经有了很大的变化,如解析依赖,选择运行平台和Runtime等等 ...
- Net core学习系列(十)——Net Core配置
一.前言 选项(Options)模式是对配置(Configuration)的功能的延伸.在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类.绑定至对 ...
- Net core学习系列(七)——Net Core中间件
一.什么是中间件(Middleware)? 中间件是组装到应用程序管道中以处理请求和响应的软件. 每个组件: 选择是否将请求传递给管道中的下一个组件. 可以在调用管道中的下一个组件之前和之后执行工作. ...
随机推荐
- 【书评:Oracle查询优化改写】第四章
[书评:Oracle查询优化改写]第四章 BLOG文档结构图 一.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① check的 ...
- Mysql 常见数据类型及约束
Mysql 常见数据类型及约束 最近在跟几个不太懂技术的同事(哈哈, 其实我也不懂), 要整一个数据库项目, 然后前端, 后端, 都没有像样的, 数据输出还不是由我们控制.... 这可难受了, 然后总 ...
- maven学习笔记三(依赖特性,作用域)
上一章中 我们看到了添加了个junit的依赖包.那么maven中想添加依赖的jar包我们只需要配置相应的dependency就行.例如: <dependency> <groupId ...
- Yii2安装任务调度扩展
一.安装扩展 在安装之前添加仓库到composer.json文件中 "repositories": [{"type": "vcs", &qu ...
- Cloudera Certified Associate Administrator案例之Test篇
Cloudera Certified Associate Administrator案例之Test篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备工作(将CM升级到&qu ...
- docker学习4-docker安装mysql环境
前言 docker安装mysql环境非常方便,简单的几步操作就可以了 拉取mysql镜像 先拉取mysql的镜像,可以在docker的镜像仓库找到不同TAG标签的版本https://hub.docke ...
- 《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现
如题 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式可细分为如下, 本文不做多余解释 远程代理 虚拟代理 缓冲代理 保护代理 借鉴文章 ht ...
- 实现批量添加10个用户,用户名为user01-10,密码为user后面跟3个随机字符
#!/bin/bash ` do user="user$i" password=$( | md5sum | ) useradd user$i echo "$user$pa ...
- Vue 项目中 ESlint 配置
前言 对于 ESlint 这一块一直存在一些疑问,今天看到一个文章内容挺好的,这里拿来了. 一.eslint 安装 1.全局安装 npm i -g eslint 全局安装的好处是,在任何项目我们都可以 ...
- Thinkphp内核百度小程序输出接口
最近百度小程序比较火,自己站点用thinkphp打造的,所以写了这个Thinkphp的百度小程序输出接口,实现数据同步. 附上代码 <?php namespace app\article\con ...