Spring+Mybatis +Quartz 实现定时任务管理

不点 阅读:586 2021-03-31 16:59:50 评论:0

 

任务要求:通过开源任务调度框架Quartz,实现定时任务的添加、修改、删除、暂停、恢复和分页查询功能。

第一步:base 模块添加quartz jar包依赖:

	<!-- 定时任务框架  --> 
		<dependency> 
			<groupId>org.quartz-scheduler</groupId> 
			<artifactId>quartz</artifactId> 
			<version>2.3.0</version> 
		</dependency>

第二步:新增Quartz配置类对象:SchedulerConfig.java

import java.io.IOException; 
import java.util.Properties; 
 
import org.quartz.Scheduler; 
import org.quartz.ee.servlet.QuartzInitializerListener; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.config.PropertiesFactoryBean; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.io.ClassPathResource; 
import org.springframework.scheduling.quartz.SchedulerFactoryBean; 
 
import com.***.ucas.job.factory.CustomerJobFactory; 
 
@Configuration 
public class SchedulerConfig { 
	@Autowired 
	private CustomerJobFactory jobFactory; 
 
	@Bean 
	public SchedulerFactoryBean schedulerFactoryBean() throws IOException { 
		SchedulerFactoryBean factory = new SchedulerFactoryBean(); 
		factory.setOverwriteExistingJobs(true); 
		// 延时启动 
		factory.setStartupDelay(20); 
 
		// 加载quartz数据源配置 
		factory.setQuartzProperties(quartzProperties()); 
 
		// 自定义Job Factory,用于Spring注入 
		factory.setJobFactory(jobFactory); 
		return factory; 
	} 
 
	@Bean 
	public Properties quartzProperties() throws IOException { 
		PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); 
		propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); 
		// 在quartz.properties中的属性被读取并注入后再初始化对象 
		propertiesFactoryBean.afterPropertiesSet(); 
		return propertiesFactoryBean.getObject(); 
	} 
 
	/* 
	 * quartz初始化监听器 
	 */ 
	@Bean 
	public QuartzInitializerListener executorListener() { 
		return new QuartzInitializerListener(); 
	} 
 
	/* 
	 * 通过SchedulerFactoryBean获取Scheduler的实例 
	 */ 
	@Bean(name = "scheduler") 
	public Scheduler scheduler() throws Exception { 
		return schedulerFactoryBean().getScheduler(); 
	} 
}

自定义定时任务工厂:CustomerJobFactory.java

import org.quartz.spi.TriggerFiredBundle; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 
import org.springframework.scheduling.quartz.AdaptableJobFactory; 
import org.springframework.stereotype.Component; 
 
@Component 
public class CustomerJobFactory extends AdaptableJobFactory { 
	 @Autowired 
	 private AutowireCapableBeanFactory capableBeanFactory; 
 
	@Override 
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { 
		// 调用父类的方法 
        Object jobInstance = super.createJobInstance(bundle); 
        // 进行注入 
        capableBeanFactory.autowireBean(jobInstance); 
        return jobInstance; 
	} 
}

三、添加Quartz的配置文件:在service模块的src/main/resource文件夹下新建quartz.properties 配置文件,配置文件的内容如下:

# 固定前缀org.quartz 
# 主要分为scheduler、threadPool、jobStore、plugin等部分 
org.quartz.scheduler.instanceName = DefaultQuartzScheduler 
org.quartz.scheduler.rmi.export = false 
org.quartz.scheduler.rmi.proxy = false 
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false 
 
# 实例化ThreadPool时,使用的线程类为SimpleThreadPool 
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
 
# threadCount和threadPriority将以setter的形式注入ThreadPool实例 
# 并发个数 
org.quartz.threadPool.threadCount = 5 
# 优先级 
org.quartz.threadPool.threadPriority = 5 
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true 
org.quartz.jobStore.misfireThreshold = 5000 
 
 
#MySQL 持久化 
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 
# 表名前缀 
org.quartz.jobStore.tablePrefix = qrtz_ 
# 指定数据库 
org.quartz.jobStore.dataSource = ucas 
# 指定mysql 驱动 
org.quartz.dataSource.ucas.driver = com.mysql.cj.jdbc.Driver 
# 数据库连接地址 
org.quartz.dataSource.ucas.URL = jdbc:mysql://192.168.*.**:3306/ucas?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true 
# 数据库账户 
org.quartz.dataSource.ucas.user = root 
# 数据库密码 
org.quartz.dataSource.ucas.password = ****** 
# 配置最大连接数 
org.quartz.dataSource.ucas.maxConnections = 10

四、自定义定时任务对应的实体对象:SysCron.java

import java.util.Date; 
 
import com.***.common.model.BaseModel; 
 
@SuppressWarnings("serial") 
public class SysCron extends BaseModel { 
    private String id; 
 
    private String jobName; 
 
    private String jobDescription; 
 
    private String jobGroupName; 
 
    private String jobClassName; 
 
    private String triggerName; 
 
    private String triggerGroupName; 
 
    private String prevFireTime; 
 
    private String nextFireTime; 
 
    private String cronExpression; 
 
    private String triggerState; 
 
    public String getId() { 
        return id; 
    } 
 
    public void setId(String id) { 
        this.id = id == null ? null : id.trim(); 
    } 
 
    public String getJobName() { 
        return jobName; 
    } 
 
    public void setJobName(String jobName) { 
        this.jobName = jobName == null ? null : jobName.trim(); 
    } 
 
    public String getJobDescription() { 
        return jobDescription; 
    } 
 
    public void setJobDescription(String jobDescription) { 
        this.jobDescription = jobDescription == null ? null : jobDescription.trim(); 
    } 
 
    public String getJobGroupName() { 
        return jobGroupName; 
    } 
 
    public void setJobGroupName(String jobGroupName) { 
        this.jobGroupName = jobGroupName == null ? null : jobGroupName.trim(); 
    } 
 
    public String getJobClassName() { 
        return jobClassName; 
    } 
 
    public void setJobClassName(String jobClassName) { 
        this.jobClassName = jobClassName == null ? null : jobClassName.trim(); 
    } 
 
    public String getTriggerName() { 
        return triggerName; 
    } 
 
    public void setTriggerName(String triggerName) { 
        this.triggerName = triggerName == null ? null : triggerName.trim(); 
    } 
 
    public String getTriggerGroupName() { 
        return triggerGroupName; 
    } 
 
    public void setTriggerGroupName(String triggerGroupName) { 
        this.triggerGroupName = triggerGroupName == null ? null : triggerGroupName.trim(); 
    } 
 
    public String getPrevFireTime() { 
        return prevFireTime; 
    } 
 
    public void setPrevFireTime(String prevFireTime) { 
        this.prevFireTime = prevFireTime; 
    } 
 
    public String getNextFireTime() { 
        return nextFireTime; 
    } 
 
    public void setNextFireTime(String nextFireTime) { 
        this.nextFireTime = nextFireTime; 
    } 
 
    public String getCronExpression() { 
        return cronExpression; 
    } 
 
    public void setCronExpression(String cronExpression) { 
        this.cronExpression = cronExpression == null ? null : cronExpression.trim(); 
    } 
 
    public String getTriggerState() { 
        return triggerState; 
    } 
 
    public void setTriggerState(String triggerState) { 
        this.triggerState = triggerState == null ? null : triggerState.trim(); 
    } 
}

自定义接口服务层:SysCronService.java

import java.util.List; 
import java.util.Map; 
import com.***.common.model.PageParam; 
import com.***.common.page.PageData; 
import com.***.ucas.domain.SysCron; 
 
public interface SysCronService{ 
	 
	// 全部查询 
	List<SysCron> selectAll(Map<String,Object> parame); 
	//分页查询 
	PageData<SysCron> selectAllPage(Map<String,Object> parame, PageParam rb); 
	// 添加定时任务 
	public boolean addSysCron(SysCron entity); 
	// 更新定时任务 
	public boolean updateSysCron(SysCron entity); 
	// 删除定时任务 
	public boolean deleteSysCron(SysCron entity); 
	// 暂时定时任务 
	public boolean pauseSysCron(SysCron entity); 
	// 恢复定时任务 
	public boolean resumeJob(SysCron entity); 
} 

自定义接口服务实现层:SysCronServiceImpl .java (核心代码:实现定时任务新增、修改、暂停、恢复和删除功能

import java.util.List; 
import java.util.Map; 
import org.quartz.CronScheduleBuilder; 
import org.quartz.CronTrigger; 
import org.quartz.JobBuilder; 
import org.quartz.JobDetail; 
import org.quartz.JobKey; 
import org.quartz.Scheduler; 
import org.quartz.TriggerBuilder; 
import org.quartz.TriggerKey; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import com.***.common.job.BaseJob; 
import com.***.common.model.PageParam; 
import com.***.common.page.PageData; 
import com.***.ucas.api.SysCronService; 
import com.***.ucas.domain.SysCron; 
import com.***.ucas.mapper.SysCronMapper; 
import com.github.pagehelper.PageHelper; 
import com.github.pagehelper.PageInfo; 
 
@Service 
public class SysCronServiceImpl implements SysCronService { 
	private static final Logger log = LoggerFactory.getLogger(SysCronServiceImpl.class); 
 
	@Autowired 
	private Scheduler scheduler; 
	@Autowired 
	private SysCronMapper mapper; 
	 
	@Override 
	public List<SysCron> selectAll(Map<String, Object> parame) { 
		return mapper.selectAll(parame); 
	} 
 
	@Override 
	public PageData<SysCron> selectAllPage(Map<String, Object> parame, PageParam rb) { 
		// TODO Auto-generated method stub 
		PageData<SysCron> pageData = new PageData<SysCron>(); 
		 
		PageHelper.startPage(rb.getPageNo(), rb.getLimit()); 
		List<SysCron> rs = mapper.selectAll(parame); 
		 
		PageInfo<SysCron> pageInfo = new PageInfo<SysCron>(rs); 
		pageData.setData(pageInfo.getList()); 
		pageData.setPageNum(pageInfo.getPageNum()); 
		pageData.setPageSize(pageInfo.getPageSize()); 
		pageData.setTotalCount(pageInfo.getTotal()); 
		return pageData; 
	} 
 
	 
	@Override 
	public boolean addSysCron(SysCron entity) { 
		boolean target = false; 
		try { 
			// 启动调度器 
			scheduler.start(); 
			// 构建job信息 
			JobDetail jobDetail = JobBuilder.newJob(getClass(entity.getJobClassName()).getClass()) 
					.withIdentity(entity.getJobClassName(), entity.getJobGroupName()).build(); 
			// 表达式调度构建器(即任务执行的时间) 
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(entity.getCronExpression()); 
			// 按新的cronExpression表达式构建一个新的trigger 
			CronTrigger trigger = TriggerBuilder.newTrigger() 
					.withIdentity(entity.getJobClassName(), entity.getJobGroupName()).withSchedule(scheduleBuilder) 
					.build(); 
 
			scheduler.scheduleJob(jobDetail, trigger); 
			target = true; 
		} catch (Exception e) { 
			log.error("创建定时任务异常" + e.getMessage()); 
			return target; 
		} 
		return target; 
	} 
 
	@Override 
	public boolean updateSysCron(SysCron entity) { 
		boolean target = false; 
		try { 
			TriggerKey triggerKey = TriggerKey.triggerKey(entity.getJobClassName(), entity.getJobGroupName()); 
			// 表达式调度构建器 
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(entity.getCronExpression()); 
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); 
			// 按新的cronExpression表达式重新构建trigger 
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); 
			// 按新的trigger重新设置job执行 
			scheduler.rescheduleJob(triggerKey, trigger); 
			target = true; 
		} catch (Exception e) { 
			log.error("定时任务更新失败" + e.getMessage()); 
			return target; 
		} 
 
		return target; 
	} 
 
	@Override 
	public boolean deleteSysCron(SysCron entity) { 
		boolean target = false; 
		try { 
			scheduler.pauseTrigger(TriggerKey.triggerKey(entity.getJobClassName(), entity.getJobGroupName())); 
			scheduler.unscheduleJob(TriggerKey.triggerKey(entity.getJobClassName(), entity.getJobGroupName())); 
			scheduler.deleteJob(JobKey.jobKey(entity.getJobClassName(), entity.getJobGroupName())); 
			target = true; 
		} catch (Exception e) { 
			log.error("定时任务删除失败" + e.getMessage()); 
			return target; 
		} 
		return target; 
	} 
 
	@Override 
	public boolean pauseSysCron(SysCron entity) { 
		boolean target = false; 
		try { 
			scheduler.pauseJob(JobKey.jobKey(entity.getJobClassName(), entity.getJobGroupName())); 
			target = true; 
		} catch (Exception e) { 
			log.error("暂停定时任务失败" + e.getMessage()); 
			return target; 
		} 
		return target; 
	} 
 
	@Override 
	public boolean resumeJob(SysCron entity) { 
		boolean target = false; 
		try { 
			scheduler.resumeJob(JobKey.jobKey(entity.getJobClassName(), entity.getJobGroupName())); 
			target = true; 
		} catch (Exception e) { 
			log.error("恢复定时任务失败" + e.getMessage()); 
			return target; 
		} 
		return target; 
	} 
 
	/** 
	 *  
	 * @param classname 
	 * @return 
	 * @throws Exception 
	 */ 
	public static BaseJob getClass(String classname) throws Exception { 
		Class<?> class1 = Class.forName(classname); 
		return (BaseJob) class1.newInstance(); 
	} 
 
	 
 
} 

数据库mapp 接口定义和mapp 查询映射

import java.util.List; 
import java.util.Map; 
 
import com.***.common.model.PageParam; 
import com.***.common.page.PageData; 
import com.***.ucas.domain.SysCron; 
 
public interface SysCronMapper { 
    // 全部查询 
 	List<SysCron> selectAll(Map<String,Object> parame); 
 	//分页查询 
 	PageData<SysCron> selectAllPage(Map<String,Object> parame, PageParam rb); 
}
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<mapper namespace="com.digipower.ucas.mapper.SysCronMapper"> 
 
  <!-- 公共查询条件  --> 
  <sql id="condition"> 
  		<if test="jobClassName != null"> 
  			and jd.job_class_name = #{jobClassName,jdbcType=VARCHAR} 
  		</if> 
  		<if test="jobGroupName != null"> 
  			and jd.job_group = #{jobGroupName,jdbcType=VARCHAR} 
  		</if> 
  		<if test="triggerName != null"> 
  			and t.trigger_name = #{triggerName,jdbcType=VARCHAR} 
  		</if> 
  		<if test="triggerGroupName != null"> 
  			and t.trigger_group = #{triggerGroupName,jdbcType=VARCHAR} 
  		</if> 
  		<if test="triggerState != null"> 
  			and t.trigger_state = #{triggerState, jdbcType=VARCHAR} 
  		</if> 
  </sql> 
 
	 <!-- 全部查询 --> 
    <select id="selectAll" resultType="com.digipower.ucas.domain.SysCron"> 
            select 
                jd.job_name as jobname, 
                jd.description as jobdescription, 
                jd.job_group as jobgroupname, 
                jd.job_class_name as jobclassname, 
                t.trigger_name as triggername, 
                t.trigger_group as triggergroupname, 
                from_unixtime(t.prev_fire_time/1000,'%y-%m-%d %t') as prevfiretime, 
                from_unixtime(t.next_fire_time/1000,'%y-%m-%d %t') as nextfiretime, 
                ct.cron_expression as cronexpression, 
                t.trigger_state as triggerstate 
            from 
                qrtz_job_details jd 
            join qrtz_triggers t 
            join qrtz_cron_triggers ct on jd.job_name = t.job_name 
            and t.trigger_name = ct.trigger_name 
            and t.trigger_group = ct.trigger_group 
            where 1 = 1 
            <include refid="condition" /> 
    </select> 
</mapper>

至此,Spring + Mybatis + Quartz 实现定义任务管理的基本功能封装完毕。

效果截图:待补充

第五步:添加自定义定时任务:

定义通用公共基础任务:BaseJob.java

import org.quartz.Job; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
 
/** 
 * 定时任务基础类 
 * @author zzg 
 * 
 */ 
public interface BaseJob extends Job { 
	public void execute(JobExecutionContext context) throws JobExecutionException; 
} 

添加自定义Job 

import java.util.Date; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import com.***.common.job.BaseJob; 
 
public class SimpleJob implements BaseJob { 
	private static final Logger log = LoggerFactory.getLogger(SimpleJob.class); 
	 
	public SimpleJob(){ 
		System.out.println(new Date() + "SimpleJob"); 
        try { 
            Thread.sleep(10000); 
            System.out.println("任务 SimpleJob 开始干活。。。"); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
            log.error("SimpleJob 定时任务报错:" + e.getMessage()); 
        } 
        System.out.println(new Date() + "SimpleJob 任务结束------------------------------------"); 
	} 
 
	@Override 
	public void execute(JobExecutionContext context) throws JobExecutionException { 
		// TODO Auto-generated method stub 
		 System.out.println("SimpleJob执行时间: " + new Date()); 
	} 
 
}
import java.util.List; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
import org.springframework.beans.factory.annotation.Autowired; 
import com.alibaba.fastjson.JSONObject; 
import com.***.common.job.BaseJob; 
import com.***.ucas.domain.SysDataCategory; 
import com.***.ucas.mapper.SysDataCategoryMapper; 
 
public class SysDataCategoryJob implements BaseJob { 
 
	@Autowired 
	private SysDataCategoryMapper mapper; 
	 
	@Override 
	public void execute(JobExecutionContext context) throws JobExecutionException { 
		List<SysDataCategory> list = mapper.selectAll(); 
		if(list != null && list.size() > 0){ 
			String json = JSONObject.toJSONString(list); 
			System.out.println("json 内容:" + json); 
		} 
	} 
 
}

补充说明:Quartz.2.x MySQL 建库脚本:请参考:https://blog.csdn.net/zhouzhiwengang/article/details/101776655

 

 

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号