zoukankan      html  css  js  c++  java
  • (二)学习了解OrchardCore笔记——起始篇:OrchardCore的中间件

      现在开始看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, "10");
                        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中间件了。

  • 相关阅读:
    iOS 索引列 使用详解
    iOS 搜索条使用详解
    iOS 百度地图使用详解
    在iOS中使用ZBar扫描二维码和条形码
    自学html-five(锚点、伪类、字符实体)
    自学html-four(css初始化及html语义标签 -> h标签 p标签 img标签 有序列表 无序列表 表格 超链接)
    自学html--htree(CSS)
    自学html--two(盒模型)
    自学html--one(div布局)
    常用控件补充(UIDatePicker、UIWebView)
  • 原文地址:https://www.cnblogs.com/ShuiSen/p/13277927.html
Copyright © 2011-2022 走看看