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

 

任务要求:通过开源任务调度框架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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值