敞开成长之旅!这是我参与「日新方案 12 月更文挑战」的第30天,点击检查活动详情
1、什么是Quartz
quartz是一个功用丰厚的开源的使命调用体系,它能够界说很多job并发履行,支撑业务和集群
2、能够做什么
界说使命,在任何时刻,或许某一时刻能够做想履行的使命
3、Quartz 三要素:
- Scheduler:使命调度器,一切的使命都是从这儿开端。
- Trigger:触发器,定期履行使命,一般有cron表达式
- JobDetail 使命详细
- Job : 界说使命详细履行的逻辑,终究履行的逻辑
job 完成 QuartzJobBean ,abstractQuartzJob,使命履行的地方
Scheduler
留意:scheduler是一个接口类,一切的详细完成类都是经过SchedulerFactory工厂类完成,因此是需要装备调度工厂的,由他来调度使命
自界说SchedulerFactory(简略运用Quartz不需要自界说这个(留意)
)
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
{
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池装备
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
// JobStore装备
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// 集群装备
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
// sqlserver 启用
// prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
factory.setQuartzProperties(prop);
factory.setSchedulerName("RuoyiScheduler");
// 延时发动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选,QuartzScheduler
// 发动时更新己存在的Job,这样就不必每次修改targetObject后删去qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
// 设置主动发动,默以为true
factory.setAutoStartup(true);
return factory;
}
Trigger和JobDetail
常用办法
-
withIdentity() 给触发器一些属性 比如姓名,组名。
-
storeDurably() 耐久化存储
-
withSchedule(ScheduleBuilder schedBuilder) 以某种触发器触发。
简略示例
JobDetail jobDetail = JobBuilder.newJob(QuartzJobBean.class)
.withIdentity("name1", "group1")
.storeDurably(true)
.build();
ScheduleBuilder(运用cronScheduler)
CronScheduleBuilder cronScheduleBuilder =
CronScheduleBuilder.cronSchedule(("0 0/5 * * * ?"));
@Bean
public Trigger storeUserLikeAndCountTrigger(){
CronTrigger cronTrigger = TriggerBuilder.newTrigger().forJob(storeUserLikeAndCountJobDetail())
.withIdentity("trigger1", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule(("0 0/5 * * * ?")))
.startNow() //当即发动
.build();
return cronTrigger;
}
4、cron表达式写法
CornTrigger表达式的写法 * * * * * * 分别代表秒、分、时、日、月、周几
比如: 0 0 12 ? * 3 每周二中午 12 点履行使命 0 0 0 0 * ? 每月 1 日 0 点履行使命
字段 答应值 答应的特别字符
秒 0-59 , – * / 分 0-59 , – * / 小时 0-23 , – * / 日期 1-31 , – * ? / L W C 月份 1-12 或许 JAN-DEC , – * / 星期 1-7 或许 SUN-SAT , – * ? / L C # 年(可选) 留空, 1970-2099 , – * / 表达式 含义 “0 0 12 * * ?” 每天中午12点触发 “0 15 10 ? * *” 每天上午10:15触发 “0 15 10 * * ?” 每天上午10:15触发 “0 15 10 * * ? *” 每天上午10:15触发 “0 15 10 * * ? 2005” 2005年的每天上午10:15触发 “0 * 14 * * ?” 在每天下午2点到下午2:59期间的每1分钟触发 “0 0/5 14 * * ?” 在每天下午2点到下午2:55期间的每5分钟触发 “0 0/5 14,18 * * ?” 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 “0 0-5 14 * * ?” 在每天下午2点到下午2:05期间的每1分钟触发 “0 10,44 14 ? 3 WED” 每年三月的星期三的下午2:10和2:44触发 “0 15 10 ? * MON-FRI” 周一至周五的上午10:15触发 “0 15 10 15 * ?” 每月15日上午10:15触发 “0 15 10 L * ?” 每月最终一日的上午10:15触发 “0 15 10 ? * 6L” 每月的最终一个星期五上午10:15触发 “0 15 10 ? * 6L 2002-2005” 2002年至2005年的每月的最终一个星期五上午10:15触发 “0 15 10 ? * 6#3” 每月的第三个星期五上午10:15触发
特别字符 含义 * 表明一切值; ? 表明未说明的值,即不关心它为何值; – 表明一个指定的规模; , 表明附加一个或许值; / 符号前表明开端时刻,符号后表明每次递增的值;
L(“last”) (“last”) “L” 用在day-of-month字段意思是 “这个月最终一天”;用在 day-of-week字段, 它简略意思是 “7” or “SAT”。 假设在day-of-week字段里和数字联合运用,它的意思便是 “这个月的最终一个星期几” – 例如: “6L” means “这个月的最终一个星期五”. 当咱们用“L”时,不指明一个列表值或许规模是很重要的,否则的话,咱们会得到一些意想不到的结果。
W(“weekday”) 只能用在day-of-month字段。用来描叙最接近指定天的作业日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的作业日”,即假设这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;假设这个月第15天是周日,那么触发器将会在这个月第16天即周一触发;假设这个月第15天是周二,那么就在触发器这天触发。
留意一点:这个用法只会在当前月核算值,不会跳过当前月。“W”字符仅能在day-of-month指明一天,不能是一个规模或列表。也能够用“LW”来指定这个月的最终一个作业日。
只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用”6#3”指这个月第3个周五(6指周五,3指第3个)。假设指定的日期不存在,触发器就不会触发。
C 指和calendar联系后核算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天
测试实例
1、导入依靠
<!-- 守时使命 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>xxxx</version>
<exclusions>
<exclusion>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
</exclusions>
</dependency>
版别依据springboot版别定,详细官网
2、导入Quartz数据库表
-- ----------------------------
-- 1、存储每一个已装备的 jobDetail 的详细信息
-- ----------------------------
drop table if exists QRTZ_JOB_DETAILS;
create table QRTZ_JOB_DETAILS (
sched_name varchar(120) not null,
job_name varchar(200) not null,
job_group varchar(200) not null,
description varchar(250) null,
job_class_name varchar(250) not null,
is_durable varchar(1) not null,
is_nonconcurrent varchar(1) not null,
is_update_data varchar(1) not null,
requests_recovery varchar(1) not null,
job_data blob null,
primary key (sched_name,job_name,job_group)
) engine=innodb;
-- ----------------------------
-- 2、 存储已装备的 Trigger 的信息
-- ----------------------------
drop table if exists QRTZ_TRIGGERS;
create table QRTZ_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
job_name varchar(200) not null,
job_group varchar(200) not null,
description varchar(250) null,
next_fire_time bigint(13) null,
prev_fire_time bigint(13) null,
priority integer null,
trigger_state varchar(16) not null,
trigger_type varchar(8) not null,
start_time bigint(13) not null,
end_time bigint(13) null,
calendar_name varchar(200) null,
misfire_instr smallint(2) null,
job_data blob null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group)
) engine=innodb;
-- ----------------------------
-- 3、 存储简略的 Trigger,包括重复次数,距离,以及已触发的次数
-- ----------------------------
drop table if exists QRTZ_SIMPLE_TRIGGERS;
create table QRTZ_SIMPLE_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
repeat_count bigint(7) not null,
repeat_interval bigint(12) not null,
times_triggered bigint(10) not null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb;
-- ----------------------------
-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息
-- ----------------------------
drop table if exists QRTZ_CRON_TRIGGERS;
create table QRTZ_CRON_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
cron_expression varchar(200) not null,
time_zone_id varchar(80),
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb;
-- ----------------------------
-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创立他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时分)
-- ----------------------------
drop table if exists QRTZ_BLOB_TRIGGERS;
create table QRTZ_BLOB_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
blob_data blob null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb;
-- ----------------------------
-- 6、 以 Blob 类型存储寄存日历信息, quartz可装备一个日历来指定一个时刻规模
-- ----------------------------
drop table if exists QRTZ_CALENDARS;
create table QRTZ_CALENDARS (
sched_name varchar(120) not null,
calendar_name varchar(200) not null,
calendar blob not null,
primary key (sched_name,calendar_name)
) engine=innodb;
-- ----------------------------
-- 7、 存储已暂停的 Trigger 组的信息
-- ----------------------------
drop table if exists QRTZ_PAUSED_TRIGGER_GRPS;
create table QRTZ_PAUSED_TRIGGER_GRPS (
sched_name varchar(120) not null,
trigger_group varchar(200) not null,
primary key (sched_name,trigger_group)
) engine=innodb;
-- ----------------------------
-- 8、 存储与已触发的 Trigger 相关的状况信息,以及相联 Job 的履行信息
-- ----------------------------
drop table if exists QRTZ_FIRED_TRIGGERS;
create table QRTZ_FIRED_TRIGGERS (
sched_name varchar(120) not null,
entry_id varchar(95) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
instance_name varchar(200) not null,
fired_time bigint(13) not null,
sched_time bigint(13) not null,
priority integer not null,
state varchar(16) not null,
job_name varchar(200) null,
job_group varchar(200) null,
is_nonconcurrent varchar(1) null,
requests_recovery varchar(1) null,
primary key (sched_name,entry_id)
) engine=innodb;
-- ----------------------------
-- 9、 存储少数的有关 Scheduler 的状况信息,假设是用于集群中,能够看到其他的 Scheduler 实例
-- ----------------------------
drop table if exists QRTZ_SCHEDULER_STATE;
create table QRTZ_SCHEDULER_STATE (
sched_name varchar(120) not null,
instance_name varchar(200) not null,
last_checkin_time bigint(13) not null,
checkin_interval bigint(13) not null,
primary key (sched_name,instance_name)
) engine=innodb;
-- ----------------------------
-- 10、 存储程序的悲观锁的信息(假设运用了悲观锁)
-- ----------------------------
drop table if exists QRTZ_LOCKS;
create table QRTZ_LOCKS (
sched_name varchar(120) not null,
lock_name varchar(40) not null,
primary key (sched_name,lock_name)
) engine=innodb;
drop table if exists QRTZ_SIMPROP_TRIGGERS;
create table QRTZ_SIMPROP_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
str_prop_1 varchar(512) null,
str_prop_2 varchar(512) null,
str_prop_3 varchar(512) null,
int_prop_1 int null,
int_prop_2 int null,
long_prop_1 bigint null,
long_prop_2 bigint null,
dec_prop_1 numeric(13,4) null,
dec_prop_2 numeric(13,4) null,
bool_prop_1 varchar(1) null,
bool_prop_2 varchar(1) null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb;
commit;
3、 自界说调度器工厂
@Configuration
public class ScheduleConfig
{
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
{
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池装备
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
// JobStore装备
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// 集群装备
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
// sqlserver 启用
// prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
factory.setQuartzProperties(prop);
factory.setSchedulerName("RuoyiScheduler");
// 延时发动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选,QuartzScheduler
// 发动时更新己存在的Job,这样就不必每次修改targetObject后删去qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
// 设置主动发动,默以为true
factory.setAutoStartup(true);
return factory;
}
}
4、界说SysJob,存储创立的使命 便于反射调用办法
public class SysJob implements Serializable
{
private static final long serialVersionUID = 1L;
/** 使命ID */
private Long jobId;
/** 使命称号 */
private String jobName;
/** 使命组名 */
private String jobGroup;
/** 调用方针字符串 */
private String invokeTarget;
/** cron履行表达式 */
private String cronExpression;
/** cron方案战略 */
private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
/** 是否并发履行(0答应 1禁止) */
private String concurrent;
/** 使命状况(0正常 1暂停) */
private String status;
public Long getJobId()
{
return jobId;
}
public void setJobId(Long jobId)
{
this.jobId = jobId;
}
@NotBlank(message = "使命称号不能为空")
@Size(min = 0, max = 64, message = "使命称号不能超过64个字符")
public String getJobName()
{
return jobName;
}
public void setJobName(String jobName)
{
this.jobName = jobName;
}
public String getJobGroup()
{
return jobGroup;
}
public void setJobGroup(String jobGroup)
{
this.jobGroup = jobGroup;
}
@NotBlank(message = "调用方针字符串不能为空")
@Size(min = 0, max = 500, message = "调用方针字符串长度不能超过500个字符")
public String getInvokeTarget()
{
return invokeTarget;
}
public void setInvokeTarget(String invokeTarget)
{
this.invokeTarget = invokeTarget;
}
@NotBlank(message = "Cron履行表达式不能为空")
@Size(min = 0, max = 255, message = "Cron履行表达式不能超过255个字符")
public String getCronExpression()
{
return cronExpression;
}
public void setCronExpression(String cronExpression)
{
this.cronExpression = cronExpression;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getNextValidTime()
{
if (StringUtils.isNotEmpty(cronExpression))
{
return CronUtils.getNextExecution(cronExpression);
}
return null;
}
public String getMisfirePolicy()
{
return misfirePolicy;
}
public void setMisfirePolicy(String misfirePolicy)
{
this.misfirePolicy = misfirePolicy;
}
public String getConcurrent()
{
return concurrent;
}
public void setConcurrent(String concurrent)
{
this.concurrent = concurrent;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("jobId", getJobId())
.append("jobName", getJobName())
.append("jobGroup", getJobGroup())
.append("cronExpression", getCronExpression())
.append("nextValidTime", getNextValidTime())
.append("misfirePolicy", getMisfirePolicy())
.append("concurrent", getConcurrent())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}
4、界说详细使命job
4.1、笼统使命,使命履行日志
/**
* 笼统quartz调用
*
*/
public abstract class AbstractQuartzJob implements Job
{
private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
/**
* 线程本地变量
*/
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
// 当使命被触发,那么走这儿
@Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
// 存储使命信息的方针
SysJob sysJob = new SysJob();
// 将调度使命的JobDataMap中的属性,放入sysJob
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
try
{
// 履行使命之前
before(context, sysJob);
if (sysJob != null)
{
// 履行真正的使命(笼统办法,由子类完成)
doExecute(context, sysJob);
}
// 使命履行完后,使命履行记录
after(context, sysJob, null);
}
catch (Exception e)
{
log.error("使命履行反常 - :", e);
after(context, sysJob, e);
}
}
/**
* 履行前
*
* @param context 作业履行上下文方针
* @param sysJob 体系方案使命
*/
protected void before(JobExecutionContext context, SysJob sysJob)
{
threadLocal.set(new Date());
}
/**
* 履行后
*
* @param context 作业履行上下文方针
* @param sysJob 体系方案使命
*/
protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
{
Date startTime = threadLocal.get();
threadLocal.remove();
final SysJobLog sysJobLog = new SysJobLog();
xxxxxx使命信息
// 写入数据库当中
SpringUtils.getBean(XXX.class).addJobLog(sysJobLog);
}
/**
* 履行办法,由子类重载
*
* @param context 作业履行上下文方针
* @param sysJob 体系方案使命
* @throws Exception 履行过程中的反常
*/
protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
}
4.2 界说子类
履行使命子类
public class QuartzJobExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
{
// 反射履行使命
jobInvokeUtil.invokeMethod(sysJob);
}
}
并发履行使命子类
public class ConcurrentQuartzJobExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
{
// 反射履行使命
jobInvokeUtil.invokeMethod(sysJob);
}
}
4.3 反射东西类
/**
* 使命履行东西
*/
public class JobInvokeUtil {
/**
* 履行方针办法
*
* @param sysJob 体系使命
*/
public static void invokeMethod(SysJob sysJob) throws Exception {
// 获取调度方针 rg:myTask.noParamsMethod 前面为bean 的姓名,后面为办法名
String invokeTarget = sysJob.getInvokeTarget();
// 获取调度方针 bean称号
String beanName = getBeanName(invokeTarget);
// 获取调度方针 办法名
String methodName = getMethodName(invokeTarget);
// 获取调度方针 参数
List<Object[]> methodParams = getMethodParams(invokeTarget);
// beanName 不包括"." 即为正确beanName
if (!isValidClassName(beanName)) {
// 从容器中获取bean实例
Object bean = SpringUtils.getBean(beanName);
invokeMethod(bean, methodName, methodParams);
} else {
// 经过反射创立bean实例 此刻beanName的写法: com.xiaoxu.domain.Task
Object bean = Class.forName(beanName).newInstance();
invokeMethod(bean, methodName, methodParams);
}
}
/**
* 调用使命办法
*
* @param bean 方针方针
* @param methodName 办法称号
* @param methodParams 办法参数
*/
private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) {
// 有参 经过method反射 调用
Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
method.invoke(bean, getMethodParamsValue(methodParams));
} else {
// 无参 经过method反射 调用
Method method = bean.getClass().getDeclaredMethod(methodName);
method.invoke(bean);
}
}
/**
* 校验是否为为class包名
*
* @param invokeTarget 称号
* @return true是 false否
*/
public static boolean isValidClassName(String invokeTarget) {
return StringUtils.countMatches(invokeTarget, ".") > 1;
}
/**
* 获取bean称号
*
* @param invokeTarget 方针字符串
* @return bean称号
*/
public static String getBeanName(String invokeTarget) {
// 取 target 在"("前 的子字符串
String beanName = StringUtils.substringBefore(invokeTarget, "(");
return StringUtils.substringBeforeLast(beanName, ".");
}
/**
* 获取bean办法
*
* @param invokeTarget 方针字符串
* @return method办法
*/
public static String getMethodName(String invokeTarget) {
String methodName = StringUtils.substringBefore(invokeTarget, "(");
return StringUtils.substringAfterLast(methodName, ".");
}
/**
* 获取method办法参数相关列表
*
* @param invokeTarget 方针字符串
* @return method办法相关参数列表
*/
public static List<Object[]> getMethodParams(String invokeTarget) {
String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
if (StringUtils.isEmpty(methodStr)) {
return null;
}
String[] methodParams = methodStr.split(",");
List<Object[]> classs = new LinkedList<>();
for (int i = 0; i < methodParams.length; i++) {
String str = StringUtils.trimToEmpty(methodParams[i]);
// String字符串类型,包括'
if (StringUtils.contains(str, "'")) {
classs.add(new Object[]{StringUtils.replace(str, "'", ""), String.class});
}
// boolean布尔类型,等于true或许false
else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) {
classs.add(new Object[]{Boolean.valueOf(str), Boolean.class});
}
// long长整形,包括L
else if (StringUtils.containsIgnoreCase(str, "L")) {
classs.add(new Object[]{Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class});
}
// double浮点类型,包括D
else if (StringUtils.containsIgnoreCase(str, "D")) {
classs.add(new Object[]{Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class});
}
// 其他类型归类为整形
else {
classs.add(new Object[]{Integer.valueOf(str), Integer.class});
}
}
return classs;
}
/**
* 获取参数类型
*
* @param methodParams 参数相关列表
* @return 参数类型列表
*/
public static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
Class<?>[] classs = new Class<?>[methodParams.size()];
int index = 0;
for (Object[] os : methodParams) {
classs[index] = (Class<?>) os[1];
index++;
}
return classs;
}
/**
* 获取参数值
*
* @param methodParams 参数相关列表
* @return 参数值列表
*/
public static Object[] getMethodParamsValue(List<Object[]> methodParams) {
Object[] classs = new Object[methodParams.size()];
int index = 0;
for (Object[] os : methodParams) {
classs[index] = (Object) os[0];
index++;
}
return classs;
}
}
5、创立使命放入Scheduler调度器中,并发动使命
SchedulerUtils 调度器东西类
/**
* 守时使命东西类
*/
public class ScheduleUtils {
/**
* 得到quartz使命类
*
* @param sysJob 履行方案
* @return 详细履行使命类
*/
private static Class<? extends Job> getQuartzJobClass(SysJob sysJob) {
// 默认值0 答应并发履行
boolean isConcurrent = "0".equals(sysJob.getConcurrent());
return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
}
/**
* 构建使命触发方针
*/
public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
}
/**
* 构建使命键方针
*/
public static JobKey getJobKey(Long jobId, String jobGroup) {
return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
}
/**
* 创立守时使命
*/
public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException {
// 获取job class字节码(quartz使命类) 到底是并发仍是不并发
Class<? extends Job> jobClass = getQuartzJobClass(job);
// 构建job信息
Long jobId = job.getJobId();
String jobGroup = job.getJobGroup();
// 经过jobBuilder 创立jobDetail(寄存job相关信息), 指定job类型(怎样履行job),指定jobKey
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();
// 表达式调度构建器 设置守时使命失败的战略 1:当即履行,2 履行一次,3 放弃履行
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
// 按新的cronExpression表达式构建一个新的trigger 指定triggerKey withSchedule:触发器时刻设定
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
.withSchedule(cronScheduleBuilder).build();
// 放入参数,运行时的办法能够获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
// 判断是否存在
if (scheduler.checkExists(getJobKey(jobId, jobGroup))) {
// 避免创立时存在数据问题 先移除,然后在履行创立操作
scheduler.deleteJob(getJobKey(jobId, jobGroup));
}
// 调度容器设置JobDetail 和 Trigger
scheduler.scheduleJob(jobDetail, trigger);
// 暂停使命 经过jobKey
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) {
scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
}
}
/**
* 设置守时使命战略
*/
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
throws TaskException {
switch (job.getMisfirePolicy()) {
case ScheduleConstants.MISFIRE_DEFAULT:
return cb;
case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
return cb.withMisfireHandlingInstructionIgnoreMisfires();
case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
return cb.withMisfireHandlingInstructionFireAndProceed();
case ScheduleConstants.MISFIRE_DO_NOTHING:
return cb.withMisfireHandlingInstructionDoNothing();
default:
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
+ "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
}
}
}
大致履行流程