BusinessHostModule.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. using Autofac.Core;
  2. using Business.Core.MongoDBHelper;
  3. using Business.EntityFrameworkCore;
  4. using Business.HangFire;
  5. using Business.MultiTenancy;
  6. using Hangfire;
  7. using Hangfire.Dashboard.BasicAuthorization;
  8. using Hangfire.MySql;
  9. using Hangfire.MySql.Core;
  10. using Microsoft.AspNetCore.Authentication.JwtBearer;
  11. using Microsoft.AspNetCore.Builder;
  12. using Microsoft.AspNetCore.Cors;
  13. using Microsoft.AspNetCore.DataProtection;
  14. using Microsoft.AspNetCore.Hosting;
  15. using Microsoft.Extensions.Configuration;
  16. using Microsoft.Extensions.DependencyInjection;
  17. using Microsoft.Extensions.Hosting;
  18. using Microsoft.OpenApi.Models;
  19. using StackExchange.Redis;
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Data;
  23. using System.IO;
  24. using System.Linq;
  25. using System.Security.Cryptography.Pkcs;
  26. using Volo.Abp;
  27. using Volo.Abp.AspNetCore.ExceptionHandling;
  28. using Volo.Abp.AspNetCore.MultiTenancy;
  29. using Volo.Abp.AspNetCore.Mvc;
  30. using Volo.Abp.AspNetCore.Serilog;
  31. using Volo.Abp.Autofac;
  32. using Volo.Abp.Caching;
  33. using Volo.Abp.Data;
  34. using Volo.Abp.EntityFrameworkCore.MySQL;
  35. using Volo.Abp.Localization;
  36. using Volo.Abp.Modularity;
  37. using Volo.Abp.MultiTenancy;
  38. using Volo.Abp.Threading;
  39. using Volo.Abp.VirtualFileSystem;
  40. namespace Business
  41. {
  42. [DependsOn(
  43. typeof(AbpAutofacModule),
  44. typeof(AbpEntityFrameworkCoreMySQLModule),
  45. typeof(BusinessHttpApiModule),
  46. typeof(BusinessApplicationModule),
  47. typeof(BusinessEntityFrameworkCoreModule),
  48. typeof(AbpAspNetCoreMultiTenancyModule),
  49. typeof(AbpAspNetCoreSerilogModule)
  50. )]
  51. public class BusinessHostModule : AbpModule
  52. {
  53. private const string DefaultCorsPolicyName = "Default";
  54. public override void ConfigureServices(ServiceConfigurationContext context)
  55. {
  56. var configuration = context.Services.GetConfiguration();
  57. var hostingEnvironment = context.Services.GetHostingEnvironment();
  58. //ConfigureConventionalControllers();
  59. ConfigureMultiTenancy();
  60. ConfigureAuthentication(context, configuration);
  61. ConfigureLocalization();
  62. ConfigureCache(configuration);
  63. ConfigureVirtualFileSystem(context, hostingEnvironment);
  64. //ConfigureRedis(context, configuration, hostingEnvironment);
  65. ConfigureCors(context, configuration);
  66. ConfigureSwaggerServices(context, configuration);
  67. ConfigureHangfire(context, configuration);
  68. //MongoDB依赖注入
  69. ConfigureMongoDB(configuration);
  70. if(hostingEnvironment.IsDevelopment())
  71. {
  72. Configure<AbpExceptionHandlingOptions>(options =>
  73. {
  74. options.SendExceptionsDetailsToClients = true;
  75. });
  76. }
  77. }
  78. private void ConfigureConventionalControllers()
  79. {
  80. Configure<AbpAspNetCoreMvcOptions>(options =>
  81. {
  82. options.ConventionalControllers.Create(typeof(BusinessApplicationModule).Assembly);
  83. });
  84. }
  85. private void ConfigureMultiTenancy()
  86. {
  87. Configure<AbpMultiTenancyOptions>(options =>
  88. {
  89. options.IsEnabled = true;
  90. });
  91. }
  92. private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
  93. {
  94. context.Services.AddHangfire(config =>
  95. {
  96. //config.UseStorage(new MySqlStorage(configuration.GetConnectionString("Business"),new MySqlStorageOptions
  97. //{
  98. // TransactionIsolationLevel =IsolationLevel.ReadCommitted,
  99. // QueuePollInterval = TimeSpan.FromSeconds(15),
  100. // JobExpirationCheckInterval = TimeSpan.FromHours(1),
  101. // CountersAggregateInterval = TimeSpan.FromMinutes(5),
  102. // PrepareSchemaIfNecessary = true,
  103. // DashboardJobListLimit = 50000,
  104. // TransactionTimeout = TimeSpan.FromMinutes(1),
  105. // TablePrefix = "Hangfire"
  106. //}));
  107. config.UseStorage(new MySqlStorage(configuration.GetConnectionString("Default"), new MySqlStorageOptions
  108. {
  109. QueuePollInterval = TimeSpan.FromSeconds(15),
  110. JobExpirationCheckInterval = TimeSpan.FromHours(1),
  111. CountersAggregateInterval = TimeSpan.FromMinutes(5),
  112. PrepareSchemaIfNecessary = true,
  113. DashboardJobListLimit = 50000,
  114. TransactionTimeout = TimeSpan.FromMinutes(1),
  115. }));
  116. });
  117. }
  118. /// <summary>
  119. /// MongoDB依赖注入
  120. /// </summary>
  121. /// <param name="context"></param>
  122. /// <param name="configuration"></param>
  123. private void ConfigureMongoDB(IConfiguration configuration)
  124. {
  125. Configure<Config>(options => {
  126. options.connectstring = configuration.GetConnectionString("MongoDB");
  127. options.database = configuration.GetConnectionString("DBName");
  128. });
  129. }
  130. private void ConfigureCache(IConfiguration configuration)
  131. {
  132. Configure<AbpDistributedCacheOptions>(options =>
  133. {
  134. options.KeyPrefix = "dopbiz:";
  135. });
  136. }
  137. private void ConfigureVirtualFileSystem(ServiceConfigurationContext context, IWebHostEnvironment webHostEnvironment)
  138. {
  139. //var hostingEnvironment = context.Services.GetHostingEnvironment();
  140. if (webHostEnvironment.IsDevelopment())
  141. {
  142. Configure<AbpVirtualFileSystemOptions>(options =>
  143. {
  144. options.FileSets.ReplaceEmbeddedByPhysical<BusinessDomainModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Domain"));
  145. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationContractsModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application.Contracts"));
  146. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application"));
  147. });
  148. }
  149. }
  150. private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
  151. {
  152. context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  153. .AddJwtBearer(options =>
  154. {
  155. options.Authority = configuration["AuthServer:Authority"];
  156. options.RequireHttpsMetadata = false;
  157. options.Audience = "BusinessService";
  158. });
  159. }
  160. private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
  161. {
  162. if (configuration["UseSwagger"] == "true")
  163. {
  164. context.Services.AddSwaggerGen(options =>
  165. {
  166. options.SwaggerDoc("v1", new OpenApiInfo { Title = "Business Service API", Version = "v1" });
  167. options.DocInclusionPredicate((docName, description) => true);
  168. options.CustomSchemaIds(type => type.FullName);
  169. options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
  170. {
  171. Description = "请输入JWT令牌,例如:Bearer 12345abcdef",
  172. Name = "Authorization",
  173. In = ParameterLocation.Header,
  174. Type = SecuritySchemeType.ApiKey,
  175. Scheme = "Bearer"
  176. });
  177. options.AddSecurityRequirement(new OpenApiSecurityRequirement()
  178. {
  179. {
  180. new OpenApiSecurityScheme
  181. {
  182. Reference = new OpenApiReference
  183. {
  184. Type = ReferenceType.SecurityScheme,
  185. Id = "Bearer"
  186. },
  187. Scheme = "oauth2",
  188. Name = "Bearer",
  189. In = ParameterLocation.Header,
  190. },
  191. new List<string>()
  192. }
  193. });
  194. });
  195. }
  196. }
  197. private void ConfigureLocalization()
  198. {
  199. Configure<AbpLocalizationOptions>(options =>
  200. {
  201. options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
  202. options.Languages.Add(new LanguageInfo("en", "en", "English"));
  203. options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
  204. options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
  205. options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
  206. options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
  207. });
  208. }
  209. private void ConfigureRedis(
  210. ServiceConfigurationContext context,
  211. IConfiguration configuration,
  212. IWebHostEnvironment hostingEnvironment)
  213. {
  214. context.Services.AddStackExchangeRedisCache(options =>
  215. {
  216. options.Configuration = configuration["Redis:Configuration"];
  217. });
  218. if (!hostingEnvironment.IsDevelopment())
  219. {
  220. var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
  221. context.Services
  222. .AddDataProtection()
  223. .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
  224. }
  225. }
  226. private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
  227. {
  228. context.Services.AddCors(options =>
  229. {
  230. options.AddPolicy(DefaultCorsPolicyName, builder =>
  231. {
  232. builder
  233. .WithOrigins(
  234. configuration["App:CorsOrigins"]
  235. .Split(",", StringSplitOptions.RemoveEmptyEntries)
  236. .Select(o => o.RemovePostFix("/"))
  237. .ToArray()
  238. )
  239. .WithAbpExposedHeaders()
  240. .SetIsOriginAllowedToAllowWildcardSubdomains()
  241. .AllowAnyHeader()
  242. .AllowAnyMethod()
  243. .AllowCredentials();
  244. });
  245. });
  246. }
  247. public override void OnApplicationInitialization(ApplicationInitializationContext context)
  248. {
  249. var app = context.GetApplicationBuilder();
  250. var configuration = context.GetConfiguration();
  251. app.UseCorrelationId();
  252. app.UseStaticFiles();
  253. app.UseRouting();
  254. app.UseCors(DefaultCorsPolicyName);
  255. app.UseAuthentication();
  256. app.UseAbpClaimsMap();
  257. if (MultiTenancyConsts.IsEnabled)
  258. {
  259. app.UseMultiTenancy();
  260. }
  261. app.UseAbpRequestLocalization();
  262. if (configuration["UseSwagger"] == "true")
  263. {
  264. app.UseSwagger();
  265. app.UseSwaggerUI(options =>
  266. {
  267. options.SwaggerEndpoint("/swagger/v1/swagger.json", "Business Service API");
  268. });
  269. }
  270. app.UseAuditing();
  271. app.UseAbpSerilogEnrichers();
  272. app.UseUnitOfWork();
  273. app.UseConfiguredEndpoints();
  274. //app.UseHangfireServer();
  275. app.UseHangfireDashboard(options: new DashboardOptions
  276. {
  277. Authorization = new[]
  278. {
  279. new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions
  280. {
  281. RequireSsl = false,
  282. SslRedirect = false,
  283. LoginCaseSensitive = true,
  284. Users = new []
  285. {
  286. new BasicAuthAuthorizationUser
  287. {
  288. Login = configuration["Hangfire:Login"],
  289. PasswordClear = configuration["Hangfire:Password"]
  290. }
  291. }
  292. })
  293. },
  294. DashboardTitle = "任务调度中心"
  295. });
  296. RecurringJob.AddOrUpdate<IHangFireJobService>(a=>a.SyncDataMySQLData(),CronType.Day(0,0,1),TimeZoneInfo.Local);
  297. AsyncHelper.RunSync(async () =>
  298. {
  299. using (var scope = context.ServiceProvider.CreateScope())
  300. {
  301. await scope.ServiceProvider
  302. .GetRequiredService<IDataSeeder>()
  303. .SeedAsync();
  304. }
  305. });
  306. }
  307. }
  308. }