zoukankan      html  css  js  c++  java
  • Quartz网页笔记整理 与 QuartzHelper实例

    0.Quartz.NET 3.x Tutorial

    Quartz.NET - Quartz.NET 3.x Tutorial

    1.简单的Quartz例子调用

    Quartz.NET实现作业调度

    2.Quartz的调度框架,包含可视化的界面的简单使用

    Quartz.net 开源job调度框架(一)

     3.CronTrigger Tutorial

    Quartz.NET - CronTrigger Tutorial

    4.CrystalQuartz

    Net作业调度(二) -CrystalQuartz远程管理

    5.Quartz Instance

    5.1 Clinet

    5.1.1 使用到的相关实体定义

    [Description("触发器基础信息类")]
        public class TriggerModel
        {
            #region CommonInfo
            /// <summary>
            /// 触发器名称
            /// </summary>
            public string name { get; set; }
    
            /// <summary>
            /// 触发器所在组
            /// </summary>
            public string group { get; set; }
    
            /// <summary>
            /// 触发器描述
            /// </summary>
            public string description { get; set; }
    
            /// <summary>
            /// 触发器开始执行时间
            /// </summary>
            public string startTime { get; set; }
    
            /// <summary>
            /// 触发器结束执行时间
            /// </summary>
            public string endTime { get; set; }
    
            /// <summary>
            /// 触发器所使用的日历过滤器
            /// </summary>
            public string calendarName { get; set; }
    
            /// <summary>
            /// 触发器下次执行时间
            /// </summary>
            public string nextFireTime { get; set; }
    
            /// <summary>
            /// 触发器上次执行时间
            /// </summary>
            public string previousFireTime { get; set; }
    
            /// <summary>
            /// 触发器的触发规则
            /// </summary>
            public string rule { get; set; }
    
            /// <summary>
            /// 触发器触发次数
            /// </summary>
            public int? timesTriggered { get; set; }
    
            /// <summary>
            /// 触发器类型
            /// </summary>
            public string triggerType { get; set; }
    
            /// <summary>
            /// 触发器状态(Normal = 0,Paused = 1,Complete = 2,Error = 3,Blocked = 4,None = 5,)
            /// </summary>
            public int triggerState { get; set; }
    
            /// <summary>
            /// 关联Job组名
            /// </summary>
            public string jobDetailGroup { get; set; }
    
            /// <summary>
            /// 关联Job组名
            /// </summary>
            public string jobDetailName { get; set; }
    
            #endregion
    
            #region SimpleTrigger
            /// <summary>
            /// 触发器重复执行次数
            /// </summary>
            public int repeatCount { get; set; }
    
            /// <summary>
            /// 触发器执行周期
            /// </summary>
            public string repeatInterval { get; set; }
    
            #endregion
    
            #region DailyTimeTrigger
            /// <summary>
            /// 日常触发器每天开始触发时间
            /// </summary>
            public string startTimeOfDay { get; set; }
    
            /// <summary>
            /// 日常触发器每天结束触发时间
            /// </summary>
            public string endTimeOfDay { get; set; }
    
            /// <summary>
            /// 周中天
            /// </summary>
            public string daysOfWeek { get; set; }
            #endregion
    
            #region CronTrigger
            /// <summary>
            /// Cron表达式
            /// </summary>
            public string cronExpression { get; set; }
            #endregion
        }
    
        /// <summary>
        /// Trigger操作类
        /// </summary>
        public class TriggerOperateModel
        {
            /// <summary>
            /// 名称
            /// </summary>
            public string name { get; set; }
    
            /// <summary>
            ////// </summary>
            public string group { get; set; }
    
            /// <summary>
            /// 操作类型
            /// </summary>
            public int operateType { get; set; }
        }
       public class JobMapModel
        {
            public string key { get; set; }
    
            public string value { get; set; }
        }
     [Description("作业信息类")]
        public class JobModel
        {
            /// <summary>
            /// 作业所在组
            /// </summary>     
            public string group { get; set; }
    
            /// <summary>
            /// 作业名称
            /// </summary>
            public string name { get; set; }
    
            /// <summary>
            /// 作业描述
            /// </summary>
            public string description { get; set; }
    
            /// <summary>
            /// 作业类型
            /// </summary>
            public string type { get; set; }
    
            /// <summary>
            /// 作业是否允许孤立存在
            /// </summary>
            public bool durable { get; set; }
    
            /// <summary>
            /// 工作数据字段
            /// </summary>
            public List<JobMapModel> jobDataMap { get; set; }
    
            /// <summary>
            /// 
            /// </summary>
            public bool requestsRecovery { get; set; }
    
            /// <summary>
            /// 并发控制
            /// </summary>
            public bool concurrentExecutionDisallowed { get; set; }
    
            /// <summary>
            /// 执行后JobData数据是否能持久
            /// </summary>
            public bool persistJobDataAfterExecution { get; set; }
    
            /// <summary>
            /// 与JobInfo关联的所有TriggerInfos
            /// </summary>
            public List<TriggerModel> triggerInfos { get; set; }
    
        }
     public class JobTriggerModel
        {
            /// <summary>
            /// 作业名称
            /// </summary>
            public string jobName { get; set; }
    
    
            /// <summary>
            /// 触发器名称
            /// </summary>
            public string triggerName { get; set; }
    
            /// <summary>
            /// 触发器所在组
            /// </summary>     
            public string triggerGroup { get; set; }
    
            /// <summary>
            /// 触发器开始执行时间
            /// </summary>
            public string startTime { get; set; }
    
            /// <summary>
            /// 触发器结束执行时间
            /// </summary>
            //public string endTime { get; set; }
    
    
            /// <summary>
            /// 触发器下次执行时间
            /// </summary>
            public string nextFireTime { get; set; }
    
            /// <summary>
            /// 触发器上次执行时间
            /// </summary>
            public string previousFireTime { get; set; }
        }

    5.1.2 Quartz帮助类

    using Quartz;
    using Quartz.Impl;
    using Quartz.Impl.Matchers;
    using Quartz.Impl.Triggers;
    using Models.QuartzTimedTask;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    public class QuartzHelper
        {
            #region SchedulerOperate
    
            /// <summary>
            /// 创建Scheduler实例
            /// </summary>
            /// <returns></returns>
            public IScheduler CreateScheduler()
            {
                ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
    
                return schedulerFactory.GetScheduler();
            }
    
            #endregion
    
    
            #region private
    
            private bool AddOrEditJobDetail(JobModel jobInfo, bool isReplace)
            {
                var result = false;
                var scheduler = CreateScheduler();
    
    
                //job
                var jobDetail = QuartzConvert.JobInfoToJobDetailImpl(jobInfo);
                var isCheckExistsOk = scheduler.CheckExists(jobDetail.Key);
                isCheckExistsOk = isReplace ? !isCheckExistsOk : isCheckExistsOk;
                if (jobDetail == null || isCheckExistsOk) return false;
    
                //add job
                scheduler.AddJob(jobDetail, isReplace, !jobDetail.Durable);
                result = scheduler.CheckExists(jobDetail.Key);
    
                return result;
            }
    
            #endregion
    
    
            /// <summary>
            /// 添加新的JobDetail
            /// </summary>
            /// <param name="jonInfo"></param>
            /// <returns></returns>
            public bool AddNewJobDetail(JobModel jobInfo)
            {
                return AddOrEditJobDetail(jobInfo, false);
            }
    
            /// <summary>
            /// 编辑JobDetail
            /// </summary>
            /// <param name="jonInfo"></param>
            /// <returns></returns>
            public bool EditJobDetail(JobModel jobInfo)
            {
                return AddOrEditJobDetail(jobInfo, true);
            }
    
            /// <summary>
            /// 删除JobDetail
            /// </summary>
            /// <param name="name"></param>
            /// <param name="group"></param>
            /// <returns></returns>
            public bool DeleteJobDetail(string name, string group)
            {
                var scheduler = CreateScheduler();
    
                var ifExecute =
                    scheduler.GetCurrentlyExecutingJobs()
                        .Select(z => z.JobDetail)
                        .Where(z => z.Key.Name == name && z.Key.Group == group)
                        .ToList()
                        .Count > 0;
    
                if (ifExecute) return false;
    
                var result = scheduler.DeleteJob(new JobKey(name, group));
    
                return result;
            }
    
    
            #region trigger
    
            /// <summary>
            /// 添加Trigger
            /// </summary>
            /// <param name="triggerInfo"></param>
            /// <returns></returns>
            public bool AddNewTriggerWithJobDetail(TriggerModel triggerInfo)
            {
                var scheduler = CreateScheduler();
    
                var trigger = scheduler.GetTrigger(new TriggerKey(triggerInfo.name, triggerInfo.group));
                if (trigger != null) return false;
    
                var job = scheduler.GetJobDetail(new JobKey(triggerInfo.jobDetailName, triggerInfo.jobDetailGroup));
                if (job == null) return false;
    
                trigger = QuartzConvert.TriggerInfoToCronTrigger(triggerInfo);
                if (trigger == null) return false;
    
                var abstractTrigger = trigger as AbstractTrigger;
                if (abstractTrigger == null) return false;
    
                abstractTrigger.JobKey = job.Key;
                scheduler.ScheduleJob(abstractTrigger);
                abstractTrigger.StartTimeUtc = abstractTrigger.StartTimeUtc.AddSeconds(1);
                scheduler.PauseTrigger(abstractTrigger.Key);
    
                return true;
            }
    
            public bool DeleteTrigger(string name, string group)
            {
                var scheduler = CreateScheduler();
    
                var ifExecute =
                    scheduler.GetCurrentlyExecutingJobs()
                        .Select(z => z.Trigger)
                        .Where(z => z.Key.Name == name && z.Key.Group == group)
                        .ToList()
                        .Count > 0;
    
                if (ifExecute) return false;
    
                var result = scheduler.UnscheduleJob(new TriggerKey(name, group));
    
                return result;
            }
    
            public void PauseTrigger(TriggerOperateModel operate)
            {
                var scheduler = CreateScheduler();
                if (scheduler == null) scheduler = CreateScheduler();
                if (operate.operateType != 0 && operate.operateType != 1) return;
                scheduler.PauseTrigger(new TriggerKey(operate.name, operate.group));
            }
    
            public void ResumeTrigger(TriggerOperateModel operate)
            {
                var scheduler = CreateScheduler();
                if (scheduler == null) scheduler = CreateScheduler();
                if (operate.operateType != 0 && operate.operateType != 1) return;
                scheduler.ResumeTrigger(new TriggerKey(operate.name, operate.group));
            }
    
    
            //<summary>
            //根据JobDetail获取
            //</summary>
            //<param name="jobKey"></param>
            //<returns></returns>
            public List<TriggerModel> GetTriggerInfosByJobDetail(JobKey jobKey)
            {
                var scheduler = CreateScheduler();
                var triggers = scheduler.GetTriggersOfJob(jobKey).ToList();
                var triggerInfos = new List<TriggerModel>();
    
                triggers.ForEach(z =>
                {
                    var trigger = QuartzConvert.CronTriggerImplToTriggerInfo((CronTriggerImpl)z);
                    if (trigger == null) return;
                    trigger.triggerState = (int)scheduler.GetTriggerState(z.Key);
                    triggerInfos.Add(trigger);
                });
    
                return triggerInfos;
            }
    
            #endregion
    
    
            /// <summary>
            /// 获取所有任务
            /// </summary>
            /// <returns></returns>
            public List<JobModel> GetAllJobDetails()
            {
                var result = new List<JobModel>();
                var scheduler = CreateScheduler();
                var groupNameList = scheduler.GetJobGroupNames();
    
                foreach (var groupName in groupNameList)
                {
                    var jobKeyList = scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)).ToList();
                    foreach (var jobKey in jobKeyList)
                    {
                        var jobDetail = scheduler.GetJobDetail(jobKey) as JobDetailImpl;
                        result.Add(QuartzConvert.JobDetailImplToJobInfo(jobDetail, this));
                    }
                }
    
                return result;
            }
    
    
            public List<JobTriggerModel> GetJobTriggerList()
            {
                var result = new List<JobTriggerModel>();
                var scheduler = CreateScheduler();
                var groupNameList = scheduler.GetTriggerGroupNames();
                foreach (var groupName in groupNameList)
                {
                    var triggerKeyList = scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.GroupEquals(groupName));
    
                    foreach (var triggerKey in triggerKeyList)
                    {
                        var triggerDetail = scheduler.GetTrigger(triggerKey) as CronTriggerImpl;
                        var jobTrigger = QuartzConvert.CronTriggerImplToJobTriggerModel(triggerDetail);
                        result.Add(jobTrigger);
                    }
                }
                return result;
            }
    
            /// <summary>
            /// 立即执行一次
            /// </summary>
            /// <param name="jobKey"></param>
            public void ExcuteJobNow(string name, string group)
            {
                var scheduler = CreateScheduler();
                var jobKey = new JobKey(name, group);
                var jobDetail = scheduler.GetJobDetail(jobKey);
                var excuteNowTrigger = TriggerBuilder.Create().WithIdentity("ExcuteNowTrigger", "ExcuteNowGroup").ForJob(jobDetail).StartNow().Build();
                scheduler.ScheduleJob(excuteNowTrigger);
            }
        }
    using Quartz;
    using Quartz.Impl;
    using Quartz.Impl.Triggers;
    using QuartzTimedTaskJobs;
    using QuartzTimedTask.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
     public class QuartzConvert
        {
            private static Type JobType = typeof(FireTimingTaskJob);
    
            /// <summary>
            /// JobInfo转JobDetail
            /// </summary>
            /// <param name="jobInfo"></param>
            /// <returns></returns>
            public static JobDetailImpl JobInfoToJobDetailImpl(JobModel jobInfo)
            {
                var jobDetail = new JobDetailImpl
                {
                    Name = jobInfo.name,
                    Group = jobInfo.group,
                    Key = new JobKey(jobInfo.name, jobInfo.group),
                    Description = jobInfo.description,
                    JobType = JobType,
                    RequestsRecovery = jobInfo.requestsRecovery,
                    Durable = jobInfo.durable
                };
    
                if (jobInfo.jobDataMap != null && jobInfo.jobDataMap.Count > 0)
                {
                    jobInfo.jobDataMap.ForEach(z =>
                    {
                        jobDetail.JobDataMap.Add(z.key, z.value);
                    });
                }
    
                return jobDetail;
            }
    
            /// <summary>
            /// TriggerModel转CronTriggerImpl(只支持CronTriggerImpl)
            /// </summary>
            /// <param name="triggerInfo"></param>
            /// <returns></returns>
            public static CronTriggerImpl TriggerInfoToCronTrigger(TriggerModel triggerInfo)
            {
                var cronTrigger = new CronTriggerImpl
                {
                    Name = triggerInfo.name,
                    Group = triggerInfo.group,
                    CalendarName = triggerInfo.calendarName,
                    Description = triggerInfo.description,
                    CronExpressionString = CronExpression.IsValidExpression(triggerInfo.cronExpression) ? triggerInfo.cronExpression : "",
                };
    
                #region [StartTimeEndTime]-Operate
    
                DateTime startTime, endTime;
                var ifsuccess = DateTime.TryParse(triggerInfo.startTime, out startTime);
                if (!ifsuccess) startTime = DateTime.Now;
                cronTrigger.StartTimeUtc = startTime;
                ifsuccess = DateTime.TryParse(triggerInfo.endTime, out endTime);
                if (ifsuccess) cronTrigger.EndTimeUtc = endTime;
    
                #endregion
    
                return cronTrigger;
            }
    
            public static JobModel JobDetailImplToJobInfo(JobDetailImpl jobDetailImpl, QuartzHelper qh)
            {
                var jobInfo = new JobModel
                {
                    name = jobDetailImpl.Name,
                    group = jobDetailImpl.Group,
                    description = jobDetailImpl.Description,
                    type = jobDetailImpl.JobType.Name,
                    requestsRecovery = jobDetailImpl.RequestsRecovery,
                    durable = jobDetailImpl.Durable,
                    concurrentExecutionDisallowed = jobDetailImpl.ConcurrentExecutionDisallowed,
                    persistJobDataAfterExecution = jobDetailImpl.PersistJobDataAfterExecution,
                    jobDataMap = new List<JobMapModel>(),
                };
    
                //if (jobDetailImpl.JobDataMap != null && jobDetailImpl.JobDataMap.Count > 0)
                //{
                //    jobDetailImpl.JobDataMap.ForEach(z =>
                //    {
                //        jobInfo.jobDataMap.Add(new JobMapModel { key = z.Key, value = z.Value.ToString() });
                //    });
                //}
    
                jobInfo.triggerInfos = qh.GetTriggerInfosByJobDetail(jobDetailImpl.Key);
    
                return jobInfo;
            }
    
            /// <summary>
            /// CronTriggerImpl转TriggerInfo
            /// </summary>
            /// <param name="cronTriggerImpl"></param>
            /// <returns></returns>       
            public static TriggerModel CronTriggerImplToTriggerInfo(CronTriggerImpl cronTriggerImpl)
            {
                var triggerInfo = new TriggerModel
                {
                    name = cronTriggerImpl.Name,
                    group = cronTriggerImpl.Group,
                    calendarName = cronTriggerImpl.CalendarName,
                    description = cronTriggerImpl.Description,
                    startTime = cronTriggerImpl.StartTimeUtc.ToString(),
                    endTime = cronTriggerImpl.EndTimeUtc != null ? ((DateTimeOffset)cronTriggerImpl.EndTimeUtc).ToString() : "",
                    cronExpression = cronTriggerImpl.CronExpressionString,
                    rule = cronTriggerImpl.CronExpressionString,
                    triggerType = "CronTriggerImpl",
                    previousFireTime = cronTriggerImpl.GetPreviousFireTimeUtc() != null ? cronTriggerImpl.GetPreviousFireTimeUtc().ToString() : "",
                    nextFireTime = cronTriggerImpl.GetNextFireTimeUtc() != null ? cronTriggerImpl.GetNextFireTimeUtc().ToString() : ""
                };
    
                return triggerInfo;
            }
    
            private static string FormatDTO(DateTimeOffset? dto)
            {
                return dto.HasValue ? dto.Value.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") : string.Empty;
            }
    
            public static JobTriggerModel CronTriggerImplToJobTriggerModel(CronTriggerImpl cronTriggerImpl)
            {
                var jobTriggerInfo = new JobTriggerModel
                {
                    jobName = cronTriggerImpl.JobName,
                    triggerGroup = cronTriggerImpl.Group,
                    triggerName = cronTriggerImpl.Name,
                    startTime = FormatDTO(cronTriggerImpl.StartTimeUtc),
                    previousFireTime = FormatDTO(cronTriggerImpl.GetPreviousFireTimeUtc()),
                    nextFireTime = FormatDTO(cronTriggerImpl.GetNextFireTimeUtc())
                };
    
                return jobTriggerInfo;
            }
        }

    5.1.3 config文件

    <configuration>
        <configSections>
            <section name="quartz" type="System.Configuration.NameValueSectionHandler" />
        </configSections>
    
     <quartz>
        <add key="quartz.scheduler.instanceName" value="QuartzTimedTaskScheduler" />
        <add key="quartz.scheduler.proxy" value="true" />
        <add key="quartz.threadPool.threadCount" value="5" />
        <add key="quartz.scheduler.proxy.address" value="tcp://127.0.0.1:556/QuartzTimedTaskScheduler" />
      </quartz>

    5.2 WindowsServices 服务

     using Quartz;
     
     public class FireTimingTaskJob : IJob
        {
            public string TaskName { get; set; }
    
            #region IJob Members
    
            public void Execute(IJobExecutionContext context)
            {
     
                try
                {
                    var content = string.Format("{0:yyyy-MM-dd HH:mm:ss.fff} Task:{1},Run Trigger:{2}", DateTime.Now, TaskName, context.Trigger.SerializeObject());
                    Console.WriteLine(content);
                }
                catch
                {
                    try
                    {
                        System.Threading.Thread.Sleep(1000);
                       
                    }
                    catch (Exception ex)
                    {
                        //log.ErrorFormat("Fire task-{0} by trigger-{1} failed. Exception:{2}", TaskName, context.Trigger.Key, ex);
                        var content = string.Format("{0:yyyy-MM-dd HH:mm:ss.fff} Task:{1},Run Exception:{2}", DateTime.Now, TaskName, ex);
                        Console.WriteLine(content);
                    }
                }
            }
    
            #endregion
        }
    using Quartz;
    using Quartz.Impl;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    //using QuartzTimedTaskJobs;必须要引用项目文件
    
    namespace QuartzTimedTaskService
    {
        public class QuartzHost
        {
            IScheduler sched;
            public void Start()
            {
                try
                {
                    ISchedulerFactory sf = new StdSchedulerFactory();
    
                    sched = sf.GetScheduler();
                    sched.Start();
                }
                catch (Exception ex)
                {
    
                    if (ex.InnerException != null)
                    {
                        Console.WriteLine(ex.Message);
                        if (ex.InnerException.InnerException != null)
                        {
                            if (ex.InnerException.InnerException.InnerException != null)
                            {
                                Console.WriteLine(ex.InnerException.InnerException.InnerException.Message);
                            }
                            Console.WriteLine(ex.InnerException.InnerException.Message);
                        }
                        Console.WriteLine(ex.InnerException.Message);
                    }
                    Console.WriteLine(ex.Message);
                }
    
            }
    
            public void Stop()
            {
                if (sched != null)
                {
                    sched.Shutdown(true);
                    sched = null;
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Topshelf;
    using Topshelf.Extension;
    
    namespace QuartzTimedTaskService
    {
        class Program
        {
            static void Main(string[] args)
            {
                HostFactory.Run(x =>
                {
                    x.Service<QuartzHost>(s =>
                    {
                        s.ConstructUsing(name => new QuartzHost());
                        s.WhenStarted(h => h.Start());
                        s.WhenStopped(h => h.Stop());
                    });
    
                    x.SetDescription("Smt Quartz Timed Task Service.");
                    x.SetDisplayName("Smt Quartz Timed Task Service");
                    x.SetServiceName("SmtQuartzTimedTaskService");
                    x.SetStartTimeout(TimeSpan.FromMinutes(2));
                    x.SetStopTimeout(TimeSpan.FromMinutes(2));
    
                    x.RunAsLocalSystem()
                     .StartAutomatically()
                     .EnableServiceRecovery(r =>
                     {
                         r.RestartService(1)
                          .RestartService(1)
                          .RestartService(1)
                          .SetResetPeriod(1);
                     })
                      .UseHostBuilder((environment, setting) => new CustomConsoleHostBuilder(environment, setting)); ;
                });
            }
        }
    }
      <quartz>
        <add key="quartz.scheduler.instanceName" value="QuartzTimedTaskScheduler" />
        <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
        <add key="quartz.threadPool.threadCount" value="10" />
        <add key="quartz.threadPool.threadPriority" value="Normal" />
        <add key="quartz.jobStore.misfireThreshold" value="60000" />
        <add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
    
        <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
        <add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz" />
        <add key="quartz.jobStore.dataSource" value="QuartzTimedTask" />
        <add key="quartz.dataSource.QuartzTimedTask.connectionString" value="Server=192.168.1.100;Database=my_QuartzTimedTask;User=sa;Password=123456;Charset=utf8;Pooling=false;" />
        <add key="quartz.dataSource.QuartzTimedTask.provider" value="MySql-695" />
    
        <!--远程输出配置-->
        <add key="quartz.scheduler.exporter.type" value="Quartz.Simpl.RemotingSchedulerExporter, Quartz" />
        <add key="quartz.scheduler.exporter.port" value="556" />
        <add key="quartz.scheduler.exporter.bindName" value="QuartzTimedTaskScheduler" />
        <add key="quartz.scheduler.exporter.channelType" value="tcp" />
        <add key="quartz.scheduler.exporter.channelName" value="tcpQuartz" />
        <add key="quartz.scheduler.exporter.rejectRemoteRequests" value="false" />
    
      </quartz>
  • 相关阅读:
    关于HashMap的线程安全问题
    Java利器之UML类图详解
    mongoDB4.0数据库
    requests-html库render的使用
    爬虫最新的库requests-html库总结
    爬虫多次爬取时候cookie的存储用于登入
    requests模块响应体属性和方法重新整理
    Visual Studio 代码补全功能有时候会失效的原因
    C++Primer笔记——文本查询程序(原创,未使用类)
    Clion 常用快捷键
  • 原文地址:https://www.cnblogs.com/FH-cnblogs/p/9645474.html
Copyright © 2011-2022 走看看