3. 应用启动 Startup
3.1 Startup
类
Startup
类是 ASP.NET Core
应用程序启动默认调用的类,该类是在 Program.cs
中配置:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace Furion.Web.Entry
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.Inject()
.UseStartup<Startup>();
});
}
}
}
3.1.2 Startup
两个重要方法
Startup
默认有两个重要的方法:
ConfigureServices
:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务Configure
:配置应用请求处理管道
默认代码如下:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Furion.Web.Entry
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
在这里,不打算详细讲 Startup
类的具体功能和作用。
了解更多
想了解更多 Startup
知识可查阅 ASP.NET Core - Startup 类 章节。
3.2 AppStartup
在 Furion
框架中,提供了更为灵活的 Startup
类配置方式,无需在 Web 启用层
中配置,可将配置放到任何项目层。
可能会有读者有疑问,为什么要多此一举呢?原因有几点:
Startup
类默认和Web 应用层
绑定在一起,这样就会导致如果我创建了新的Web 应用层
,Startup
又要重新配置- 随着业务的增长,需要集成越来越多的第三方服务,这时候
Startup
类就会变得越来越臃肿,难以维护 Startup
类无法与其他项目类型进行共用
所以,Furion
提供了更加灵活的配置方式:AppStartup
。
注意事项
如果 AppStartup
的派生类所在的项目层没有被启动层直接或间接添加引用,那么这个 Startup.cs
就会被忽略,也就是不会自动载入注册。
3.2.1 如何配置 AppStartup
AppStartup
是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。
3.2.2 AppStartup
约定
AppStartup
派生类只有两个小约定:
- 任何公开、非静态、返回值为
void
且方法第一个参数是IServiceCollection
类型,那么他就是一个ConfigureServices
方法 - 任何公开、非静态、返回值为
void
且方法第一个参数是IApplicationBuilder
类型,第二个参数是IWebHostEnvironment
类型,那么他就是一个Configure
方法
所以,我们可以自由的编写方法,只要遵循约定即可,如:
using Microsoft.Extensions.DependencyInjection;
namespace Furion.EntityFramework.Core
{
public class MyStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDataValidation();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
}
// 可以随意定义名字和方法
public void XXXXName(IServiceCollection services)
{
}
// 可以随意定义名字和方法
public void ZZZName(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
3.2.3 AppStartup
配置顺序
默认情况下,AppStartup
配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 AppStartup
派生类中贴 [AppStartup(order)]
特性即可。
order
数值越大,越在前面调用,如:
using Microsoft.Extensions.DependencyInjection;
namespace Furion.EntityFramework.Core
{
[AppStartup(10)]
public class FirstStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
using Microsoft.Extensions.DependencyInjection;
namespace Furion.EntityFramework.Core
{
[AppStartup(9)]
public class SecondStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
FirstStartup
会在 SecondStartup
之前调用。
3.2.4 AppStartup
方法调用顺序
AppStartup
方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。
3.3 Startup
配置最佳实践
建议 Web
启动层的 Startup.cs
保持为空方法体,如:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Furion.Web.Entry
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
将所有 Web 应用层
配置迁移到 Furion.Web.Core.Startup.cs
中,如:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Furion.Web.Core
{
[AppStartup(800)]
public sealed class FurWebCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCorsAccessor();
services.AddControllers().AddInject();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCorsAccessor();
app.UseAuthentication();
app.UseAuthorization();
app.UseInject();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
这样,后续更换 Web 应用层
也无需重新配置 Startup.cs
3.4 构造函数注入说明
AppStartup
的派生类并未提供依赖注入的功能,也即是无法通过构造函数进行注入服务。原因是 AppStartup
是个空类,目的是用来查找 Startup
的。
那如何像 Startup.cs
一样使用服务呢?
- 获取配置
IConfiguration
实例:通过App.Configuration
- 解析服务:通过
App.GetService<TService>()
或app.ApplicationServices.GetService<TService>()
关于 Configure
方法注入
AppStartup
针对 Configure
方法提供了参数解析注入功能,也就是只要在方法中声明接口参数即可自动注入,如:
// app 和 env 会自动注入
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
3.5 关于 appsettings.json
在默认情况下,ASP.NET Core
配置放在 appsettings.json
中配置,但是这样的方式和 Startup.cs
配置一样的道理,一旦我们更换了 Web 应用层
,那么 appsettings.json
又要重新配置一次。
所以,Furion
框架提供了更加灵活的方式配置 appsettings.json
,只需要在任何项目层根目录下创建 .json
文件即可。Furion
框架最后会自动合并所有分散的配置文件。
如我们在 Furion.EntityFramework.Core
层创建 dbsettings.json
配置数据库连接字符串,如:
{
"ConnectionStrings": {
"DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",
"Sqlite3ConnectionString": "Data Source=./Furion.db"
}
}
无需在 appsettings.json
中配置,下面是 appsettings.json
默认代码:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Information"
}
},
"AllowedHosts": "*"
}
这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。
特别注意
其他层的配置文件不能以 appsettings.json
命名,会导致覆盖启动层的配置。
另外,在其他层创建的 *.json
文件必须设置文件属性为 始终复制或较新复制
。
3.6 神奇的 Inject()
Inject()
方法是 Furion
框架提供的最小侵入式的方法,可以让任何 ASP.NET Core
Web 项目瞬间支持所有 Furion
框架特性。
我们创建了新的 Web 项目
,只需要三个步骤即可:
- 添加
Furion.Web.Core
项目引用 - 在
Program.cs
中调用即可 - 将
Startup.cs
代码迁移到Furion.Web.Core
项目的Startup.cs
中
如:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace Furion.Web.Entry
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.Inject()
.UseStartup<Startup>();
});
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Furion.Web.Entry
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}
Startup.cs
代码迁移
只需要将 ConfigureServices
和 Configure
方法代码迁移到 Furion.Web.Core.Startup.cs
中即可,而 Startup.cs
中两个方法留空即可。
非常简单吧。我们后续创建任何 MVC
,RazorPages
,Blazor
项目只需要添加 Furion.Web.Core
引用和调用 Inject()
即可。
了解更多
想了解更多 Inject
知识可查阅 2.4 神奇的 Inject 章节。
3.7 反馈与建议
与我们交流
给 Furion 提 Issue。