目录

  • 引入
  • 组合模式
  • 源码

引入

在上一篇执行 _connectionDelegate 之后,HttpConnectionMiddleware 处理请求

return connection.ProcessRequestsAsync(_application);

在 HttpConnection 中调用 IRequestProcessor 的 ProcessRequestsAsync 方法

await requestProcessor.ProcessRequestsAsync(httpApplication);

跳转到 IRequestProcessor 的实现类 HttpProtocol 的 ProcessRequests 方法

private async Task ProcessRequests<TContext>(IHttpApplication<TContext> application) where TContext : notnull

这里会创建 MessageBody

var messageBody = CreateMessageBody();

然后创建一个真正的 context,这个时候 context 就被转换成一个可读的 HTTPContext

var context = application.CreateContext(this);

接着开始真正的调用 HTTPApplication,走到 Host 里面,接着执行 startup 里面写的管道

// Run the application code for this request
await application.ProcessRequestAsync(context);

那么接下来的 controller,api 如何出来呢?

通过 routing 和 endpoints,每个请求会 map 到一个 endpoint

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

调用 UseRouting 之后会添加一个 EndpointRoutingMiddleware,用于匹配路由,会将一个 URL 匹配到一个 Endpoint

MapControllers 会扫描所有 api 上面的路由,添加到 DataSource 中,它被 EndpointDataSource 所使用

由于 DataSource 的存在,可以找到匹配,匹配之后会将 SelectEndpoint 挂到 HttpContext

而 Endpoint 中是一个 RequestDelegate

如果不使用 Route 和 Endpoint,可以使用这样的形式

app.Run(async context => { await context.Response.WriteAsync("aaa"); });

在匹配的时候我们用到了组合的设计模式

组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性

组合模式(Composite)经常用于树形结构,为了简化代码,使用Composite可以把一个叶子节点与一个父节点统一起来处理

Route DfaNode:通过遍历的形式,当一个 url 进来的时候,会把所有的路由进行分割,从上到下进行匹配

源码

https://github.com/dotnet/aspnetcore/

在目录 Microsoft.AspNetCore.Routing.Matching 下面有一个 DfaMatcher,它继承自 Matcher

internal sealed partial class DfaMatcher : Matcher

DfaMatcher 有一个 MatchAsync 方法

public sealed override Task MatchAsync(HttpContext httpContext)

在 MatchAsync 方法里面首先拿到 path,接着查找候选集

var path = httpContext.Request.Path.Value!;

var (candidates, policies) = FindCandidateSet(httpContext, path, segments);

FindCandidateSet 方法里面有已经构造好的 DfaState,包含了路由分割信息

private readonly DfaState[] _states;

在进行 Match 之前需要有一个 DfaTree,可以在 DfaMatcherBuilder 中找到

DfaMatcherBuilder 有一个 Build 方法

public override Matcher Build()

在 Build 方法里面 BuildDfaTree

var root = BuildDfaTree(includeLabel);

BuildDfaTree 由很多个 Node 组成

AddNode(root, states, exitDestination);

然后构建 DfaState

states[exitDestination] = new DfaState(
Array.Empty<Candidate>(),
Array.Empty<IEndpointSelectorPolicy>(),
JumpTableBuilder.Build(exitDestination, exitDestination, null),
null);

再把 DfaState 传给 DfaMatcher

return new DfaMatcher(_loggerFactory.CreateLogger<DfaMatcher>(), _selector, states, maxSegmentCount);

由于这个过程比较复杂,所以将这个过程包装在 DataSourceDependentMatcher,但是它不是一个 Matcher

DataSourceDependentMatcher 的 MatchAsync 方法直接调用了 CurrentMatcher 的 MatchAsync 方法

public override Task MatchAsync(HttpContext httpContext)
{
return CurrentMatcher.MatchAsync(httpContext);
}

所以 DataSourceDependentMatcher 的主要功能是构造一个 Matcher,就是一个 DfaMatcher

private Matcher CreateMatcher(IReadOnlyList<Endpoint> endpoints)

对外部来讲只是一个 Matcher,然后它需要实现对内部的封装,把所有细节隐藏在 DataSourceDependentMatcher 中

DataSourceDependentMatcher 只是一个对 DfaMatcher 叶子节点的组合

课程链接

https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

.NET 云原生架构师训练营(组合模式)--学习笔记的更多相关文章

  1. .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记

    目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...

  2. .NET 云原生架构师训练营(权限系统 RGCA 架构设计)--学习笔记

    目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...

  3. .NET 云原生架构师训练营(建立系统观)--学习笔记

    目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...

  4. .NET 云原生架构师训练营(设计原则与模式)--学习笔记

    在复杂系统的架构设计中引入设计原则与模式,能够极大降低复杂系统开发.和维护的成本 目录 几个问题 为什么要学习设计模式 优良架构设计的具体指标 理解复杂系统 面向对象思想(指导复杂系统的分析.设计.实 ...

  5. .NET 云原生架构师训练营(责任链模式)--学习笔记

    目录 责任链模式 源码 责任链模式 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无需关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了 何时使用:在处理 ...

  6. .NET 云原生架构师训练营(系统架构)--学习笔记

    目录 对外展现的功能 内部功能 功能交互与价值通路 系统架构 目标 认识系统的价值通路 认识功能架构,通过把功能结构与形式结构结合来描述系统架构 受益原则 好的架构必须使人受益,要想把架构做好,就要专 ...

  7. .NET 云原生架构师训练营(模块二 基础巩固 敏捷开发)--学习笔记

    2.7.1 敏捷开发 敏捷介绍 敏捷的起源 敏捷软件开发宣言 敏捷开发十二原则 生命周期对比 敏捷开发的特点 敏捷的发展 敏捷的核心 敏捷的起源 2001年,17个老头子在一起一边滑雪,一边讨论工作, ...

  8. .NET 云原生架构师训练营(设计原则&&设计模式)--学习笔记

    目录 设计原则 设计模式 设计原则 DRY (Don't repeat yourself 不要重复) KISS (Keep it stupid simple 简单到傻子都能看懂) YAGNI (You ...

  9. .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 聚合)--学习笔记

    2.5.5 MongoDB -- 聚合 排序 索引类型 创建索引 排序 // 升序 db.getCollection('author').find({}).sort({"age": ...

随机推荐

  1. Linux目录结构和基础命令

    Linux目录和基础命令 目录 Linux目录和基础命令 1 Linux目录结构 1.1 Linux文件名命令要求 1.2 文件的类型 2. 基础命令 2.1 ls 2.2 cd和pwd 2.3 命令 ...

  2. 【C/C++】two pointers/归并排序/原理/理解/实现/算法笔记4.6

    1.two pointers 思路:对序列进行扫描的时候,根据序列本身的特性用两个下标i和j对序列进行扫描,从而降低算法复杂度. ·例1 在递增序列中找a + b = M while (i<j) ...

  3. 项目开发中,真的有必要定义VO,BO,PO,DO,DTO这些吗?

    存在即是合理的,业务复杂,人员协同性要求高的场景下,这些规范性的东西不按着来虽然不会出错,程序照样跑,但是遵守规范会让程序更具扩展性和可读性,都是前辈血淋淋的宝贵经验,为什么不用? 随着现在后端编程标 ...

  4. 2、Redis的安装

    一.Windows下Redis安装 下载地址 Redis中文网站 Github地址 1.将下载下来的文件解压到目录 2.双击redis-server.exe运行   出现如下界面证明运行成功 3.双击 ...

  5. 模板方法模式(Template Method Pattern)——复杂流程步骤的设计

    模式概述 在现实生活中,很多事情都包含几个实现步骤,例如请客吃饭,无论吃什么,一般都包含点单.吃东西.买单等几个步骤,通常情况下这几个步骤的次序是:点单 --> 吃东西 --> 买单. 在 ...

  6. 【划重点】Python pandas简介

    一.pandas获取Excel表单的两种方式 import pandas as pd df1 = pd.DataFrame(pd.read_excel(r'C:\Users\ASUS\Desktop\ ...

  7. Vector Demo

    /* * vectorDemo.cpp * * Created on: Jul 17, 2014 * Author: lichfeng */ #include<vector> #inclu ...

  8. 月薪过2w的IT程序员都是怎么做到的?

    ​  先说结论:要月入过2万,不能仅仅靠技术,更要找个肯给到这份工资的平台.也就是说,尽量去大城市,尽量去大公司. 我在上海,先说下我知道的薪资情况,基本上,只要有3年开发经验,能过大厂或外企的面试, ...

  9. 自定义函数(Power Query 之 M 语言)

    数据源: 任意工作簿 目标: 使用自定义函数实现将数据源导入Power Query编辑器 操作过程: PowerQuery编辑器>主页>新建源>其他源>空查询 编辑栏内写入公式 ...

  10. LuoguP1723 高手过愚人节 题解

    Content 有 \(n\) 次询问,每次询问给定一个字符串 \(s\),求这个字符串最长的回文子串的长度. 数据范围:\(n\) 无解(至少从题面来看是这样的),字符串长度目测应该在 \(10^7 ...