emmmm,其实本来想发服务器部署那一篇的笔记的,可奈何折腾了好多天的linux,部署还是有一小丢丢不完美(我还是想完美一些)所以,今天先把core的这篇主线给更新了。
NET Core 管道机制(自己画的将就着看吧)
![v2-e01af13a7b029440dbba372832eae408_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/f9e526a5f56a12c4a9bc5a42c958ccdc.jpeg)
net core默认情况下是通过Startup类来配置服务和管道的。
如上图所示:整个应用如同一个管道,请求进来,经过一个个中间件,最后到达我们的路由,控制器,经过处理,并将结果一步步进行返回。
我们可以将这个管道想象成一个大商场,商场有一个进口(Request)和一个出口(Response),每一个人都是一次请求,经过进口,通过安检(认证),给予你能进入哪些商店(中间件)的权利(授权)。相当于你进去之后,给你发了一张临时的身份识别卡,卡上面有你的全部信息,这个卡可以看做是HttpContext。授权之后,假定你要进入未经授权的商店,肯定会被拒绝,因为你一在他们商店刷卡,就会显示你没有进入此地的权利。
你路过了鲜花店(Middleware),假若你有权利进入,你可以选择进去买鲜花,也可以选择不买。你可以转了一圈商场什么都不做,按原路返回,也可以走到半中腰就回去了。
下面来看一下Startup类的配置。
其中有两个核心的方法。一个是ConfigureServices(服务配置类),一个是Configure(配置类)。
前面有一篇IoC和DI中我写过,在这里再复习一下。
ConfigureServices是用来配置各种各样的服务的,比如认证这个中间件,他是你进入商场的安检关卡,这里就是给安检人员配备相应的设备,比如电脑,身份识别卡,再或者对讲机、警棍等等。没有这些设备,我应用的服务中间件如何能正常工作呢?这里的服务配置添加,不分先后顺序。因为不论是先给警察配好警棍,还是给清洁阿姨准备扫帚。这些都是准备工作,还没到真正服务的时候,所以不分先后顺序。
而Configure中的配置的中间件是区分先后顺序的。比如,先放好静态文件服务、路由服务、之后授权、认证、xxx服务、最后到endoptions控制器,其实控制器也是一个大的中间件,它里面有各种服务,比如过滤器等等。
![v2-52118e4ef3150dc30e6149b7ee5882d3_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/9ab13b582176e1e4c053c7a3f21ef839.jpeg)
中间件是什么呢,如我开头图示,它是一种装配到应用程序管道以处理请求和响应的软件,每个组件可以:
《1》选择是否将请求传递到管道中的下一个组件。
《2》可在调用管道中的下一个组件前后执行工作。即中间件的事前逻辑和事后逻辑。
当然,如果出现错误,它不会再进行下一个组件,而是原路返回。
中间件的写法:
(1)命名:类名后缀:Middleware
(2)构造函数:注入RequestDelegate next
(3)逻辑 异步 命名 :async Task Invoke(HttpContext context)
接下来,我们自己建一个中间件。先说下思路:建一个可以设置全局变量的中间件,当请求经过中间件,分析请求,并将参数解析出来之后,赋值给全局变量。
新建类:SetOptionMiddleware,添加构造函数和方法
![v2-b73d7e7ac16f0d534b3db2cca181e673_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/c55c649432ea7fd13876b265b0297328.jpeg)
至于为什么这样写?没有为什么,这是net core的约定,就是要这么写,它才是一个中间件。构造函数那里我还注入了一个全局类,这个IOptions<class> 这个东西,可以认为是一个公共的对象,它可以从头传到尾,供中间件使用。下图是CommonOption类
![v2-48898a7e18a214e5ea95ef6c64f09e74_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/9d059222771ebf3ca58f308128c91a5e.jpeg)
Invoke的方法如下:
![v2-119b059c49d81c55c5bdb5373e18fbe3_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ec27af43cfbd1ce0ee74c0a21ec4b8b9.jpeg)
解析请求头上附加的参数option,若存在,在将其赋值给全局变量,最后在前端打印出我们传的参数。
接下来,需要在Startup中,添加对此中间件的使用,由于其并没有依赖任何其他外部的工具或服务,所以并不需要为其依赖注入或者配备其他的服务。只需在Configure里添加即可,如下图:
![v2-91b2ccc4c53ce7554f3eb56f0fbd6ed7_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/edbafa1bd5dd5e2aab9a9d354a7d8dd7.jpeg)
但是看起来好像和下面的其他的中间件有点区别,为了遵循微软的规范,我决定学它的写法emmmm(其实我觉得我这样写也还行吧)
新建一个扩展类,如下图:
![v2-a1e756e3fa71d9789782694da0ce6b7b_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/dc6f6112ddf14808b930509d1429ef65.jpeg)
然后,就可以使用:
![v2-8209b56f9c20b6615ba530162be95c93_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/95bd01dc28f3e89399dd0d6deba0315b.jpeg)
接下来,我们在中间件上打上断点,观察变量的变化:
在url上加上参数:
![v2-0ee23f39e8316f57b6e18e1410fff8d5_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ab37add50059f490feeb22c45db7b310.jpeg)
![v2-0cb05b877d9f3408764a7133534076a0_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/bb290af3cb9ad49ba534ee2656cbaa80.jpeg)
如上图所示:可以看到,在给全局对象赋值前,我们的option(请求的参数)是 《巴黎圣母院》 ,全局对象的值是 默认值
继续调试:发现,值有了变化:
![v2-df7097aaa0b1a68bb05ff79efc8b8778_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/8b57a2125b3a682b604e594a8638c21e.jpeg)
继续之后,前端的视图也输出了我们的文本内容,而非默认的Index视图内容
![v2-6fbf9fcd2d35d5ce9b79093c276664f2_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ea1a0b8446f4cb9950f57cb4e553bbdd.jpeg)
emm,今天粗略的中间件就到这里了,接下来是依赖注入:
依赖注入,这个已经是老生常谈了。但还是复习一下,温故而知新,可以为师矣嘛。和之前不一样的是,这次会使用代码示例来研究依赖注入微软源生的三大生命周期(上次粗略的说了下,而且着重用的是第三方IoC:Autofac)
依赖注入是实现松散耦合技术,将依赖关系注入到容器当中。在ASP .NET Core中容器为IServiceProvider接口表示,任何人都可以实现自己的容器。最好使用构造函数注入,第三方IoC容器有:UnityIoC,AutoFac等等。
三大生命周期:
(1)多例模式 Transient。每解析一次接口,就会实例化一个对象。每次对象都是唯一且不同的。 每次解析请求,实例的都是一个全新的对象。
(2)Scoped 英文释为范围,区域。第一次请求,它会实例出一个对象:
IA a=new A();并缓存下来,接下来的每一次请求,会判断是否是同一个HttpContext,如若是同一个,那么它仍然返回这个a对象。
这里解释下,什么叫一次请求。同一次请求,它的HttpContext肯定是同一个,所以返回的都是a。这里Scoped其实就是一次http请求的作用域,同一次请求,可能多次请求其他的服务,也可能多次请求同一个控制器,只是这个人进了商场买东西,不管做什么,还是这个人。 但是它一旦出了这个商场(结束了本次http请求)再次进入商场,就是新的请求了,就需要重新过安检。(虽然还是那个人)
(3)单例模式:singleton 只要服务器不嗝屁,不管解析多少次接口,拿到的都是a。换句话说就是,只要皇帝不死,太子一直是太子!从商场建成开业到商场倒闭关门,此次程序服务过程中,单例返回的始终是这个a。
下面通过代码来践行验证:
新建一个接口,和实现。里面放一个返回guid的方法。如下图:
![v2-387e7080fd46978b049f3fae3f9e4e81_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/f40b53884d8443f9cda0f87453e99501.jpeg)
接着我们在Startup中依赖注入服务。
(1)先使用多例模式
![v2-56d8759397bf75f6215098f46a203e93_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/bf23027c4f1a8581eae7b799469d82ef.jpeg)
控制器和视图如下:
![v2-24edf8c1710cdcd01428706ca3842c04_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/9881cbbe6638ba5265b50312ea1539ce.jpeg)
![v2-217145e9eda70415352135e6e4158ee9_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/2bce9686024900370b38a028577d9886.jpeg)
测试结果如下
![v2-7927f638f317bc667f10540fb3dd2110_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/a5840eb0031e15350e0927a9004b7e82.jpeg)
刷新再尝试:
![v2-4ae5af86571a3614d0da628a211cea97_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/07c1e8c32d10b9518d0a6606dd22dc98.jpeg)
结果四次解析,均不同,验证多例模式:每次解析,实例化的对象都不同。
(2)接着使用Scoped,配置:
![v2-0efc764dc3590dbc3f2fce72e448f1fa_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/6e1be5270ca9ebc14053cb923ec4c5bb.jpeg)
第一次http请求如下图:
![v2-f621d3ff9c5df516eb7ab37ab4c1f1c0_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/8926ae030192455acf49e1e4e6d85f33.jpeg)
第二次请求:
![v2-4ef866455d4199f788435c4226e9cf5e_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/6b6129cba4a872343018fb563a012ef1.jpeg)
两次请求,在同一次请求有效范围内,均产生相同的实例对象。
(3)单例模式
配置如下:
![v2-b75c302f049ecab62a4d78ba3e73431f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/df308c91dae631b6bb6068f7a009d35a.jpeg)
测试如下:
![v2-c0d88b03cf183ae4684425ba14c8efa2_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/860c383a4b2d693ce3466862b6991963.jpeg)
发现,不管刷新多少次,始终返回如上内容对象。证明:单例模式下,从应用程序启动到结束,不管请求多少次,解析多少次接口,始终返回同一对象。
下面是琐碎笔记内容:
(1)出现 已添加了具有相同键的项 错误,前端调试传参无误,后端不进入断点。 原因:后台的接收参数的model可能出现了同样的参数(大小写不一样但是参数一样。C#后台区分大小写,但是前端传过来的参数传输的时候不识别大小写,它给后端,就不知道给谁了。
(2)出现错误 xxxxx could not be located 原因:服务或者类的构造函数没有加public修饰符,导致容器没有足够的访问权限,不能加载,报错。
(3)git命令复习:
git checkout -b name1:创建分支name1并切换到分支name1上,相当于两条命令:git branch name1 git checkout name1 两条命令
在另外一个分支做完之后,commit之后,切换到master分支
git checkout master
之后合并分支
git merge 旧的分支
(4)swagger 配置好之后,访问swaager 报无法发现 ....json 文件
原因是中间件位置没有使用swagger。有三个地方需要添加,第一,configureservice那添加跟服务,并配置好文档。 第二个,configure那使用swagger,使用swaggerUI
如果报500错误,其中一个原因是,你可能没有给你的动作方法加上谓词,因为swagger需要知道你的接口方法是什么httpmethod
(5)几个后缀名文件识别:
bat 批处理程序 bak mssql数据库的备份文件
dmp oracle数据库的备份文件
(6)VS中找到所有的变量,一次性更换到所有的名字
ctrl+f ctrl+h
(7)快速实现接口:alt+enter
(8)调试-窗口-即时 窗口 可以实时观察调试时的变量的值的变化。
好了,今天笔记到这里结束了,有交流的请留言,下次再见。