jfinal定时调度任务插件QuartzPlugin

jfinal与quartz结合。

即可以在配置文件中配置定时任务。又可动态添加新的定时任务。

使用中的项目:

http://www.3dmomoda.com

依赖jar包:quartz-2.0.2.jar

其他的依赖自己稍微改下就可以


quartz_config.properties(quartz配置)

#============================================================================
# 配置主要调度程序属性
#============================================================================
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================
# 配置线程池  
#============================================================================
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5

#============================================================================
# 配置任务 
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000

org.quartz.scheduler.skipUpdateCheck = true

quartz_job.properties(任务配置,默认的调度任务可以在这里添加)

#开启的任务列表“,”隔开
jobArray = task1,task2

#搭客任务定时结束
task1.job=com.momoda.quartz.Task1
task1.cron=00 00 23 * * ?
task1.desc=任务1

#归档登录日志
task2.job=com.momoda.quartz.Task2
task2.cron=00 00 04 * * ?
task2.desc=任务2

FormaterCronExpression.java(日期转cron定时表达式类)

public class FormaterCronExpression {
	static String formart = "yyyy-MM-dd HH:mm:ss";

	public static String formaterCronExpression(String date) {
		SimpleDateFormat format = new SimpleDateFormat(formart.substring(0, date.length() - 1));
		SimpleDateFormat format2 = new SimpleDateFormat("yyyy MM dd HH mm ss");
		try {
			Date d = format.parse(date);
			date = format2.format(d);
			String[] dateArry = date.split(" ");
			String exp = dateArry[5] + " " + dateArry[4] + " " + dateArry[3] + " " + dateArry[2] + " " + dateArry[1]
					+ " ? " + dateArry[0];
			return exp;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}

}

JobBean.java(任务对象实体bean)

/**
 * 计划任务信息
 */
public class JobBean {

	/** 任务id */
	private String jobId;

	/** 任务描述 */
	private String jobDesc;

	/** 任务运行时间表达式 */
	private String cronExpression;

	/** 任务分组 */
	private String jobGroup;

	/** 任务类 */
	private String jobClass;

	public String getJobId() {
		return jobId;
	}

	public void setJobId(String jobId) {
		this.jobId = jobId;
	}

	public String getJobDesc() {
		return jobDesc;
	}

	public void setJobDesc(String jobDesc) {
		this.jobDesc = jobDesc;
	}

	public String getCronExpression() {
		return cronExpression;
	}

	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}

	public String getJobGroup() {
		return jobGroup;
	}

	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}

	public String getJobClass() {
		return jobClass;
	}

	public void setJobClass(String jobClass) {
		this.jobClass = jobClass;
	}

	public JobBean(String jobId, String jobDesc, String cronExpression, String jobGroup, String jobClass) {
		this.jobId = jobId;
		this.jobDesc = jobDesc;
		this.cronExpression = cronExpression;
		this.jobGroup = jobGroup;
		this.jobClass = jobClass;
	}

	public JobBean() {
		super();
	}
}

QuartzPlugin.java(插件类)

public class QuartzPlugin implements IPlugin {
	private List<JobBean> jobs = new ArrayList<JobBean>();
	private SchedulerFactory sf;
	private static Scheduler scheduler;
	private String jobConfig;
	private String confConfig;
	private Map<String, String> jobProp;

	public QuartzPlugin(String jobConfig, String confConfig) {
		this.jobConfig = jobConfig;
		this.confConfig = confConfig;
	}

	public QuartzPlugin(String jobConfig) {
		this.jobConfig = jobConfig;
		this.confConfig = "/quartz_config.properties";
	}

	public QuartzPlugin() {
		this.jobConfig = "/quartz_job.properties";
		this.confConfig = "/quartz_config.properties";
	}

	public static void addJob(JobBean job) {
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobDesc(), job.getJobGroup());
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			// 不存在,创建一个
			if (null == trigger) {
				Class<Job> j2 = (Class<Job>) Class.forName(job.getJobClass());
				JobDetail jobDetail = JobBuilder.newJob(j2).withIdentity(job.getJobDesc(), job.getJobGroup()).build();
				jobDetail.getJobDataMap().put("scheduleJob", job);

				// 表达式调度构建器
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

				// 按新的cronExpression表达式构建一个新的trigger
				trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobDesc(), job.getJobGroup())
						.withSchedule(scheduleBuilder).build();
				try {
					scheduler.scheduleJob(jobDetail, trigger);
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				// Trigger已存在,那么更新相应的定时设置
				// 表达式调度构建器
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

				// 按新的cronExpression表达式重新构建trigger
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

				// 按新的trigger重新设置job执行
				scheduler.rescheduleJob(triggerKey, trigger);
			}
		} catch (Exception e) {
		}
	}

	@Override
	public boolean start() {
		loadJobsFromProperties();
		startJobs();
		return true;
	}

	private void startJobs() {
		try {
			if (StrKit.notBlank(confConfig)) {
				sf = new StdSchedulerFactory(confConfig);
			} else {
				sf = new StdSchedulerFactory();
			}
			scheduler = sf.getScheduler();
		} catch (SchedulerException e) {
			Throwables.propagate(e);
		}
		for (JobBean entry : jobs) {
			addJob(entry);
		}
		try {
			scheduler.start();
		} catch (SchedulerException e) {
			Throwables.propagate(e);
		}
	}

	private void loadJobsFromProperties() {
		if (StrKit.isBlank(jobConfig)) {
			return;
		}
		jobProp = ResourceKit.readProperties(jobConfig);
		String jobArray = jobProp.get("jobArray");
		if (StrKit.isBlank(jobArray)) {
			return;
		}
		String[] jobArrayList = jobArray.split(",");
		for (String jobName : jobArrayList) {
			jobs.add(createJobBean(jobName));
		}
	}

	private JobBean createJobBean(String key) {
		JobBean job = new JobBean();
		job.setJobClass(jobProp.get(key + ".job"));
		job.setCronExpression(jobProp.get(key + ".cron"));
		job.setJobGroup(jobProp.get(key));
		job.setJobDesc(jobProp.get(key + ".desc"));
		return job;
	}

	@Override
	public boolean stop() {
		try {
			scheduler.shutdown();
		} catch (SchedulerException e) {
			Throwables.propagate(e);
		}
		return true;
	}
}


configPlugin方法中将插件启动就可以


动态添加定时任务

JobBean job = new JobBean();
job.setJobClass("com.momoda.quartz.DakeTaskJob");
job.setCronExpression(FormaterCronExpression.formaterCronExpression(task.getStr("closingTime")));
job.setJobGroup("DakeTaskJob");
job.setJobDesc("DakeTaskJob_" + taskid);
QuartzPlugin.addJob(job);


评论区

JFinal

2016-06-23 22:10

感谢分享,这个确实有很多人找我要的功能,非常实用 ^_^

fangjunai

2016-06-24 08:51

请问 cron4j 调度 可以按秒执行吗?

埋头苦干

2016-06-24 10:29

@fangjunai 可以,每秒,每隔5秒,每分钟,每隔5分钟,都是可以的,自己查下cron表达式

fangjunai

2016-06-24 11:30

@埋头苦干 表达式我查过.但多是基于QuartZ的, 如: 0/1 * * * * 在cron4j 就不能按秒执行.

fangjunai

2016-06-24 11:30

@埋头苦干 表达式我查过.但多是基于QuartZ的, 如: 0/1 * * * * 在cron4j 就不能按秒执行.

埋头苦干

2016-06-28 11:46

@fangjunai 不好意思,没注意你说的是cron4j ,这个具体没有测试。

lcg0211

2016-06-30 16:42

@埋头苦干 请问默认调度任务和动态添加任务的区别与实际应用,具体是用在哪些任务?

埋头苦干

2016-07-01 09:53

@lcg0211 默认调度任务就好比每天晚上都要执行一次数据统计之类的,动态添加任务呢就是好比是我有一个定时提醒的模块,这个定时提醒可以自己设定时间。

eagle

2016-07-12 11:52

Throwables在哪个包,ResourceKit在哪个包

埋头苦干

2016-07-12 15:35

@eagle
只依赖jar包:quartz-2.0.2.jar

其他的依赖自己稍微改下就可以

yotop

2016-07-13 08:42

@JFinal 前段时间刚做了定时服务,期待波总可以把定时服务加到后续的2.3版本中,毕竟大家都很懒,O(∩_∩)O哈哈~

JFinal

2016-07-13 09:23

@yotop jfinal 2.3 版本的定时任务调度已经加完了,我正用着呢,哈哈

tandaly

2016-08-01 20:00

哇,这个我很需要,赞赞赞!

埋头苦干

2016-08-02 15:53

@tandaly 有需要就拿去

wanzhou0310

2016-08-06 21:14

@埋头苦干 我也在找定时任务的功能,谢谢您的提供~

nbjgl

2016-08-28 22:38

收藏了

JFinal

2016-08-28 23:36

@nbjgl 社区会做收藏功能,到时候收藏更方便

thinkive

2016-11-06 10:30

FormaterCronExpression.formaterCronExpression(‘表达式’)里面表达式2016-11-06 10:22:10 这种好像不行

埋头苦干

2016-11-07 11:40

@thinkive 不可能,我一直在这么用呢。看看报什么错。

thinkive

2016-12-06 20:19

我这边启动的时候总是提示这个错误,但是不影响定时器的运行:有谁清楚的吗?
log4j:ERROR Failed to excute sql
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
2016-12-06 20:18:27:848[INFO]: Quartz scheduler 'DefaultQuartzScheduler' initialized from the specified file : 'quartz_config.properties' from the class resource path.

JFinal

2016-12-06 20:30

@thinkive 异常信息已经极其明确, sql 语法错误而已,把 sql 改对即可打完收枪

埋头苦干

2016-12-07 17:06

@thinkive @JFinal 他这个应该是想把quartz配置成持久化到数据库,估计是表不存在,或者字段对不上的原因。可以把quartz_config.properties的配置贴出来看下。

thinkive

2016-12-07 19:43

@埋头苦干 #============================================================================
# 配置主要调度程序属性
#============================================================================
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================
# 配置线程池
#============================================================================
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5

#============================================================================
# 配置任务
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000

org.quartz.scheduler.skipUpdateCheck = true

埋头苦干

2016-12-12 10:18

@thinkive 一样的配置,那看来是我想多了,应该就是你的任务中的哪条sql报错了

localhost8080

2017-03-09 16:48

@eagle 这个你配置好了吗,缺少这个包?