我们知道NET Core
应用程序的核心配置在项目中的Startup.cs
文件.
public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { //... return services.AddAbp<WebModule>(//...); } public void Configure(IApplicationBuilder app) { app.UseAbp(//...); //... } }
public void ConfigureServices(IServiceCollection services)
方法主要用于将服务添加到DI
容器中并做一些配置.public void Configure(IApplicationBuilder app)
配置请求管道.
Abp
框架使用自己的DI容器(主要为了兼容之前的NET Framework版本和使用一些高级特性,如拦截器),所以我们在ConfigureServices
方法的底部会看到return services.AddAbp(//...)
这时候ConfigureServices
的方法返回值也变成了IServiceProvider
(关于这点请参考:默认服务容器替换)
框架与ASPNET Core
深度集成的地方就在AddAbp
方法和UseAbp
的内部:
public static class AbpServiceCollectionExtensions { /// <summary> /// Integrates ABP to AspNet Core. /// </summary> /// <typeparam name="TStartupModule">Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.</typeparam> /// <param name="services">Services.</param> /// <param name="optionsAction">An action to get/modify options</param> public static IServiceProvider AddAbp<TStartupModule>(this IServiceCollection services, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null) where TStartupModule : AbpModule { var abpBootstrapper = AddAbpBootstrapper<TStartupModule>(services, optionsAction); ConfigureAspNetCore(services, abpBootstrapper.IocManager); return WindsorRegistrationHelper.CreateServiceProvider(abpBootstrapper.IocManager.IocContainer, services); } private static void ConfigureAspNetCore(IServiceCollection services, IIocResolver iocResolver) { //See https://github.com/aspnet/Mvc/issues/3936 to know why we added these services. services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>(); //Use DI to create controllers services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); //Use DI to create view components services.Replace(ServiceDescriptor.Singleton<IViewComponentActivator, ServiceBasedViewComponentActivator>()); //Change anti forgery filters (to work proper with non-browser clients) services.Replace(ServiceDescriptor.Transient<AutoValidateAntiforgeryTokenAuthorizationFilter, AbpAutoValidateAntiforgeryTokenAuthorizationFilter>()); services.Replace(ServiceDescriptor.Transient<ValidateAntiforgeryTokenAuthorizationFilter, AbpValidateAntiforgeryTokenAuthorizationFilter>()); //Add feature providers var partManager = services.GetSingletonServiceOrNull<ApplicationPartManager>(); partManager?.FeatureProviders.Add(new AbpAppServiceControllerFeatureProvider(iocResolver)); //Configure JSON serializer services.Configure<MvcJsonOptions>(jsonOptions => { jsonOptions.SerializerSettings.ContractResolver = new AbpMvcContractResolver(iocResolver) { NamingStrategy = new CamelCaseNamingStrategy() }; }); //Configure MVC services.Configure<MvcOptions>(mvcOptions => { mvcOptions.AddAbp(services); }); //Configure Razor services.Insert(0, ServiceDescriptor.Singleton<IConfigureOptions<RazorViewEngineOptions>>( new ConfigureOptions<RazorViewEngineOptions>( (options) => { options.FileProviders.Add(new EmbeddedResourceViewFileProvider(iocResolver)); } ) ) ); } private static AbpBootstrapper AddAbpBootstrapper<TStartupModule>(IServiceCollection services, Action<AbpBootstrapperOptions> optionsAction) where TStartupModule : AbpModule { var abpBootstrapper = AbpBootstrapper.Create<TStartupModule>(optionsAction); services.AddSingleton(abpBootstrapper); return abpBootstrapper; } }
AbpBootstrapper
作为Abp
核心的引导类,负责初始化Abp
系统,加载插件,配置Abp
和模块以及启动模块(PreInitialize
,Initialize
, PostInitialize
). 这个引导类在console应用程序中同样可以启动Abp
ϵͳ.
接下来Abp
配置和替换了多个MVC
的组件,如IControllerActivator,IViewComponentActivator,MvcJsonOptions,MvcOptions
更多的配置在mvcOptions.AddAbp(services)
方法下:
internal static class { public static void AddAbp(this MvcOptions options, IServiceCollection services) { AddConventions(options, services); AddFilters(options); AddModelBinders(options); } private static void AddConventions(MvcOptions options, IServiceCollection services) { options.Conventions.Add(new AbpAppServiceConvention(services)); } private static void AddFilters(MvcOptions options) { options.Filters.AddService(typeof(AbpAuthorizationFilter)); options.Filters.AddService(typeof(AbpAuditActionFilter)); options.Filters.AddService(typeof(AbpValidationActionFilter)); options.Filters.AddService(typeof(AbpUowActionFilter)); options.Filters.AddService(typeof(AbpExceptionFilter)); options.Filters.AddService(typeof(AbpResultFilter)); } private static void AddModelBinders(MvcOptions options) { options.ModelBinderProviders.Insert(0, new AbpDateTimeModelBinderProvider()); } }
AbpAppServiceConvention
主要用于配置动态API,这个后面会有一章单独说明.
AbpAuthorizationFilter AbpAuditActionFilter AbpValidationActionFilter AbpUowActionFilter AbpExceptionFilter AbpResultFilter
依次添加6个MVC
过滤器分别实现授权,审计,参数验证,工作单元,异常处理以及返回内容的包装.(请注意过滤器顺序很重要)
AbpDateTimeModelBinderProvider
用作DateTime
的统一时区处理.
接下来我们再看UseAbp
方法:
public static class AbpApplicationBuilderExtensions { public static void UseAbp(this IApplicationBuilder app) { app.UseAbp(null); } public static void UseAbp([NotNull] this IApplicationBuilder app, Action<AbpApplicationBuilderOptions> optionsAction) { Check.NotNull(app, nameof(app)); var options = new AbpApplicationBuilderOptions(); optionsAction?.Invoke(options); if (options.UseCastleLoggerFactory) { app.UseCastleLoggerFactory(); } InitializeAbp(app); if (options.UseAbpRequestLocalization) { //TODO: This should be added later than authorization middleware! app.UseAbpRequestLocalization(); } if (options.UseSecurityHeaders) { app.UseAbpSecurityHeaders(); } } public static void UseEmbeddedFiles(this IApplicationBuilder app) { app.UseStaticFiles( new StaticFileOptions { FileProvider = new EmbeddedResourceFileProvider( app.ApplicationServices.GetRequiredService<IIocResolver>() ) } ); } private static void InitializeAbp(IApplicationBuilder app) { var abpBootstrapper = app.ApplicationServices.GetRequiredService<AbpBootstrapper>(); abpBootstrapper.Initialize(); var applicationLifetime = app.ApplicationServices.GetService<IApplicationLifetime>(); applicationLifetime.ApplicationStopping.Register(() => abpBootstrapper.Dispose()); } public static void UseCastleLoggerFactory(this IApplicationBuilder app) { var castleLoggerFactory = app.ApplicationServices.GetService<Castle.Core.Logging.ILoggerFactory>(); if (castleLoggerFactory == null) { return; } app.ApplicationServices .GetRequiredService<ILoggerFactory>() .AddCastleLogger(castleLoggerFactory); } public static void UseAbpRequestLocalization(this IApplicationBuilder app, Action<RequestLocalizationOptions> optionsAction = null) { var iocResolver = app.ApplicationServices.GetRequiredService<IIocResolver>(); using (var languageManager = iocResolver.ResolveAsDisposable<ILanguageManager>()) { var supportedCultures = languageManager.Object .GetLanguages() .Select(l => CultureInfo.GetCultureInfo(l.Name)) .ToArray(); var options = new RequestLocalizationOptions { SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }; var userProvider = new AbpUserRequestCultureProvider(); //0: QueryStringRequestCultureProvider options.RequestCultureProviders.Insert(1, userProvider); options.RequestCultureProviders.Insert(2, new AbpLocalizationHeaderRequestCultureProvider()); //3: CookieRequestCultureProvider options.RequestCultureProviders.Insert(4, new AbpDefaultRequestCultureProvider()); //5: AcceptLanguageHeaderRequestCultureProvider optionsAction?.Invoke(options); userProvider.CookieProvider = options.RequestCultureProviders.OfType<CookieRequestCultureProvider>().FirstOrDefault(); userProvider.HeaderProvider = options.RequestCultureProviders.OfType<AbpLocalizationHeaderRequestCultureProvider>().FirstOrDefault(); app.UseRequestLocalization(options); } } public static void UseAbpSecurityHeaders(this IApplicationBuilder app) { app.UseMiddleware<AbpSecurityHeadersMiddleware>(); } }
核心InitializeAbp(app)
,使用上文之前提到AbpBootstrapper
引导启动Abp
系统.(我们知道Abp模块有个Shutdown()
方法,Abp
使用IApplicationLifetime
接口捕获应用程序事件实现模块的Shoutdown
)
之后按需启动几个中间件,如: RequestLocalization
,SecurityHeaders
等(这些小组件和之前的过滤器后面我会分别详细介绍,这里就不深入讲解)
Abp中文网:https://cn.abp.io/
Abp交流群:735901849(纯技术交流,无广告,不卖课)