BusinessHostModule.cs 12 KB

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