[从0到1搭建ABP微服务] - 搭建Business微服务

简介

互联网产品主要分为两大类,分别是B端产品和C端产品。B端产品主要管业务(Business)代表系统有ERP、WMS、CRM等,C端产品主要管消费者(Consumer)代表主要就是各种电商网站如淘宝、京东等。本篇文章将基于ABP框架搭建一个Business微服务,后续我会逐渐添加一些实用的业务功能到Business服务中。

新建项目

在MicroServices目录中创建一个新的 asp.net core 项目Business.Host

空项目结果如下:

DDD分层

在空项目中使用DDD设计思想搭建分层架构,在Business解决方案中添加以下新的类库

安装模块组件

Domain层

在空Business.Domain层中安装ABP组件
PM> Install-Package Volo.Abp.Ddd.Domain
PM> Install-Package Volo.Abp.Localization
PM> Install-Package Volo.Abp.Validation

Application.Contracts层

在空Business.Application.Contracts层中安装ABP组件并引用Domain层
PM> Install-Package Volo.Abp.Ddd.Application

Application层

在空Business.Application层中安装ABP组件和引用Application.Contracts层
PM> Install-Package Volo.Abp.AutoMapper

EntityFrameworkCore层

在空Business.EntityFrameworkCore层中安装EF Core、ABP组件和引用Domain层
PM> Install-Package Microsoft.EntityFrameworkCore.Design
PM> Install-Package Volo.Abp.EntityFrameworkCore
PM> Install-Package Volo.Abp.EntityFrameworkCore.SqlServer
PM> Install-Package Volo.Abp.AuditLogging.EntityFrameworkCore
PM> Install-Package Volo.Abp.PermissionManagement.EntityFrameworkCore
PM> Install-Package Volo.Abp.SettingManagement.EntityFrameworkCore
PM> Install-Package Volo.Abp.TenantManagement.EntityFrameworkCore

HttpApi层

在空Business.HttpApi层中安装ABP组件和引用Application.Contracts层
PM> Install-Package Volo.Abp.AspNetCore.Mvc

HttpApi.Client层

在空Business.HttpApi.Client层中安装ABP组件和引用Application.Contracts层
PM> Install-Package Volo.Abp.Http.Client

Host层

在空Business.Host层中安装ids4、redis、serilog、swagger、ABP组件和引用Application、EntityFrameworkCore层、HttpApi层
PM> Install-Package Microsoft.EntityFrameworkCore.Tools
PM> Install-Package IdentityServer4.AccessTokenValidation -Version 3.0.1
PM> Install-Package Serilog.AspNetCore -Version 3.2.0
PM> Install-Package Serilog.Sinks.File -Version 4.1.0
PM> Install-Package Serilog.Sinks.Elasticsearch -Version 6.5.0
PM> Install-Package Swashbuckle.AspNetCore -Version 5.0.0
PM> Install-Package Microsoft.Extensions.Caching.StackExchangeRedis -Version 3.1.0
PM> Install-Package Microsoft.AspNetCore.DataProtection.StackExchangeRedis -Version 3.1.0
PM> Install-Package Volo.Abp.Autofac
PM> Install-Package Volo.Abp.AspNetCore.MultiTenancy
PM> Install-Package Volo.Abp.AspNetCore.Serilog
PM> Install-Package Volo.Abp.Caching

配置Module

添加BusinessDomainModule

在Business.Domain层中添加BusinessDomainModule.cs

    [DependsOn(
        typeof(AbpLocalizationModule)
    )]
    public class BusinessDomainModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpVirtualFileSystemOptions>(options =>
            {
                options.FileSets.AddEmbedded<BusinessDomainModule>("Business");
            });

            Configure<AbpLocalizationOptions>(options =>
            {
                options.Resources
                    .Add<BusinessResource>("en")
                    .AddBaseTypes(typeof(AbpValidationResource))
                    .AddVirtualJson("/Localization/Business");
            });

            Configure<AbpMultiTenancyOptions>(options =>
            {
                options.IsEnabled = MultiTenancyConsts.IsEnabled;
            });
        }
    }

添加BusinessApplicationContractsModule

在Business.Application.Contracts层中添加BusinessApplicationContractsModule.cs

    [DependsOn(
        typeof(AbpDddApplicationModule)
    )]
    public class BusinessApplicationContractsModule : AbpModule
    {

    }

添加BusinessApplicationModule

在Business.Application层中添加BusinessApplicationModule.cs

    [DependsOn(
        typeof(BusinessDomainModule),
        typeof(BusinessApplicationContractsModule),
        typeof(AbpAutoMapperModule)
    )]
    public class BusinessApplicationModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<BusinessApplicationModule>();
            });
        }
    }

添加BusinessEntityFrameworkCoreModule

在Business.EntityFrameworkCore层中添加Business.EntityFrameworkCore

    [DependsOn(
        typeof(BusinessDomainModule),
        typeof(AbpEntityFrameworkCoreModule)
    )]
    public class BusinessEntityFrameworkCoreModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddAbpDbContext<BusinessDbContext>(options =>
            {
                options.AddDefaultRepositories(includeAllEntities: true);
            });
        }
    }

添加BusinessHttpApiModule

在Business.HttpApi层中添加Business.HttpApi.cs

    [DependsOn(
        typeof(BusinessApplicationContractsModule),
        typeof(AbpAspNetCoreMvcModule)
    )]
    public class BusinessHttpApiModule : AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            PreConfigure<IMvcBuilder>(mvcBuilder =>
            {
                mvcBuilder.AddApplicationPartIfNotExists(typeof(BusinessHttpApiModule).Assembly);
            });
        }
    }

添加BusinessHttpApiClientModule

在Business.HttpApi.Client层中添加Business.HttpApi.Client.cs

    [DependsOn(
        typeof(BusinessApplicationContractsModule)
    )]
    public class BusinessHttpApiClientModule : AbpModule
    {
        public const string RemoteServiceName = "Business";

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

添加BusinessHostModule

在Business.Host层中添加BusinessHostModule.cs

    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(AbpEntityFrameworkCoreSqlServerModule),
        typeof(AbpPermissionManagementEntityFrameworkCoreModule),
        typeof(AbpSettingManagementEntityFrameworkCoreModule),
        typeof(AbpAuditLoggingEntityFrameworkCoreModule),
        typeof(AbpTenantManagementEntityFrameworkCoreModule),
        typeof(BusinessHttpApiModule),
        typeof(BusinessApplicationModule),
        typeof(AbpAspNetCoreMultiTenancyModule),
        typeof(AbpAspNetCoreSerilogModule)
    )]
    public class BusinessHostModule : AbpModule
    {
        private const string DefaultCorsPolicyName = "Default";

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

            ConfigureConventionalControllers();
            ConfigureAuthentication(context, configuration);
            ConfigureLocalization();
            ConfigureSql();
            ConfigureCache(configuration);
            ConfigureVirtualFileSystem(context);
            ConfigureRedis(context, configuration, hostingEnvironment);
            ConfigureCors(context, configuration);
            ConfigureSwaggerServices(context);
        }

        private void ConfigureSql()
        {
            Configure<AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();
            });    
        }

        private void ConfigureCache(IConfiguration configuration)
        {
            Configure<AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "Business:";
            });
        }

        private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            if (hostingEnvironment.IsDevelopment())
            {
                Configure<AbpVirtualFileSystemOptions>(options =>
                {
                    options.FileSets.ReplaceEmbeddedByPhysical<BusinessDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Domain"));
                    options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application.Contracts"));
                    options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application"));
                });
            }
        }

        private void ConfigureConventionalControllers()
        {
            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(BusinessApplicationModule).Assembly);
            });
        }

        private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = configuration["AuthServer:Authority"];
                    options.RequireHttpsMetadata = true;
                    options.ApiName = "BusinessService";
                });
        }

        private static void ConfigureSwaggerServices(ServiceConfigurationContext context)
        {
            context.Services.AddSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "Business Service API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) => true);
                });
        }

        private void ConfigureLocalization()
        {
            Configure<AbpLocalizationOptions>(options =>
            {
                options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
                options.Languages.Add(new LanguageInfo("en", "en", "English"));
                options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
                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", "繁體中文"));
            });
        }

        private void ConfigureRedis(
            ServiceConfigurationContext context,
            IConfiguration configuration,
            IWebHostEnvironment hostingEnvironment)
        {
            context.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = configuration["Redis:Configuration"];
            });

            if (!hostingEnvironment.IsDevelopment())
            {
                var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
                context.Services
                    .AddDataProtection()
                    .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
            }
        }

        private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddCors(options =>
            {
                options.AddPolicy(DefaultCorsPolicyName, builder =>
                {
                    builder
                        .WithOrigins(
                            configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();

            app.UseCorrelationId();
            app.UseVirtualFiles();
            app.UseRouting();
            app.UseCors(DefaultCorsPolicyName);
            app.UseAuthentication();
            if (MultiTenancyConsts.IsEnabled)
            {
                app.UseMultiTenancy();
            }
            app.UseAuthorization();
            app.UseAbpRequestLocalization();

            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Business Service API");
            });

            app.UseAuditing();
            app.UseAbpSerilogEnrichers();
            app.UseMvcWithDefaultRouteAndArea();
        }

种子文件和配置文件

配置文件如下:

{
  "App": {
    "CorsOrigins": "https://*.abc.com,http://localhost:9527"
  },
  "ConnectionStrings": {
    "Default": "Server=localhost;Database=ABP;User Id=sa;Password=123456;",
    "Business": "Server=localhost;Database=Business;User Id=sa;Password=123456;"
  },
  "Redis": {
    "Configuration": "localhost"
  },
  "AuthServer": {
    "Authority": "https://localhost:53362"
  }
}

启动

Ctrl+F5运行

测试API

在swagger中测试/api/test接口

测试成功

代码地址:https://github.com/WilliamXu96/ABP-MicroService
文章目录:https://www.cnblogs.com/william-xu/p/12537155.html

posted @ 2020-04-02 17:17  一曲肝腸斷  阅读(1305)  评论(7编辑  收藏