Startup.cs 13.5 KB
using Autofac.Extensions.DependencyInjection;
using Hh.Mes.Common.config;
using Hh.Mes.Common.log;
using Hh.Mes.Service;
using Hh.Mes.Service.Repository;
using Hh.Mes.Service.SystemAuth;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Linq;
using Quartz;
using Quartz.AspNetCore;
using Quartz.AspNetCore.Logging;
using Quartz.Job.Jobs;
using Quartz.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using WebMvc.Aop;


namespace WebMvc
{
    public class Startup
    {
        public IConfiguration Configuration { get; }
        public IWebHostEnvironment webHostEnvironment { get; set; }

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            webHostEnvironment = env;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            #region 自定义配置appsettings.json 节点 AppSettings.SetAppSetting(Configuration.GetSection("AppCustomSettings"));
            AppSettings.SetAppSetting(Configuration.GetSection("AppCustomSettings"));
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend1 = AppSettings.GetAppSeting("AppCustomExtend1");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend2 = AppSettings.GetAppSeting("AppCustomExtend2");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend3 = AppSettings.GetAppSeting("AppCustomExtend3");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend4 = AppSettings.GetAppSeting("AppCustomExtend4");

            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend5 = AppSettings.GetAppSeting("AppCustomExtend5");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend6 = AppSettings.GetAppSeting("AppCustomExtend6");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend7 = AppSettings.GetAppSeting("AppCustomExtend7");
            ConfigRead.GetInstance.GetAppsetConnection().AppCustomExtend8 = AppSettings.GetAppSeting("AppCustomExtend8");
            #endregion

            services.Configure<FormOptions>(options =>
            {
                options.ValueCountLimit = int.MaxValue;
                options.ValueLengthLimit = int.MaxValue;
                options.KeyLengthLimit = int.MaxValue;
                options.MultipartBodyLengthLimit = int.MaxValue;
                options.MultipartBoundaryLengthLimit = int.MaxValue;
                //解决文件上传Request body too large
                options.MultipartBodyLengthLimit = 268435456;
            });

            services.AddMvc(option =>
            {
                option.EnableEndpointRouting = false;
                option.ModelBinderProviders.Insert(0, new JsonBinderProvider());
                //加入全局异常类
                option.Filters.Add<Aop.HttpGlobalExceptionFilter>();
            }).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

            //Asp.Net Core获取请求上下文HttpContext https://www.cnblogs.com/tianma3798/p/10361644.html
            services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();

            services.AddMemoryCache();
            services.AddOptions();

            #region HTTPS
            //services.AddMvc(options =>
            //{
            //    options.SslPort = ConfigRead.GetInstance.GetAppsetConnection().WebPort;
            //    options.Filters.Add(new RequireHttpsAttribute());
            //});

            //services.AddAntiforgery(
            //    options =>
            //    {
            //        options.Cookie.Name = "_af";
            //        options.Cookie.HttpOnly = true;
            //        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            //        options.HeaderName = "X-XSRF-TOKEN";
            //    });
            #endregion

            //数据库连接地址
            var connectionString = ConfigRead.GetInstance.GetAppsetConnection().BaseDBContext;

            #region 启用Quartz中间件
            services.AddQuartz(options =>
            {
                options.UseSqlServer(connectionString);
                options.UseProperties(false);
            });
            #endregion

            //Redis 设置缓存
            Task.Factory.StartNew(() =>
            {
                new BaseInfoCacheService().SetBaseInfoCacheFirst();
            });

            #region 注册SqlSugars、操作日志、XSS攻击防御等
            //SqlSugars
            services.BatchRegisterService(Program.service, Program.serviceSuffix);
            services.AddDirectoryBrowser();

            //操作日志
            services.AddScoped<OperLogFilter>();
            //services.AddScoped<InterfaceLogFilter>();
            //xss攻击防御
            services.AddScoped<XSSFilterAttribute>();
            #endregion

            #region 注入登录、授权等服务

            services.AddScoped<LoginParse>();
            services.AddScoped<AuthContextFactory>();
            services.AddScoped<SystemAuthStrategy>();
            services.AddScoped<NormalAuthStrategy>();
            services.AddScoped(typeof(IAuth), typeof(LocalAuth));
            #endregion

            //解决开发环境修改html,需要重新编译启动程序,编译发布环境不需要 https://www.cnblogs.com/Can-daydayup/p/13630050.html#!comments
            if (webHostEnvironment.IsDevelopment()) services.AddRazorPages().AddRazorRuntimeCompilation();

            //使用AutoFac进行注入
            return new AutofacServiceProvider(AutofacExt.InitAutofac(services));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                ConfigRead.GetInstance.GetAppsetConnection().IsDevelopment = false;
                app.UseDeveloperExceptionPage();
            }
            else
            {
                if (IsExtSysFile()) return;
                ConfigRead.GetInstance.GetAppsetConnection().IsDevelopment = true;
                app.UseExceptionHandler("/htmlTemp");
            }
            app.UseStaticFiles();

            #region apk https://www.cnblogs.com/1175429393wljblog/p/8624679.html
            app.UseStaticFiles(
                new StaticFileOptions
                {
                    ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
                    {
                                  { ".apk", "application/vnd.android.package-archive" }
                    })
                });
            #endregion

            #region 启用Quartz中间件 开发环境不启用定时器,如果需要注释if条件
            var isDevelopment = ConfigRead.GetInstance.GetAppsetConnection().IsDevelopment;
            if (isDevelopment)
            {
                InitialQuartzAndData(app);
                Console.WriteLine();
                Console.WriteLine("友好提示:webApp线上环境已开启定作业任务,定时器code完成后需要在智能中控Job任务管理中配置!");
            }
            else
            {
                //InitialQuartzAndData(app);
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine();
                Console.WriteLine("友好提示:基础版本扩展新项目后需要重新新建数据库和指定redisRedisDb!");
                Console.WriteLine("友好提示:webApp线下环境未开启定作业任务,定时器code完成后需要在智能中控Job任务管理中配置!!");
                Console.ResetColor();
            }
            Console.WriteLine();

            #endregion

            app.UseMvcWithDefaultRoute();

            #region http 500
            app.UseExceptionHandler(errorApp =>
            {
                errorApp.Run(async context =>
                {
                    context.Response.StatusCode = 500;
                    if (context.Request.Headers["X-Requested-With"] != "XMLHttpRequest")
                    {
                        context.Response.ContentType = "text/html";
                        await context.Response.SendFileAsync($@"{env.WebRootPath}/htmlTemp/500.html");
                    }
                });
            });
            app.UseStatusCodePagesWithReExecute("/htmlTemp/{0}");
            #endregion

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                  name: "areas",
                  template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
                );
            });

            Console.ResetColor();
        }

        #region 自定义方法
        private bool IsExtSysFile()
        {
            var webMvcPath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "WebMvc.xml");
            if (!File.Exists(webMvcPath))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("WebMvc.xml 文件路径不存在,请在bin/Debug 手动拷贝复制该文件到发布目录下面(和appsettings.json平级)!:" + webMvcPath);
                Log4NetHelper.Instance.Info("WebMvc path:" + webMvcPath);
                Console.ReadLine();
                return true;
            }
            var wwwRootPath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "wwwroot");
            if (!Directory.Exists(wwwRootPath))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("wwwroot 文件夹不存在,请手动拷贝复制该文件到发布目录下面(和appsettings.json平级)!:" + webMvcPath);
                Log4NetHelper.Instance.Info("wwwroot path:" + wwwRootPath);
                Console.ReadLine();
                return true;
            }

            var aaptPath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "tools", "aapt.exe");
            if (!File.Exists(aaptPath))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("aapt.exe 文件路径不存在,请在根目录tools/aapt.exe手动拷贝复制该文件到发布目录下面(和appsettings.json平级)!:" + aaptPath);
                Log4NetHelper.Instance.Info("aaptPath path:" + aaptPath);
                Console.ReadLine();
                return true;
            }
            var unzipPath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "tools", "unzip.exe");
            if (!File.Exists(unzipPath))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("unzip.exe 文件路径不存在,请在根目录tools/unzip.exe手动拷贝复制该文件到发布目录下面(和appsettings.json平级)!:" + aaptPath);
                Log4NetHelper.Instance.Info("unzip path:" + unzipPath);
                Console.ReadLine();
                return true;
            }

            return false;
        }

        /// <summary>
        /// 初始化Quartz组件,添加定时任务数据。
        /// 解决服务程序重启后定时任务无法执行问题。
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IApplicationBuilder InitialQuartzAndData(IApplicationBuilder builder)
        {
            LogProvider.SetCurrentLogProvider(builder.ApplicationServices.GetRequiredService<LoggingProvider>());
            var sched = builder.ApplicationServices.GetRequiredService<IScheduler>();
            SysJobRepository sysJobRepository = new SysJobRepository();
            var sysJobs = sysJobRepository.GetList(x => x.status == "0");
            var context = sysJobRepository.Context;

            foreach (var item in sysJobs)
            {
                try
                {
                    var methodParams = item.methodParams;
                    var methodName = item.methodName ?? "";
                    var jobDataMap = new JobDataMap();
                    var json = JObject.Parse(methodParams);
                    if (json.Count > 0)
                    {
                        foreach (var v in json)
                        {
                            jobDataMap.Add(v.Key, v.Value.ToString());
                        }
                    }

                    var classType = Assembly.Load(typeof(JobBase).Assembly.FullName).GetType($"{typeof(JobBase).Namespace}.{methodName}");
                    IJobDetail job = JobBuilder.Create(classType).WithIdentity(item.jobName).UsingJobData(jobDataMap).Build();
                    if (job != null)
                    {
                        //创建一个触发器
                        var trigger = TriggerBuilder.Create().WithIdentity(item.jobName).WithCronSchedule(item.cronExpression).Build();
                        //将触发器和任务器绑定到调度器中
                        sched.DeleteJob(new JobKey(item.jobName)).Wait();
                        sched.ScheduleJob(job, trigger).Wait();
                    }
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.ReadLine();
                    Console.WriteLine($"创建定时任务[{item.jobName}]异常:{ex.Message}");
                    Console.ReadLine();
                }
                sched.Start();
            }
            return builder;
        }
        #endregion
    }
}