using System; using System.Collections.Generic; using System.IO; using System.Linq; using IdentityModel; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using SettleAccount.EntityFrameworkCore; //using SettleAccount.MultiTenancy; using StackExchange.Redis; using Microsoft.OpenApi.Models; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.Autofac; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.Swashbuckle; using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.VirtualFileSystem; using Hangfire; using Volo.Abp.BackgroundJobs.Hangfire; using SettleAccount.Constant; using Hangfire.SqlServer; using Hangfire.Dashboard.BasicAuthorization; using Volo.Abp.BackgroundWorkers; using SettleAccount.BackgroundJob.HangFireJob.job; using SettleAccount.BackgroundJob.HangFireJob; using Volo.Abp.BackgroundWorkers.Hangfire; using Microsoft.EntityFrameworkCore.Internal; using SettleAccount.Entities.Boms; using Volo.Abp.AspNetCore.Mvc.AntiForgery; using DotNetCore.CAP; using Microsoft.Extensions.DependencyInjection.Extensions; using System.Net.Http; using SettleAccount.UploadFile; using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring.FileSystem; namespace SettleAccount; [DependsOn( typeof(SettleAccountApplicationModule), typeof(SettleAccountEntityFrameworkCoreModule), typeof(SettleAccountHttpApiModule), typeof(AbpAspNetCoreMvcUiMultiTenancyModule), typeof(AbpAutofacModule), typeof(AbpCachingStackExchangeRedisModule), typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(AbpAuditLoggingEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpAspNetCoreSerilogModule), typeof(AbpBackgroundJobsHangfireModule), // typeof(AbpBackgroundWorkersModule), typeof(AbpBackgroundWorkersHangfireModule), typeof(AbpSwashbuckleModule) )] public class SettleAccountHttpApiHostModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); Configure(options => { options.UseSqlServer(); }); //租户功能去掉 //Configure(options => //{ // options.IsEnabled = MultiTenancyConsts.IsEnabled; //}); if (hostingEnvironment.IsDevelopment()) { Configure(options => { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}SettleAccount.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}SettleAccount.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}SettleAccount.Application.Contracts", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}SettleAccount.Application", Path.DirectorySeparatorChar))); }); } //context.Services.AddAbpSwaggerGenWithOAuth( // configuration["AuthServer:Authority"], // new Dictionary // { // {"SettleAccount", "SettleAccount API"} // }, // options => // { // options.SwaggerDoc("v1", new OpenApiInfo {Title = "SettleAccount API", Version = "v1"}); // options.DocInclusionPredicate((docName, description) => true); // options.CustomSchemaIds(type => type.FullName); // }); Configure(options => { options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); }); context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = configuration["AuthServer:Authority"]; options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); options.Audience = "SettleAccountService"; options.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }; }); context.Services.Configure(options => { options.AutoValidate = false; }); Configure(options => { options.KeyPrefix = "SettleAccount:"; }); var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("SettleAccount"); if (!hostingEnvironment.IsDevelopment()) { var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "SettleAccount-Protection-Keys"); } context.Services.AddCors(options => { options.AddDefaultPolicy(builder => { builder .WithOrigins( configuration["App:CorsOrigins"]? .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(o => o.RemovePostFix("/")) .ToArray() ?? Array.Empty() ) .WithAbpExposedHeaders() // .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding") .SetIsOriginAllowedToAllowWildcardSubdomains() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); ConfigureSwaggerServices(context); //注册中间件hangfire ConfigureHangfire(context, configuration); //注册容器 ConfigureBLOBServices(configuration); } /// /// 上传文件的容器 /// /// private void ConfigureBLOBServices(IConfiguration configPath) { Configure(options => { options.Containers.Configure(configuration => { configuration.UseFileSystem(fileSystem => { var filestreampath = Environment.CurrentDirectory + @"\wwwroot\files"; if (!Directory.Exists(filestreampath)) { Directory.CreateDirectory(filestreampath); } fileSystem.BasePath = filestreampath; }); }); }); } /// /// 注册hangfire /// /// /// private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration) { //设置队列 context.Services.AddHangfireServer(options => { options.Queues = new[] { "job1", "job2", "default" }; options.WorkerCount = Environment.ProcessorCount * 5; //并发任务数 --超出并发数。将等待之前任务的完成 (推荐并发线程是cpu 的 5倍) options.ServerName = "default"; }); //context.Services.AddHangfire(config => //{ // config.UseSqlServerStorage(configuration.GetConnectionString("SettleAccount")); //}); //详细配置 context.Services.AddHangfire(x => x.UseStorage(new SqlServerStorage( configuration.GetConnectionString("SettleAccount"), new SqlServerStorageOptions { // TransactionIsolationLevel = IsolationLevel.ReadCommitted, // 事务隔离级别。默认是读取已提交。 QueuePollInterval = TimeSpan.FromSeconds(15), //- 作业队列轮询间隔。默认值为15秒。 JobExpirationCheckInterval = TimeSpan.FromHours(1), //- 作业到期检查间隔(管理过期记录)。默认值为1小时。 CountersAggregateInterval = TimeSpan.FromMinutes(5), //- 聚合计数器的间隔。默认为5分钟。 PrepareSchemaIfNecessary = true, //- 如果设置为true,则创建数据库表。默认是true。 DashboardJobListLimit = 50000, //- 仪表板作业列表限制。默认值为50000。 TransactionTimeout = TimeSpan.FromMinutes(20), //- 交易超时。默认为1分钟。 } )) .UseSerilogLogProvider() .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() // .UseRedisStorage("127.0.0.1:6379") ); } private static void ConfigureSwaggerServices(ServiceConfigurationContext context) { context.Services.AddSwaggerGen( options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "SettleAccount Service API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); var env = context.GetEnvironment(); var configuration = context.GetConfiguration(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } // app.UseHttpsRedirection(); app.UseCookiePolicy(); app.UseCorrelationId(); app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); //if (MultiTenancyConsts.IsEnabled) //{ // app.UseMultiTenancy(); //} app.UseAbpRequestLocalization(); app.UseAuthorization(); app.UseSwagger(); app.UseAbpSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API"); //var configuration = context.GetConfiguration(); options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); options.OAuthScopes("SettleAccount"); }); //打开仪表盘-简单方式 //app.UseHangfireDashboard(); ////拦截器验证 通过验证直接进入仪表盘,没通过验证返回 401 //app.UseHangfireDashboard("/hangfire", new DashboardOptions() //{ // Authorization = new[] { new CustomHangfireAuthorizeFilter() } // ,DashboardTitle = "任务调度中心" //}); //添加面板的打开权限。不是所有人都可以打开面板。可以操作后台任务。 //app.UseHangfireDashboard("", new DashboardOptions //{ // //可视化界面 输入正确进入仪表盘 // Authorization = new[] // { // new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions // { // SslRedirect = false, // 是否将所有非SSL请求重定向到SSL URL // RequireSsl = false, // 需要SSL连接才能访问HangFire Dahsboard。强烈建议在使用基本身份验证时使用SSL // LoginCaseSensitive = false, //登录检查是否区分大小写 // Users = new[] // { // new BasicAuthAuthorizationUser // { // Login =configuration["Hangfire:Login"],//用户名 // PasswordClear=configuration["Hangfire:Password"] // } // } // }) // }, // DashboardTitle = "任务调度中心" //}); //定时任务RecurringJob调用方式1 var service = context.ServiceProvider; //service.UseHangfireTest(); //方式3测试 //RecurringJob.AddOrUpdate("job2",() => Console.WriteLine($"APS.NET Core Hangfire"), Cron.Minutely(), TimeZoneInfo.Local); //调度任务方式2 //context.AddBackgroundWorkerAsync(); app.UseAuditing(); app.UseAbpSerilogEnrichers(); app.UseConfiguredEndpoints(); } }