1. 入口文件

  一个应用程序总有一个入口文件,是应用启动代码开始执行的地方,这里往往也会涉及到应用的各种配置。当我们接触到一个新框架的时候,可以从入口文件入手,了解入口文件,能够帮助我们更好地理解应用的相关配置以及应用的工作方式。

  .Net Core 应用的入口文件是 Program.cs,这里是应用启动的地方。在 .Net 6 之前的版本,Program.cs 文件是下面这样的,这是创建一个 Web 项目时的默认代码。

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<Startup>();
});
}

  其中 Main 方法就是应用启动的入口。可以看到在应用启动的时候,通过 建造者模式 创建了一个主机,并进行了相关的配置,最后将其运行起来。

  从代码中可以看到,在对主机进行配置的时候,使用到了 Startup 类,在 .Net 6 之前的版本,Startup 类承担应用的启动任务,是应用配置的主要地方。

2. Startup 类

2.1 Startup类结构

  Startup 类支持两种定义方式,一种是实现 IStartup 接口,一种是基于约定的。无论哪一种,Startup 类的基本结构都包含以下两个个关键函数。整体来说,基于约定的 Startup 类更加灵活。

  • ConfigureServices方法
  • Configure方法

2.1.2 ConfigureServices 方法

  • 该方法是可选的
  • 该方法用于添加服务到DI容器中
  • 该方法在 Configure 方法之前被调用
  • 基于约定的情况下,该方法要么无参数,要么只能有一个参数且类型必须为 IServiceCollection
  • 该方法内的代码大多是形如 Add{Service} 的扩展方法

2.1.3 Configure方法

  • 该方法是必须的
  • 该方法用于配置 HTTP 请求管道,通过向管道添加中间件,应用不同的响应方式。
  • 该方法在 ConfigureServices 方法之后被调用
  • 基于约定的情况下,该方法中的参数可以接受任何已注入到DI容器中的服务
  • 该方法内的代码大多是形如 Use{Middleware} 的扩展方法
  • 该方法内中间件的注册顺序与代码的书写顺序是一致的,先注册的先执行,后注册的后执行

  另外还有构造函数,当使用通用主机时,Startup 构造函数支持注入以下三种服务类型,在 Startup 类中全局进行使用:

  • IConfiguration
  • IWebHostEnvironment
  • IHostEnvironment

2.2 缺省Startup

  所谓缺省Startup,就是应用启动配置不用 Startup 类,直接在 ConfigureWebHostDefaults 中进行配置。

publicstaticIHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// ConfigureServices 可以调用多次,最终会将结果聚合
webBuilder.ConfigureServices(services =>
{
})
// Configure 如果调用多次,则只有最后一次生效.
.Configure(app =>
{
// Configure调用之前,ConfigureServices已经调用,容器对象已经生成,所以这里可以通过容器直接解析需要的对象
var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
});
});

2.3 多环境配置

  .NET Core 框架支持多环境开发,可以通过环境变量 ASPNETCORE_ENVIRONMENT 来设置应用当前的运行环境,以实现一套代码在不同环境下运行,根据环境区分一定的行为,支持开发、测试、预发布、生成环境下不同条件、不同配置的运行场景。

  我们可以直接在机器的环境变量中进行设置,在项目的 Properties 文件夹里面的“launchSettings.json”文件进行配置,该文件是用于配置VS中项目启动的,在 profiles 节点中通过不同的 json 对象配置当前应用的启动模式,而描述启动模式的 json 对象支持的字段中有一个 environmentVariables 节点,可以通过键值对方式配置环境变量。

  这里配置的环境变量只会在当前项目中起作用。若应用运行环境中从未对 ASPNETCORE_ENVIRONMENT 环境变量进行配置,则默认为 Production 。而我们其实可以将 ASPNETCORE_ENVIRONMENT 设置为任意值。

  之后,这些环境变量会在主机初始化的时候作为主机配置被加载到应用中,这些会在后面的配置系统中详细讲到。而在代码中,我们可以通过注入 IWebHostEnvironment 服务获取到当前应用的运行环境。例如下面在 StartUp 中通过判断环境执行不同的应用初始化逻辑。

  IWebHostEnvironment 服务中默认提供对 Development、Production、Staging 三种环境进行判断的扩展方法,如果是其他自定的环境,如 Test,可以使用 IsEnviroment() 方法进行判断。

  通过 IWebHostEnvironment 判断不同环境,从而在 StartUp 类中使用不同的初始化初始化逻辑,这种方式适合于不同环境下代码差异较少的情况。除此之外还有两种基于约定的方式,分别是 Startup 方法约定 和 StartUp 类名约定 。

  StartUp 方法约定具体是指 StartUp 类中 ConfigureServices 和 Configure 方法还可以按照Configure{EnvironmentName}Services和Configure{EnvironmentName}Services 这样的命名格式来写,通过命名约定的 {EnvironmentName} 部分区分不同环境,装载不同环境的代码。

  如果 StartUp 类中存在与当前环境名称匹配的 Configure{EnvironmentName}Services和Configure{EnvironmentName}Services 方法的话,则应用启动时会执行相应的方法中的逻辑,如果没有则执行原始的 ConfigureServices 和 Configure 方法中的逻辑。

  通过查看源码,可以看到当我们明确配置一个 Startup 类作为应用启动类的时候,会先判断是否是实现了 IStartup 接口。

  如果没有的话,则通过 StartupLoader 判断 Startup 类是否符合约定,最终构建出实现了 IStartup 接口的ConventionBasedStartup,并注入到容器中。这时候会结合环境变量,优先获取带有环境变量的方法,如果没有则使用没有带环境变量的方法。





  而 StartUp 类名约定和方法约定类似,程序启动时,会优先寻找当前环境命名符合Startup{EnvironmentName}的 Startup 类,如果找不到,则使用名称为Startup的类。类名约定的方式适用于多环境下,代码差异较大的情况。

  类名约定的方式下,在配置使用 UseStartUp 的时候需要一点小改动:

  查看源码,可以看到在我们调用上面的方法的时候,实际上并没有做具体的 Startup 类的构建操作,只是写入了两个设置,其实就是写入到了配置系统中,其中 WebHostDefaults.StartupAssemblyKey 是关键。

  之后在我们应用启动,调用Build方法时,在构建ASP.NET Core 基本服务的时候才会根据设置去构建启动类。

  在这里通过 StartupLoader 结合环境名称查找程序集中符合约定的 Startup 类。

参考文章:

理解ASP.NET Core - Startup

ASP.NET CORE 3.1 — 应用启动

ASP.NET Core 系列总结:

目录:ASP.NET Core 系列总结

下一篇:ASP.NET Core - IStartupFilter与IHostingStartup

ASP.NET Core - 入口文件的更多相关文章

  1. ASP.NET Core 静态文件 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 静态文件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 静态文件 前几章节中,我们学习了 ASP.NET Core 的中间件 ...

  2. ASP.NET Core静态文件中间件[1]: 搭建文件服务器

    虽然ASP.NET Core是一款"动态"的Web服务端框架,但是由它接收并处理的大部分是针对静态文件的请求,最常见的是开发Web站点使用的3种静态文件(JavaScript脚本. ...

  3. 细说ASP.NET Core静态文件的缓存方式

    一.前言 我们在优化Web服务的时候,对于静态的资源文件,通常都是通过客户端缓存.服务器缓存.CDN缓存,这三种方式来缓解客户端对于Web服务器的连接请求压力的. 本文指在这三个方面,在ASP.NET ...

  4. ASP.NET Core 静态文件及JS包管理器(npm, Bower)的使用

    在 ASP.NET Core 中添加静态文件 虽然ASP.NET主要大都做着后端的事情,但前端的一些静态文件也是很重要的.在ASP.NET Core中要启用静态文件,需要Microsoft.AspNe ...

  5. 解决ASP.NET Core Mvc文件上传限制问题

    一.简介 在ASP.NET Core MVC中,文件上传的最大上传文件默认为20MB,如果我们想上传一些比较大的文件,就不知道怎么去设置了,没有了Web.Config我们应该如何下手呢? 二.设置上传 ...

  6. asp.net core webapi文件上传

    最近开发一个新项目,使用了asp.net core 2.0,采用webapi开发后台,postgresql为数据库.最先来的问题就是上传文件的问题. POST文件的一些坑 使用默认模板创建webapi ...

  7. ASP.NET Core 返回文件、用户下载文件,从网站下载文件,动态下载文件

    ASP.NET Core 中,可以在静态目录添加文件,直接访问就可以下载.但是这种方法可能不安全,也不够灵活. 我们可以在 Controller 控制器中 添加 一个 Action,通过此Action ...

  8. ASP.NET Core 静态文件

    静态文件(HTML,CSS,图片和Javascript之类的资源)会被ASP.NET Core应用直接提供给客户端. 静态文件通常位于网站根目录(web root) <content-root& ...

  9. ASP.NET Core单文件和多文件上传并保存到服务端

    前言: 在我们日常开发中,关于图片,视频,音频,文档等相关文件上传并保存到服务端中是非常常见的一个功能,今天主要是把自己在开发中常用的两种方式记录下来方便一下直接使用,并且希望能够帮助到有需要的同学! ...

  10. ASP.NET Core静态文件处理源码探究

    前言     静态文件(如 HTML.CSS.图像和 JavaScript)等是Web程序的重要组成部分.传统的ASP.NET项目一般都是部署在IIS上,IIS是一个功能非常强大的服务器平台,可以直接 ...

随机推荐

  1. Prometheus 监测 RocketMQ 最佳实践

    本文作者:郭雨杰,阿里云智能技术专家. Prometheus 集成的 50 多款云产品中,RocketMQ 在可观测方面实现了非常完善的功能,是一个特别具有代表性的云产品. 01 RocketMQ如何 ...

  2. iOS逆向之某多多App抓包

    阅读此文档的过程中遇到任何问题,请关注公众号[移动端Android和iOS开发技术分享]或加QQ群[309580013] 1.目标 由于某多多App现使用longlink进行数据传输,使用charle ...

  3. vcenter异常死机无法重启

    esxi主机异常掉电重启后,vcenter启动失败 查阅相关资料发现,一般是由于时间同步异常造成, 推荐方法是先确认bios硬件时间已同步,再删除旧的本地服务json文件,重启vcenter的服务. ...

  4. PyTorch Geometric Temporal 介绍 —— 数据结构和RGCN的概念

    Introduction PyTorch Geometric Temporal is a temporal graph neural network extension library for PyT ...

  5. audio解决不能自动播放问题

    问题描述 无法实现打开网页就能自动播放音乐 正常情况下使用autoplay即可实现自动播放,但是现在打开网页该参数无效 原因分析: 根据最新的规范,Chrome系浏览器,没有交互过的网站默认禁止自动播 ...

  6. PLSql在Oracle中创建表空间

    create tablespace db_test --表空间名 datafile 'D:\oracle\product\11.2.0\dbhome_1\oradata\orcl\test.dbf' ...

  7. 数电第四周周结_by_yc

    数电第四周周结 1.赋值语句 基本概念: 连续赋值:   1.连续赋值不能出现在过程块(如initial,always)中间:   2.连续赋值语句之间是并行的:   3. 只能对wire型变量进行赋 ...

  8. JVM面试点汇总

    JVM面试点汇总 我们会在这里介绍我所涉及到的JVM相关的面试点内容,本篇内容持续更新 我们会介绍下述JVM的相关面试点: JVM内存结构 内存溢出问题 方法区与永久代和元空间 JVM内存参数 JVM ...

  9. 【Linux】个人笔记本安装Centos并开放22端口供外网连接

    〇.参考资料 一.配置及安装内容 (一)配置 [today]低配笔记本(装centos):4+500G 个人电脑(装三个节点的虚拟机集群环境):8+628G (二)所装软件 Linux系统(可选cen ...

  10. 【RocketMQ】主从同步实现原理

    主从同步的实现逻辑主要在HAService中,在DefaultMessageStore的构造函数中,对HAService进行了实例化,并在start方法中,启动了HAService: public c ...