Jfinal实现定时任务调度

时间:2022-11-03 07:59:39

很多时候,我们会遇到让系统自动执行某段代码去执行业务相关逻辑。如生日短信通知,我们需要一个定时任务,获取到生日当天的所有用户,然后执行短信推送等业务逻辑,Jfinal是如何实现定时任务调度呢?

第一步:在Jfinal的过滤器中的configPlugin方法中加入自己实现的jfinal插件接口类配置。

@Override
public void configPlugin(Plugins me){
QuartzPlugin plugin = new QuartzPlugin("job.properties");
me.add(plugin);
//...数据源等其他配置
}

其中QuartzPlugin类的代码如下:
package com.wlkj.common.config;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import com.jfinal.plugin.IPlugin;

public class QuartzPlugin implements IPlugin {

private final Logger logger = Logger.getLogger(QuartzPlugin.class);

private static final String JOB = "job";

private String config = "job.properties";

private Properties properties;

public QuartzPlugin(String config) {
this.config = config;
}
public QuartzPlugin() {
}
private SchedulerFactory schedulerFactory;
private Scheduler scheduler;

@SuppressWarnings("unchecked")
public boolean start() {
try {
loadProperties();
} catch (IOException e) {
logger.error(e.getMessage());
return false;
}
if (properties == null) {
return false;
}
schedulerFactory = new StdSchedulerFactory();
try {
scheduler = schedulerFactory.getScheduler();
} catch (SchedulerException e) {
logger.error(e.getMessage());
return false;
}
if (scheduler == null) {
logger.error("scheduler is null");
return false;
}
Enumeration<Object> enums = properties.keys();
while (enums.hasMoreElements()) {
String key = enums.nextElement() + "";
if (!key.endsWith(JOB) || !isTrue(getJobKey(key, "enable"))) {
continue;
}
String jobClassName = properties.get(key) + "";
String jobName = key.substring(0, key.lastIndexOf("."));
String jobCronExp = properties.getProperty(getJobKey(key, "cron")) + "";
String jobGroup = properties.getProperty(getJobKey(key, "group", "jobGroup1"));
Class<? extends Job> jobClass = null;
try {
jobClass = (Class<? extends Job>) Class.forName(jobClassName);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
return false;
}
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger", jobGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(jobCronExp)).build();
try {
scheduler.scheduleJob(job, trigger);
scheduler.start();
} catch (SchedulerException e) {
logger.error(e.getMessage());
return false;
}
}
return true;
}

public boolean stop() {
try {
scheduler.shutdown();
} catch (SchedulerException e) {
logger.error(e.getMessage());
return false;
}
return true;
}

private void loadProperties() throws IOException {
properties = new Properties();
InputStream is = QuartzPlugin.class.getClassLoader().getResourceAsStream(config);
properties.load(is);
}

private String getJobKey(String str, String type, String defaultValue) {
String key = getJobKey(str, type);
if (key == null || "".equals(key.trim()))
return defaultValue;
return key;

}

private String getJobKey(String str, String type) {
return str.substring(0, str.lastIndexOf(JOB)) + type;
}

private boolean isTrue(String key) {
Object enable = properties.get(key);
if (enable != null && "false".equalsIgnoreCase((enable + "").trim())) {
return false;
}
return true;
}

}
第二步:在classpath类路径下新建job.properties文件。
job.properties文件的内容如下:

birthday.job=com.wlkj.common.config.StatisticExecutor
birthday.cron=0 1 0 ? * *
birthday.enable=true
birthday.group=1

注意:该文件的前缀必须相同,可随意取名,job的值com.wlkj.common.config.StatisticExecutor为执行任务调度的类
代码如下:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class StatisticExecutor implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
//配置好后就会在规定的之间点执行这里的代码了,需要了解job.properties里birthday.cron表达式了
//# s m h d m w(?) y(?) second minute hour date month week year
}
}

还得加入quartz的jar包,和slf4j-api和slf4j-log4j的jar

附:支持多任务调度

public boolean start() {
try {
loadProperties();
} catch (IOException e) {
logger.error(e.getMessage());
return false;
}
if (properties == null) {
return false;
}
Map<String, Object> jobMap = new HashMap<String, Object>();
Enumeration<Object> enums = properties.keys();
while (enums.hasMoreElements()) {
String key = enums.nextElement() + "";
if (!key.endsWith(JOB) || !isTrue(getJobKey(key, "enable"))) {
continue;
}
String jobName = key.substring(0, key.lastIndexOf("."));
if (!jobMap.containsKey(jobName)) {
Map<String, String> jobData = new HashMap<String, String>();
jobData.put("jobClassName", properties.getProperty(jobName + ".job") + "");
jobData.put("jobName", jobName);
jobData.put("jobCronExp", properties.getProperty(jobName + ".cron") + "");
jobData.put("jobGroup", properties.getProperty(jobName + ".group") + "");
jobMap.put(jobName, jobData);
}
}
for (String mapKey : jobMap.keySet()) {
Map<String, String> jobData = (Map<String, String>) jobMap.get(mapKey);
String jobClassName = jobData.get("jobClassName");
String jobName = jobData.get("jobName");
String jobCronExp = jobData.get("jobCronExp");
String jobGroup = jobData.get("jobGroup");
Class<? extends Job> jobClass = null;
try {

jobClass = (Class<? extends Job>) Class.forName(jobClassName);
} catch (ClassNotFoundException e) {

logger.error(e.getMessage());
return false;
}
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger", jobGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(jobCronExp)).build();
try {
schedulerFactory = new StdSchedulerFactory();
try {
scheduler = schedulerFactory.getScheduler();
} catch (SchedulerException e) {
logger.error(e.getMessage());
return false;
}
if (scheduler == null) {
logger.error("scheduler is null");
return false;
}
scheduler.scheduleJob(job, trigger);
scheduler.start();
} catch (SchedulerException e) {
logger.error(e.getMessage());
return false;
}
}
return true;
}

无非是获取到多个job名字用临时map进行存储,然后使用java反射机制遍历执行调度任务。