现在开始看Starpup的中间件。这是一个扩展方法app.UseOrchardCore()

        public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseStaticFiles(); app.UseOrchardCore();
}

  直接查看扩展方法,vs都是直接按住ctrl键+鼠标左键就可以跳转到具体方法,下面我我们定位到方法里面去。

  

  可以清楚的看到下面代码又是很熟悉的结构。

    public static class ApplicationBuilderExtensions
{
/// <summary>
/// Enables multi-tenant requests support for the current path.
/// </summary>
public static IApplicationBuilder UseOrchardCore(this IApplicationBuilder app, Action<IApplicationBuilder> configure = null)
{
var env = app.ApplicationServices.GetRequiredService<IHostEnvironment>();
var appContext = app.ApplicationServices.GetRequiredService<IApplicationContext>(); env.ContentRootFileProvider = new CompositeFileProvider(
new ModuleEmbeddedFileProvider(appContext),
env.ContentRootFileProvider); // Init also the web host 'ContentRootFileProvider'.
app.ApplicationServices.GetRequiredService<IWebHostEnvironment>()
.ContentRootFileProvider = env.ContentRootFileProvider; app.UseMiddleware<PoweredByMiddleware>(); // Ensure the shell tenants are loaded when a request comes in
// and replaces the current service provider for the tenant's one.
app.UseMiddleware<ModularTenantContainerMiddleware>(); configure?.Invoke(app); app.UseMiddleware<ModularTenantRouterMiddleware>(app.ServerFeatures); return app;
}
}

  OrchardCore自己也注释的很清楚:为当前路径启用多租户请求支持。网上很多都介绍OrchardCore是一个多租户的cms,那么什么是租户呢?我的理解就是像虚拟主机一类的东西。都知道Program的main方法就是构建一个kestrel主机运行起来(这里我直接当作iis运行起来,这样比较好理解),kestrel是一个很简陋的主机,很多功能都没有,比如像iis那样的服务器能创建虚拟主机它是没办法的,它只能提供一个主机服务,而多租户就是类似于iis上的虚拟主机了,也就是可以提供多个web站点服务。当然我表述比较土,换个角度,我们要开通web服务,就必须像服务商租用web主机,服务商有一台服务器,而我们只要开一个web服务,因此只要租用一个虚拟主机就够了而不用租用整台服务器,当然我们朋友要多开个web服务就可以多租一个虚拟主机就够了。OrchardCore就是web服务器,而我们可以开n个web服务,OrchardCore提供足够的虚拟主机给我们租用。也就是说每个租户都是独立不干扰的虚拟主机,各自提供自己的web服务。我语文比较差,大概就这么个意思。

  开始看代码,前面这几行没啥好说的,看过asp.net core源码的都能直接跳过了!就是获取环境变量,初始化Web主机“ ContentRootFileProvider”。好像很难理解,其实就是指定租户的wwwroot文件夹。后面有空再追踪下这段,先跳过。

var env = app.ApplicationServices.GetRequiredService<IHostEnvironment>();
var appContext = app.ApplicationServices.GetRequiredService<IApplicationContext>(); env.ContentRootFileProvider = new CompositeFileProvider(
new ModuleEmbeddedFileProvider(appContext),
env.ContentRootFileProvider); // Init also the web host 'ContentRootFileProvider'.
app.ApplicationServices.GetRequiredService<IWebHostEnvironment>()
.ContentRootFileProvider = env.ContentRootFileProvider;

  前面跳过是因为下面这几行才是整个OrchardCore的灵魂,先搞懂这几行,其它先旁支忽略吧

            app.UseMiddleware<PoweredByMiddleware>();

            // Ensure the shell tenants are loaded when a request comes in
// and replaces the current service provider for the tenant's one.
app.UseMiddleware<ModularTenantContainerMiddleware>(); configure?.Invoke(app); app.UseMiddleware<ModularTenantRouterMiddleware>(app.ServerFeatures);

  app.UseMiddleware多么熟悉的结构,就是加了三个中间件PoweredByMiddleware、ModularTenantContainerMiddleware和ModularTenantRouterMiddleware,从名称上已经可以大致明白他们的作用。分别是版权、模块化租户容器和模块化租户路由。

  PoweredByMiddleware比较简单,基本点进去直接看源码就明白了。

  

    /// <summary>
/// Adds the X-Powered-By header with values OrchardCore.
/// </summary>
public class PoweredByMiddleware
{
private readonly RequestDelegate _next;
private readonly IPoweredByMiddlewareOptions _options; public PoweredByMiddleware(RequestDelegate next, IPoweredByMiddlewareOptions options)
{
_next = next;
_options = options;
} public Task Invoke(HttpContext httpContext)
{
if (_options.Enabled)
{
httpContext.Response.Headers[_options.HeaderName] = _options.HeaderValue;
} return _next.Invoke(httpContext);
}
}

  asp.net core中间件熟悉的界面,一个构造函数和一个Invoke(或者异步的InvokeAsync),options也是下面的接口和类直接注入。也就是把Headers[X-Powered-By]的值设置为“OrchardCore”写入上下文对象。

    public interface IPoweredByMiddlewareOptions
{
bool Enabled { get; set; }
string HeaderName { get; }
string HeaderValue { get; set; }
} internal class PoweredByMiddlewareOptions : IPoweredByMiddlewareOptions
{
private const string PoweredByHeaderName = "X-Powered-By";
private const string PoweredByHeaderValue = "OrchardCore"; public string HeaderName => PoweredByHeaderName;
public string HeaderValue { get; set; } = PoweredByHeaderValue; public bool Enabled { get; set; } = true;
}

  ModularTenantContainerMiddleware这个中间件就是整个OrchardCore所有能力的体现了。这个Invoke比PoweredByMiddleware的复杂多了,感觉拆开可以讲三天三夜,而且坑也很多(是我知识水平太低被坑,而不是说项目不好),下次就篇再分析吧,简单说就租户主机没创建的创建,没开启的启动,收到请求的如何处理请求等等。这个Shell我是翻译不出意思,直接理解成具体某一个吧,说错请纠正,这也是我发学习笔记的原因。

    /// <summary>
/// This middleware replaces the default service provider by the one for the current tenant
/// </summary>
public class ModularTenantContainerMiddleware
{
private readonly RequestDelegate _next;
private readonly IShellHost _shellHost;
private readonly IRunningShellTable _runningShellTable; public ModularTenantContainerMiddleware(
RequestDelegate next,
IShellHost shellHost,
IRunningShellTable runningShellTable)
{
_next = next;
_shellHost = shellHost;
_runningShellTable = runningShellTable;
} public async Task Invoke(HttpContext httpContext)
{
// Ensure all ShellContext are loaded and available.
await _shellHost.InitializeAsync(); var shellSettings = _runningShellTable.Match(httpContext); // We only serve the next request if the tenant has been resolved.
if (shellSettings != null)
{
if (shellSettings.State == TenantState.Initializing)
{
httpContext.Response.Headers.Add(HeaderNames.RetryAfter, "");
httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
await httpContext.Response.WriteAsync("The requested tenant is currently initializing.");
return;
} // Makes 'RequestServices' aware of the current 'ShellScope'.
httpContext.UseShellScopeServices(); var shellScope = await _shellHost.GetScopeAsync(shellSettings); // Holds the 'ShellContext' for the full request.
httpContext.Features.Set(new ShellContextFeature
{
ShellContext = shellScope.ShellContext,
OriginalPath = httpContext.Request.Path,
OriginalPathBase = httpContext.Request.PathBase
}); await shellScope.UsingAsync(scope => _next.Invoke(httpContext));
}
}

  最后ModularTenantRouterMiddleware这个中间件一看就跟路由有关,具体代码自己ctrl+鼠标左键点吧,简单的可以理解成asp.net core web应用程序或者asp.net core web api里的app.UseEndpoints,当然不是这么简单,毕竟是模块化,所以有个StartupBase的自定义类要理解下,这也是说OrchardCore的模块化多租户不是asp.net core的原因。开始接触我也想怎么有这么矛盾的事情,明明OrchardCore就是一个asp.net core的程序,怎么有很多观点说它只是类似于asp.net core而不是asp.net core呢?现在我才明白,没错,OrchardCore是asp.net core,但是他提供模块化多租户的形式并不是跟asp.net core一样(不然哪里来的多租户,废话)。这个后面有时间再说,下一篇笔记应该是开始读上面那个ModularTenantContainerMiddleware中间件了。

最新文章

  1. 使用KRPano资源分析工具解密被加密的XML
  2. Java实现emf图片自己留转png(jpg)图片字节流
  3. 把HBITMAP 保存图片文件.
  4. PHP内核研究(内存管理1)
  5. Vue基础----&gt;VueJS的使用(一)
  6. 弃用的异步get和post方法之代理方法
  7. C++纯虚函数
  8. TFS2012团队管理基本配置及基础使用方法
  9. Vim编辑器的常用快捷键.
  10. Angularjs Directive(指令)机制
  11. Guava快速入门
  12. 初探LaTeX
  13. HTTP 错误码
  14. svg中实现文字随曲线走向,HTML直接写和JavaScript创建对象两种方式
  15. Ubuntu 18.0.4安装Mongodb
  16. 查看Orcale数据里的表是否有变化
  17. Android Wifi 主动扫描 被动扫描
  18. java 网络编(二)UDP的传输
  19. macOS SIP 权限设置
  20. AndroidDriver原理初步--Android自动化测试学习历程

热门文章

  1. WinForm通用自动更新AutoUpdater项目实战
  2. javascript 面向对象学习(三)——this,bind、apply 和 call
  3. openshift v1.5 不能登录system:admin 问题
  4. blob斑点检测
  5. Node.js 学习笔记(二)
  6. 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」
  7. INSERT INTO语句的基本用法
  8. Python中的字段分割
  9. Netty源码分析之自定义编解码器
  10. 初识Java Java基础知识