BusinessHostModule.cs 12 KB

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