.netcore基础知识(一)
Python微信訂餐小程序課程視頻
https://edu.csdn.net/course/detail/36074
Python實(shí)戰(zhàn)量化交易理財(cái)系統(tǒng)
https://edu.csdn.net/course/detail/35475
先來說說web服務(wù)器
先來一張圖 一個(gè)典型的進(jìn)程外托管模型 我們先看kestrel這一部分 我們?cè)谒懊娣帕艘粋€(gè)方向代理服務(wù)器nginx 對(duì)http請(qǐng)求做預(yù)處理 kestrel本身是可以直接用作web服務(wù)器的 但是其功能較弱 只有基礎(chǔ)功能 說白了就是一個(gè)弱化版的IIS 所以不建議直接將他暴露出來 一般會(huì)在前面加上一個(gè)反向代理服務(wù)器 當(dāng)然圖中也可以將IIS作為反向代理服務(wù)器 但是這有點(diǎn)多此一舉了 我們可以直接用IIS 這時(shí)有IIS集成技術(shù) 會(huì)消耗更少資源 這時(shí)叫做進(jìn)程內(nèi)托管 所以其實(shí)一共就有兩種最優(yōu)方案:
(1)確定要用IIS情況下 直接用IIS集成 進(jìn)程內(nèi)托管
(2)不確定要用IIS 建議Nginx/apache + Kestrel 這樣外部有一層反向代理 能有效做負(fù)載均衡,動(dòng)靜分離,訪問控制,重定向等等 kestrel僅僅用來處理http請(qǐng)求
然后來講講Host主機(jī)
Program類就是用來創(chuàng)建主機(jī)的
public class Program{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup();});}看一下這段代碼 是不是很眼熟? Core的main方法就在這里 這是程序的入口 我們看一下他做了什么
CreateHostBuilder(args).Build().Run();上面這句就是:創(chuàng)建主機(jī)生成器 ----> 配置主機(jī) ----> 創(chuàng)建主機(jī) ----> 運(yùn)行主機(jī)底下那個(gè)方法是前兩步 從 .Build().Run() 這兩步就是后面兩步主機(jī)有啥用? 微軟官方的說法是 ---- 主機(jī)負(fù)責(zé)應(yīng)用程序啟動(dòng)和生存期管理 說白了就是啟動(dòng)程序和程序的生命周期的管理 主要用于配置服務(wù)器和請(qǐng)求處理管道。 主機(jī)還可以設(shè)置日志記錄、依賴關(guān)系注入和配置 就是一系列配置都是主機(jī)來做的
最后來講一下最重要的管道和中間件
public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddControllers();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}}看一下這段代碼 我們先看第一個(gè)方法?ConfigureServices 這個(gè)方法其實(shí)很多人都用過 它是用來配置IOC容器 因?yàn)镃ore最核心的點(diǎn)就在于我們要遵循依賴注入的原則 舉個(gè)例子 我們想要吃一個(gè)蘋果 我們要怎么做 當(dāng)然是去商店買一個(gè) 而不是我們自己造一個(gè)?為啥呢?因?yàn)槲覀儧]有造蘋果的圖紙啊 也就是說 我們想要造一個(gè)蘋果 首先我們需要一個(gè)造蘋果的圖紙 這樣其實(shí)我們就和蘋果類聯(lián)系在一起了 這個(gè)圖紙 在程序里就叫做構(gòu)造方法 而例子里面的商店 其實(shí)就是IOC容器 我們想要蘋果就去商店買 我們不關(guān)心蘋果是怎么造出來的 都是商店來處理 我們就和蘋果解耦了 這就是非常典型的DI(依賴注入)思想 IOC容器其實(shí)就是反轉(zhuǎn)控制容器 幫我們?cè)鞂?shí)例的容器 我們要的話直接找它拿就好了 我們就不用去 new() 對(duì)象了
話說回來?ConfigureServices 方法其實(shí)作用就是將我們這些“蘋果”進(jìn)行注冊(cè) 說白了就是我們要給IOC容器提供構(gòu)造方法吧 否則IOC容器也不知道怎么生產(chǎn)蘋果 那怎么注冊(cè)呢 請(qǐng)看下圖:
services.AddSingleton();services.AddTransient();services.AddScoped();可以看出來 后面兩個(gè)泛型參數(shù)第一個(gè)是實(shí)現(xiàn)類的接口 第二個(gè)是實(shí)現(xiàn)類 一共是三種方法進(jìn)行注冊(cè) 我們要怎么區(qū)分這三種方法呢?
(1)AddSingleton() 這個(gè)表示單例 首次請(qǐng)求會(huì)創(chuàng)建這個(gè)服務(wù)實(shí)例 應(yīng)用程序生命周期中從頭到尾只有這一個(gè)實(shí)例存在
(2)services.AddTransient() 這個(gè)表示瞬時(shí) 每次請(qǐng)求或用到這個(gè)實(shí)例 全部都是重新創(chuàng)建的
(3)services.AddScoped() 這個(gè)表示在同一個(gè)http請(qǐng)求中 或者說同一個(gè)線程中 這個(gè)實(shí)例只會(huì)被創(chuàng)建一次 舉個(gè)例子 A依賴B 請(qǐng)求進(jìn)來了 A在方法里多次使用了B 那這個(gè)B的實(shí)例 都是同一個(gè) 加入下一次請(qǐng)求來了 那么就不是同一個(gè)了
多提一句 系統(tǒng)本來就注冊(cè)好的服務(wù)是已經(jīng)設(shè)定好生命周期的 假如我們要自定義服務(wù) 我們要給它設(shè)定生命周期 注意 若同一個(gè)服務(wù)接口我們多次注冊(cè) 后面會(huì)覆蓋前面注冊(cè)的
我們?cè)賮砜吹诙€(gè)方法Configure 這個(gè)方法其實(shí)就是用來構(gòu)建管道 增加中間件的
IApplicationBuilder 其實(shí)就是一個(gè)管道構(gòu)建器 我們看到下面的方法不斷在app.UseXXX() 其實(shí)這都是擴(kuò)展方法 其實(shí)都是在添加中間件 http請(qǐng)求進(jìn)來 所有的一切 都是中間件 不論是什么控制器 服務(wù)類 路由 身份驗(yàn)證… 全部都是中間件 中間件之間的關(guān)系是怎么樣的 執(zhí)行順序是怎么樣的 這是一個(gè)難點(diǎn) 首先說執(zhí)行順序 實(shí)際上中間件是從第一個(gè)開始 執(zhí)行到最后一個(gè) 然后從最后一個(gè)一直到第一個(gè)進(jìn)行返回 中間件原則是:1.能將請(qǐng)求傳遞給下一個(gè)中間件 2.能夠進(jìn)行響應(yīng),使管道短路? 短路是非常有必要的 沒有短路就沒有返回了 假如我們沒有設(shè)置在最后的短路中間件 系統(tǒng)會(huì)有一個(gè)報(bào)錯(cuò)的最后中間件 強(qiáng)制短路返回
執(zhí)行順序很有意思 先看我們自己寫的自定義中間件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use(async (context, next) =>{await context.Response.WriteAsync("First Begin \r\n ");await next();await context.Response.WriteAsync("First End \r\n ");});app.Use(async (context, next) =>{await context.Response.WriteAsync("Second Begin \r\n ");await next();await context.Response.WriteAsync("Second End \r\n ");});app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapGet("/", async context =>{await context.Response.WriteAsync("Hello World! \r\n");});});}可以看到我們寫了兩個(gè)自定義中間件 我們直接運(yùn)行 看看他們執(zhí)行順序是咋樣的:
是不是很有意思!我們現(xiàn)在就能理解了 next()實(shí)際上就是一個(gè)去找下一個(gè)中間件的委托 或者說next其實(shí)就是下一個(gè)中間件 先按照順序執(zhí)行第一個(gè)中間件 然后next去找下一個(gè)中間件 第二個(gè)中間件的begin執(zhí)行 然后執(zhí)行next 找到下面的helloworld 這時(shí)候沒有下一個(gè)輸出了 這時(shí)候就返回了 從helloworld 到第二個(gè)中間件里面的代碼 就到了第二個(gè)的end 然后返回到第一個(gè)中間件 就到了第一個(gè)的end 就是這樣一個(gè)順序
而且我們也可以自己寫中間件 就像我圖上所示?app.Use() 方法 一共兩個(gè)參數(shù)
public static IApplicationBuilder Use(this IApplicationBuilder app, Func, Task> middleware){throw null;}第一個(gè)那個(gè)this是拓展方法用的 是一種方便用的簡寫 從第二個(gè)參數(shù)開始 我們看到實(shí)際上這個(gè)參數(shù)是一個(gè)委托 這個(gè)委托也有兩個(gè)參數(shù) 第一個(gè)是Http的上下文對(duì)象 第二個(gè)參數(shù)是一個(gè)Task型委托 其實(shí)就是我們的next 返回值也是一個(gè)Task 表明它指向的是一個(gè)異步方法
說白了 兩個(gè)參數(shù)其實(shí)就是?(context, next) 整體是異步的 所以前面要加 async 方法體里面調(diào)用的時(shí)候要用await? 因?yàn)閚ext本身是異步方法
實(shí)際上在Core底層 next指向的就是下一個(gè)方法 委托其實(shí)就是一個(gè)函數(shù)指針 整體的處理是 先用一個(gè)List將所有中間件倒序放入 然后挨個(gè)取出 然后把反序第一個(gè) 也就是原先最后一個(gè)中間件當(dāng)參數(shù)傳遞給前一個(gè)中間件的next 所以就能串起來 執(zhí)行的時(shí)候第一個(gè)便可以根據(jù)next獲得下一個(gè)中間件 其實(shí)我們想一下 這不就是鏈表嗎 委托就是函數(shù)指針 鏈表里面的元素就是方法 不過都是用指針來處理的而已
最后還要提一點(diǎn) 要是我們寫自定義中間件 要用擴(kuò)展方法 這是約定原則
總結(jié)
以上是生活随笔為你收集整理的.netcore基础知识(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视频播放过程中做视频问答(视频弹题功能)
- 下一篇: 2020找工作更难了?做好这4方面,找到