01手动搭建基本的ABP框架

手动搭建基本的ABP框架

ABP是用于创建现代Web应用程序的完整架构和强大的基础设施! 遵循最佳实践和约定,为你提供SOLID开发经验。

创建项目

创建类库:

  • Domian
  • Domain.Shared
  • Application
  • Application.Contracts
  • EntityFrameworkCore
  • HttpApi
  • HttpApi.Client

创建ASP.NET Core Web 应用 HttpApi.Host,作为后端接口主机。

Domain.Shared

领域共享层,该层存放领域层的常量、枚举、值对象、本土化配置文件和其他对象,这些对象实际是领域层的一部分,但是解决方案中所有的层/项目中都会使用到。

  • 该项目不依赖解决中的其他项目,其他项目直接或间接引用该项目。

需要添加的Nugget包:

  • Volo.Abp.Localization Volo 本地化模块,使应用程序支持全球化

创建文件夹Localization/MyLocalization,在该文件夹下放语言配置配置文件(如:zh-Hans.json)。

在文件夹Localization文件夹下新增类MyLocalizationResource.cs,添加以下代码:

namespace Domain.Shared.Localization
{
    [LocalizationResourceName("MyLocalization")]
    public class MyLocalizationResource
    {
    }
}

在根目录下新增类DomainSharedModule.cs,添加以下代码:

namespace Domain.Shared
{
    // 添加依赖  本地化模组
    [DependsOn(
        typeof(AbpLocalizationModule)
    )]
    public class DomainSharedModule : AbpModule // 必须继承AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            // 配置虚拟文件系统  配置全球化资源文件必须配置该选项
            Configure<AbpVirtualFileSystemOptions>(options =>
            {
                options.FileSets.AddEmbedded<DomainSharedModule>();
            });

            // 配置全球化资源文件
            Configure<AbpLocalizationOptions>(options =>
            {
                options.Resources.Add<MyLocalizationResource>("zh-Hans")
                .AddVirtualJson("/Localization/MyLocalization");

                options.DefaultResourceType = typeof(MyLocalizationResource);
            });

            Configure<AbpExceptionLocalizationOptions>(options =>
            {
                options.MapCodeNamespace("MyLocalization", typeof(MyLocalizationResource));
            });
            base.ConfigureServices(context);
        }
    }
}

Domian

领域层,在该层实现系统核心业务逻辑,该层主要包含实体、集合跟、领域服务、值类型、仓储接口和解决方案的其他领域对象

  • 依赖Domain.Shared,项目中会用到它的一些常量、枚举、值对象和其他对象。

需要添加的Nugget包:

  • Volo.Abp.Ddd.Domain 领域驱动模块

添加类DomainModule.cs,添加以下代码:

namespace Domain
{
    // 依赖领域驱动模块
    // 依赖领域共享模块
    [DependsOn(
        typeof(AbpDddDomainModule),
        typeof(DomainSharedModule)
    )]
    public class DomainModule:AbpModule
    {

    }
}

Application.Contracts

应用约定层,该层存放应用服务接口、数据传输对象、应用层常量和应用层提供程序。他用于分离应用层的接口和实现。这种方式可以将接口项目做为约定包共享给客户端。

  • 依赖Domain.Shared,因为它可能会在应用接口和DTO中使用常量、枚举和其他的共享对象。

需要添加的Nugget包:

  • Volo.Abp.Ddd.Application.Contracts 应用层约定模块

添加类ApplicationContractsModule.cs,添加以下代码:

namespace Application.Contracts
{
    // 依赖应用层约定模块
    // 依赖领域共享模块
    [DependsOn(
        typeof(AbpDddApplicationContractsModule),
        typeof(DomainSharedModule)
    )]
    public class ApplicationContractsModule:AbpModule
    {

    }
}

Application

应用层,该层实现系统应用业务逻辑,实现服务接口。

  • 依赖Application.Contracts,需要实现服务接口与使用DTO。
  • 依赖Domain需要使用领域对象(实体、仓储接口等)执行应用程序逻辑。

需要添加Nugget包:

  • Volo.Abp.Ddd.Application 应用层模块
  • Volo.Abp.AutoMapper 自动映射模块

添加类ApplicationAutoMapperProfile.cs ,应用层自动映射配置类,添加以下代码:

namespace Application
{
    public class ApplicationAutoMapperProfile: Profile
    {
        public ApplicationAutoMapperProfile()
        {
            // 配置自动映射
            //CreateMap<T1, T2>();
        }
    }
}

添加类ApplicationModule.cs,添加以下代码:

namespace Application
{
    // 依赖自动配置模块
    // 依赖领域驱动应用层模块
    // 依赖领域模块
    // 依赖应用层约定模块
    [DependsOn(
        typeof(AbpAutoMapperModule),
        typeof(AbpDddApplicationModule),
        typeof(DomainModule),
        typeof(ApplicationContractsModule)
    )]
    public class ApplicationModule:AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);
            // 配置自动映射
            Configure<AbpAutoMapperOptions>(options => {
                options.AddMaps<ApplicationModule>();
            });
        }
    }
}

EntityFrameworkCore

数据库层,定义了DbContext并实现Domain项目中定义的仓储接口。

  • 依赖Domain,需要引用实体和实现仓储接口。

需要添加Nugget包:

  • Volo.Abp.EntityFrameworkCore.SqlServer SqlServer数据库模块

添加类EntityFrameworkCoreModule.cs,添加以下代码

namespace EntityFrameworkCore
{
    // 依赖SqlServer数据库模块
    [DependsOn(
        typeof(AbpEntityFrameworkCoreSqlServerModule)
    )]
    public class EntityFrameworkCoreModule:AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);
            // 配置使用 SqlServer
            Configure<AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();
            });
        }
    }
}

HttpApi

用于定义API控制器。

大多数情况下,不需要手动定义API控制器,因为ABP的动态API功能会根据应用层自动创建API控制器。但是,如果你需要编写API控制器,则可以在该层中定义。

  • 依赖Application.Contracts 项目,因为它需要注入应用服务接口

需要添加Nugget包:

  • Volo.Abp.AspNetCore.Mvc AspNetCore MVC模块

添加类HttpApiModule.cs,添加以下代码

namespace HttpApi
{
    // 依赖MVC模块
    // 依赖应用约定模块
    [DependsOn(
        typeof(AbpAspNetCoreMvcModule),
        typeof(ApplicationContractsModule)
    )]
    public class HttpApiModule:AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            ConfigureLocalization();
            base.ConfigureServices(context);
        }

        private void ConfigureLocalization()
        {
            // 配置本地化资源库
            Configure<AbpLocalizationOptions>(options => {
                options.Resources
                    .Get<MyLocalizationResource>()
                    .AddBaseTypes(typeof(AbpUiResource));
            });
        }
    }
}

HttpApi.Client

定义C#客户端代理,使用解决方案的HttpAPI项目。可以将该项目共享给第三方客户端,使其轻松的在DotNet应用程序中使用你的HttpAPI(其他类型应用程序可以手动或使用其平台的工具来使用你的API)。

ABP有动态C#API客户端功能,所以大多数情况下你不需要手动创建C#客户端代理。

  • 依赖Application.Contracts,需要使用应用服务接口和DTO

需要添加Nugget包:

  • Volo.Abp.Http.Client

添加类HttpApiClientModule.cs,添加以下代码

namespace HttpApi.Client
{
    [DependsOn(
        typeof(AbpHttpClientModule),
        typeof(ApplicationContractsModule)
    )]
    public class HttpApiClientModule:AbpModule
    {
        public const string RemoteServiceName = "Default";

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddHttpClientProxies(
                typeof(ApplicationContractsModule).Assembly,
                RemoteServiceName
            );

            Configure<AbpVirtualFileSystemOptions>(options => {
                options.FileSets.AddEmbedded<HttpApiClientModule>();
            });
        }
    }
}

HttpApi.Host

HttpAPI主机层,她有自己的appsettings.json文件(数据库链接字符串等其他配置)

  • 依赖HttpApi

由于没有使用分层模式(没有选择--tiered选项),还同时依赖:

  • Application
  • EntityFrameworkCore

需要添加Nugget包:

  • Volo.Abp.Autofac 依赖注入模块
  • Volo.Abp.Swashbuckle

添加类HttpApiHostModule.cs,添加以下代码:

namespace HttpApi.Host
{
    [DependsOn(
        typeof(HttpApiModule),
        typeof(AbpAutofacModule),
        typeof(ApplicationModule),
        typeof(EntityFrameworkCoreModule),
        typeof(AbpSwashbuckleModule)
    )]
    public class HttpApiHostModule:AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            ConfigureUrls(configuration);
            ConfigureVirtualFileSystem(context);
            ConfigureConventionalControllers();
            ConfigureLocalization();
            ConfigureCors(context, configuration);
            ConfigureSwaggerServices(context, configuration);
        }

        /// <summary>
        /// 配置URL
        /// </summary>
        /// <param name="configuration"></param>
        private void ConfigureUrls(IConfiguration configuration)
        {
            Configure<AppUrlOptions>(options =>
            {
                options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
                options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));

                options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"];
            });
        }
        /// <summary>
        /// 配置 虚拟文件系统
        /// </summary>
        /// <param name="context"></param>
        private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            if (hostingEnvironment.IsDevelopment())
            {
                Configure<AbpVirtualFileSystemOptions>(options =>
                {
                    options.FileSets.ReplaceEmbeddedByPhysical<DomainSharedModule>(
                        Path.Combine(hostingEnvironment.ContentRootPath,
                            $"..{Path.DirectorySeparatorChar}Domain.Shared"));

                    options.FileSets.ReplaceEmbeddedByPhysical<DomainModule>(
                        Path.Combine(hostingEnvironment.ContentRootPath,
                            $"..{Path.DirectorySeparatorChar}Domain"));

                    options.FileSets.ReplaceEmbeddedByPhysical<ApplicationContractsModule>(
                        Path.Combine(hostingEnvironment.ContentRootPath,
                            $"..{Path.DirectorySeparatorChar}Application.Contracts"));

                    options.FileSets.ReplaceEmbeddedByPhysical<ApplicationModule>(
                        Path.Combine(hostingEnvironment.ContentRootPath,
                            $"..{Path.DirectorySeparatorChar}Application"));
                });
            }
        }
        /// <summary>
        /// 配置 传统的控制器
        /// </summary>
        private void ConfigureConventionalControllers()
        {
            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(ApplicationModule).Assembly);
            });
        }

        private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAbpSwaggerGenWithOAuth(
                configuration["AuthServer:Authority"],
                new Dictionary<string, string>
                {
                    {"StudyAcme", "StudyAcme API"}
                },
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "StudyAcme API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                });
        }
        /// <summary>
        /// 配置本地化
        /// </summary>
        private void ConfigureLocalization()
        {
            Configure<AbpLocalizationOptions>(options =>
            {
                //options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
                //options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
                //options.Languages.Add(new LanguageInfo("en", "en", "English"));
                //options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
                //options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
                //options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
                //options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
                //options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is"));
                //options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
                //options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
                //options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
                //options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
                //options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
                //options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
                //options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
                options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
                //options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
                //options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
                //options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
                //options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά"));
            });
        }

        /// <summary>
        /// 配置Cors
        /// <para>
        /// 配置跨域请求
        /// </para>
        /// </summary>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(
                            configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
        }

        public override void OnApplicationInitialization(Volo.Abp.ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if(env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAbpRequestLocalization();

            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors();
            app.UseAuthorization();

            app.UseUnitOfWork();
            app.UseAuthorization();

            app.UseSwagger();
            app.UseAbpSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "StudyAcme API");

                var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
                c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                c.OAuthScopes("StudyAcme");
            });

            app.UseAuditing();
            app.UseConfiguredEndpoints();
        }
    }
}

Program.cs类中添加代码:

await builder.AddApplicationAsync<HttpApiHostModule>();

添加测试服务

Application项目中添加类ApplicationAppService,并添加以下代码

    /// <summary>
    /// 应用层服务基类
    /// </summary>
    public abstract class ApplicationAppService:ApplicationService
    {
        protected ApplicationAppService()
        {
            // 配置本地资源
            LocalizationResource = typeof(MyLocalizationResource);
        }
    }

Application项目中添加类TestService,并添加以下代码

    public class TestService: ApplicationAppService
    {
        private IStringLocalizer<MyLocalizationResource> _l;
        public TestService( IStringLocalizer<MyLocalizationResource> l) {
            _l = l;
        }

        public string GetTest()
        {
            return "test service";
        }

        public string GetWellCome()
        {
            return _l["LongWelcomeMessage"].Value;
        }
    }

运行HttpApi.Host可见以下API:
Api

语言选择

使用/Abp/Languages/Switch?culture=zh-Hans&uiCulture=zh-Hans&returnUrl=/ 接口进行语言切换,该接口会在Cookie中添加或更新 lpx_lang=ZH; .AspNetCore.Culture=c=zh-Hans|uic=zh-Hans

posted @ 2022-12-30 18:27  $("#阿飞")  阅读(958)  评论(0编辑  收藏  举报