BusinessHostModule.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. using Autofac.Core;
  2. using Business.Core.MongoDBHelper;
  3. using Business.Core.Utilities;
  4. using Business.EntityFrameworkCore;
  5. using Business.MultiTenancy;
  6. using Business.Quartz;
  7. using Microsoft.AspNetCore.Authentication.JwtBearer;
  8. using Microsoft.AspNetCore.Builder;
  9. using Microsoft.AspNetCore.Cors;
  10. using Microsoft.AspNetCore.DataProtection;
  11. using Microsoft.AspNetCore.Hosting;
  12. using Microsoft.Extensions.Configuration;
  13. using Microsoft.Extensions.DependencyInjection;
  14. using Microsoft.Extensions.Hosting;
  15. using Microsoft.Extensions.Logging;
  16. using Microsoft.OpenApi.Models;
  17. using NLog;
  18. using NLog.Extensions.Logging;
  19. using NLog.Web;
  20. using Quartz;
  21. using Serilog.Events;
  22. using StackExchange.Redis;
  23. using System;
  24. using System.Collections.Generic;
  25. using System.Data;
  26. using System.IO;
  27. using System.Linq;
  28. using Volo.Abp;
  29. using Volo.Abp.AspNetCore.ExceptionHandling;
  30. using Volo.Abp.AspNetCore.MultiTenancy;
  31. using Volo.Abp.AspNetCore.Mvc;
  32. using Volo.Abp.AspNetCore.Serilog;
  33. using Volo.Abp.Autofac;
  34. using Volo.Abp.Caching;
  35. using Volo.Abp.Data;
  36. using Volo.Abp.EntityFrameworkCore.MySQL;
  37. using Volo.Abp.Localization;
  38. using Volo.Abp.Modularity;
  39. using Volo.Abp.MultiTenancy;
  40. using Volo.Abp.Threading;
  41. using Volo.Abp.VirtualFileSystem;
  42. namespace Business
  43. {
  44. [DependsOn(
  45. typeof(AbpAutofacModule),
  46. typeof(AbpEntityFrameworkCoreMySQLModule),
  47. typeof(BusinessHttpApiModule),
  48. typeof(BusinessApplicationModule),
  49. typeof(BusinessEntityFrameworkCoreModule),
  50. typeof(AbpAspNetCoreMultiTenancyModule),
  51. typeof(AbpAspNetCoreSerilogModule)
  52. )]
  53. public class BusinessHostModule : AbpModule
  54. {
  55. private const string DefaultCorsPolicyName = "Default";
  56. public override void ConfigureServices(ServiceConfigurationContext context)
  57. {
  58. var configuration = context.Services.GetConfiguration();
  59. var hostingEnvironment = context.Services.GetHostingEnvironment();
  60. //ConfigureConventionalControllers();
  61. ConfigureMultiTenancy();
  62. ConfigureAuthentication(context, configuration);
  63. ConfigureLocalization();
  64. ConfigureCache(configuration);
  65. ConfigureVirtualFileSystem(context, hostingEnvironment);
  66. //ConfigureRedis(context, configuration, hostingEnvironment);
  67. ConfigureCors(context, configuration);
  68. ConfigureSwaggerServices(context, configuration);
  69. ConfigureQuartz(context, configuration);
  70. //MongoDB依赖注入
  71. ConfigureMongoDB(configuration);
  72. if (hostingEnvironment.IsDevelopment())
  73. {
  74. Configure<AbpExceptionHandlingOptions>(options =>
  75. {
  76. options.SendExceptionsDetailsToClients = true;
  77. });
  78. }
  79. }
  80. private void ConfigureConventionalControllers()
  81. {
  82. Configure<AbpAspNetCoreMvcOptions>(options =>
  83. {
  84. options.ConventionalControllers.Create(typeof(BusinessApplicationModule).Assembly);
  85. });
  86. }
  87. private void ConfigureMultiTenancy()
  88. {
  89. Configure<AbpMultiTenancyOptions>(options =>
  90. {
  91. options.IsEnabled = true;
  92. });
  93. }
  94. private void ConfigureQuartz(ServiceConfigurationContext context, IConfiguration configuration)
  95. {
  96. //程序启动执行一次日志分表检查,可以自己初始化避免需要部署脚本
  97. LogHostedService logHostedService = new LogHostedService();
  98. logHostedService.LogInstall();
  99. context.Services.AddQuartz(q =>
  100. {
  101. q.UseMicrosoftDependencyInjectionScopedJobFactory();
  102. // Just use the name of your job that you created in the Jobs folder.
  103. var jobKey = new JobKey("SyncDataJob");
  104. q.AddJob<SyncMySQLDataJob>(opts => opts.WithIdentity(jobKey));
  105. q.AddTrigger(opts => opts
  106. .ForJob(jobKey)
  107. .WithIdentity("SyncDataJob-trigger")
  108. .WithCronSchedule("0 40 9 * * ?")
  109. .WithDescription("定时同步MySQL基础数据到MongoDB"));
  110. var NLogJobKey = new JobKey("NLogJob");
  111. q.AddJob<NLogJob>(opts => opts.WithIdentity(NLogJobKey));
  112. q.AddTrigger(opts => opts
  113. .ForJob(NLogJobKey)
  114. .WithIdentity("NLogJob-trigger")
  115. .WithCronSchedule("0 01 01 * * ?")
  116. .WithDescription("定时创建NLog日志按月分表"));
  117. var ExtJobKey = new JobKey("ExtJob");
  118. q.AddJob<ExtJob>(opts => opts.WithIdentity(ExtJobKey));
  119. q.AddTrigger(opts => opts
  120. .ForJob(ExtJobKey)
  121. .WithIdentity("ExtJob-trigger")
  122. .WithCronSchedule("0 01 01 * * ?")
  123. .WithDescription("定时处理金蝶同步到Ext数据库的数据"));
  124. var WMSJobKey = new JobKey("WMSJob");
  125. q.AddJob<WMSJob>(opts => opts.WithIdentity(WMSJobKey));
  126. q.AddTrigger(opts => opts
  127. .ForJob(WMSJobKey)
  128. .WithIdentity("WMSJob-trigger")
  129. .WithCronSchedule("0 34 11 * * ?")
  130. .WithDescription("定时同步WMS物料订单等基础数据到MySQL"));
  131. //var ProductionScheduleJobKey = new JobKey("ProductionScheduleJob");
  132. //q.AddJob<ProductionScheduleJob>(opts => opts.WithIdentity(ProductionScheduleJobKey));
  133. //q.AddTrigger(opts => opts
  134. // .ForJob(ProductionScheduleJobKey)
  135. // .WithIdentity("ProductionScheduleJob-trigger")
  136. // .WithCronSchedule("0 01 01 * * ?")
  137. // .WithDescription("定时排产任务"));
  138. });
  139. context.Services.AddQuartzServer(options =>
  140. {
  141. // when shutting down we want jobs to complete gracefully
  142. options.WaitForJobsToComplete = true;
  143. });
  144. //context.Services.AddQuartzHostedService(options =>
  145. //{
  146. // // when shutting down we want jobs to complete gracefully
  147. // options.WaitForJobsToComplete = true;
  148. //});
  149. }
  150. /// <summary>
  151. /// MongoDB依赖注入
  152. /// </summary>
  153. /// <param name="context"></param>
  154. /// <param name="configuration"></param>
  155. private void ConfigureMongoDB(IConfiguration configuration)
  156. {
  157. Configure<Config>(options =>
  158. {
  159. options.connectstring = configuration.GetConnectionString("MongoDB");
  160. options.database = configuration.GetConnectionString("DBName");
  161. });
  162. }
  163. private void ConfigureCache(IConfiguration configuration)
  164. {
  165. Configure<AbpDistributedCacheOptions>(options =>
  166. {
  167. options.KeyPrefix = "dopbiz:";
  168. });
  169. }
  170. private void ConfigureVirtualFileSystem(ServiceConfigurationContext context, IWebHostEnvironment webHostEnvironment)
  171. {
  172. //var hostingEnvironment = context.Services.GetHostingEnvironment();
  173. if (webHostEnvironment.IsDevelopment())
  174. {
  175. Configure<AbpVirtualFileSystemOptions>(options =>
  176. {
  177. options.FileSets.ReplaceEmbeddedByPhysical<BusinessDomainModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Domain"));
  178. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationContractsModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application.Contracts"));
  179. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application"));
  180. });
  181. }
  182. }
  183. private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
  184. {
  185. context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  186. .AddJwtBearer(options =>
  187. {
  188. options.Authority = configuration["AuthServer:Authority"];
  189. options.RequireHttpsMetadata = false;
  190. options.Audience = "BusinessService";
  191. });
  192. }
  193. private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
  194. {
  195. if (configuration["UseSwagger"] == "true")
  196. {
  197. context.Services.AddSwaggerGen(options =>
  198. {
  199. options.SwaggerDoc("v1", new OpenApiInfo { Title = "Business Service API", Version = "v1" });
  200. options.DocInclusionPredicate((docName, description) => true);
  201. options.CustomSchemaIds(type => type.FullName);
  202. options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
  203. {
  204. Description = "请输入JWT令牌,例如:Bearer 12345abcdef",
  205. Name = "Authorization",
  206. In = ParameterLocation.Header,
  207. Type = SecuritySchemeType.ApiKey,
  208. Scheme = "Bearer"
  209. });
  210. options.AddSecurityRequirement(new OpenApiSecurityRequirement()
  211. {
  212. {
  213. new OpenApiSecurityScheme
  214. {
  215. Reference = new OpenApiReference
  216. {
  217. Type = ReferenceType.SecurityScheme,
  218. Id = "Bearer"
  219. },
  220. Scheme = "oauth2",
  221. Name = "Bearer",
  222. In = ParameterLocation.Header,
  223. },
  224. new List<string>()
  225. }
  226. });
  227. });
  228. }
  229. }
  230. private void ConfigureLocalization()
  231. {
  232. Configure<AbpLocalizationOptions>(options =>
  233. {
  234. options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
  235. options.Languages.Add(new LanguageInfo("en", "en", "English"));
  236. options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
  237. options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
  238. options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
  239. options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
  240. });
  241. }
  242. private void ConfigureRedis(
  243. ServiceConfigurationContext context,
  244. IConfiguration configuration,
  245. IWebHostEnvironment hostingEnvironment)
  246. {
  247. context.Services.AddStackExchangeRedisCache(options =>
  248. {
  249. options.Configuration = configuration["Redis:Configuration"];
  250. });
  251. if (!hostingEnvironment.IsDevelopment())
  252. {
  253. var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
  254. context.Services
  255. .AddDataProtection()
  256. .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
  257. }
  258. }
  259. private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
  260. {
  261. context.Services.AddCors(options =>
  262. {
  263. options.AddPolicy(DefaultCorsPolicyName, builder =>
  264. {
  265. builder
  266. .WithOrigins(
  267. configuration["App:CorsOrigins"]
  268. .Split(",", StringSplitOptions.RemoveEmptyEntries)
  269. .Select(o => o.RemovePostFix("/"))
  270. .ToArray()
  271. )
  272. .WithAbpExposedHeaders()
  273. .SetIsOriginAllowedToAllowWildcardSubdomains()
  274. .AllowAnyHeader()
  275. .AllowAnyMethod()
  276. .AllowCredentials();
  277. });
  278. });
  279. }
  280. public override void OnApplicationInitialization(ApplicationInitializationContext context)
  281. {
  282. var app = context.GetApplicationBuilder();
  283. var configuration = context.GetConfiguration();
  284. app.UseCorrelationId();
  285. app.UseStaticFiles();
  286. app.UseRouting();
  287. app.UseCors(DefaultCorsPolicyName);
  288. app.UseAuthentication();
  289. app.UseAbpClaimsMap();
  290. if (MultiTenancyConsts.IsEnabled)
  291. {
  292. app.UseMultiTenancy();
  293. }
  294. app.UseAbpRequestLocalization();
  295. if (configuration["UseSwagger"] == "true")
  296. {
  297. app.UseSwagger();
  298. app.UseSwaggerUI(options =>
  299. {
  300. options.SwaggerEndpoint("/swagger/v1/swagger.json", "Business Service API");
  301. });
  302. }
  303. app.UseAuditing();
  304. app.UseAbpSerilogEnrichers();
  305. app.UseUnitOfWork();
  306. app.UseConfiguredEndpoints();
  307. AsyncHelper.RunSync(async () =>
  308. {
  309. using (var scope = context.ServiceProvider.CreateScope())
  310. {
  311. await scope.ServiceProvider
  312. .GetRequiredService<IDataSeeder>()
  313. .SeedAsync();
  314. }
  315. });
  316. }
  317. }
  318. }