说明
本文基于大佬的非maven版脚手架增加的功能,大佬的脚手架是MySQL版本的,并且不再更新了,我对它进行了数据库移植,在下篇文章我会写出Oracle的移植相关细节。大佬的脚手架地址:https://gitee.com/duxiaod/irs,我引入了quartz.jar,关于spring和springmvc+mybatis的配置不详细说,运用了mybatis的generator生成相关的后台代码,前台代码就不写了。
界面展示
数据库表设计
JOB_ID设置为主键
数据序列
create sequence SEQ_TB_JOBS
minvalue 1
maxvalue 9999999999999999999999999999
start with 25
increment by 1
cache 20;
Quartz工具类
public class QuartzManagerUtil {
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/**
* @Description 添加一个定时任务
*
* @param jobName
* 任务名
* @param jobGroupName
* 任务组名
* @param triggerName
* 触发器名
* @param triggerGroupName
* 触发器组名
* @param jobClass
* 任务
* @param cron
* 事件表达式
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
Class jobClass, String cron) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
// 任务名,任务组,任务执行类
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 触发器
TriggerBuilder
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 调度容器设置jobDetail和Trigger
scheduler.scheduleJob(jobDetail, trigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一个任务的触发时间
*
* @param jobName
* 任务名
* @param jobGroupName
* 任务组名
* @param triggerName
* 触发器名
* @param triggerGroupName
* 触发器组名
* @param cron
* 时间表达式
*/
public static void modifyJobCron(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
String cron) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (cronTrigger == null) {
return;
}
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一:调用 rescheduleJob开始 */
// 触发器
TriggerBuilder
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
cronTrigger = (CronTrigger) triggerBuilder.build();
// 修改一个任务的触发器时间
scheduler.rescheduleJob(triggerKey, cronTrigger);
/** 方法二:先删除,然后创建一个新的job */
/*
* JobDetail jobDetail =
* scheduler.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
* Class extends Job> jobClass = jobDetail.getJobClass();
* removeJob(jobName, jobGroupName, triggerName,
* triggerGroupName); addJob(jobName, jobGroupName, triggerName,
* triggerGroupName, jobClass, cron);
*/
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description 删除一个任务
*
* @param jobName
* 任务名
* @param jobGroupName
* 任务组名
* @param triggerName
* 触发器名
* @param triggerGroupName
* 触发器组名
*/
public static void deleteJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
scheduler.pauseTrigger(triggerKey);// 停止触发器
scheduler.unscheduleJob(triggerKey);// 移除触发器
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description 停用所有任务
*
*/
public static void pauseAllJob() {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.pauseAll();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description 启用所有任务
*/
public static void resumeAll(){
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.resumeAll();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description 停用某个任务
*
* @param jobName
* 任务名
* @param jobGroupName
* 任务组名
*/
public static void pauseJob(String jobName, String jobGroupName) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description 启用某个任务
* @param jobName
* 任务名
* @param jobGroupName
* 任务组名
*/
public static void resumeJob(String jobName, String jobGroupName) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 关闭所有任务
*/
public static void shutDownAll(){
try {
Scheduler scheduler = schedulerFactory.getScheduler();
if(!scheduler.isShutdown()){
scheduler.shutdown();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 启动所有任务
*/
public static void startAll(){
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 立即运行一次任务
*/
public static void runOnce(String jobName, String jobGroupName){
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.triggerJob(JobKey.jobKey(jobName, jobGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 查询某个任务的状态
*/
public static TriggerState getJobStatus(String triggerName, String triggerGroupName) throws SchedulerException{
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerState state = scheduler.getTriggerState(TriggerKey.triggerKey(triggerName, triggerGroupName));
return state;
}
}
JobController代码
@Controller
@RequestMapping("job")
public class JobController {
@Autowired
private JobService jobService;
@RequestMapping("/jobList")
@RequiresPermissions("job:job:list")
public String jobList() {
return "page/job/jobList";
}
@RequestMapping("/getJobList")
@RequiresPermissions("job:job:list")
@ResponseBody
public ResultUtil getJobList(Integer page, Integer limit) {
return jobService.selectJobs(page, limit);
}
@RequestMapping("/getExecutingJobList")
@RequiresPermissions("job:job:list")
@ResponseBody
public ResultUtil getExecutingJobList(Integer page, Integer limit) {
return jobService.getExecutingJobList(page, limit);
}
@SysLog("批量删除指定任务信息")
@RequestMapping("/delJobs/{jobsId}")
@RequiresPermissions("job:job:delete")
@ResponseBody
public ResultUtil delJobs(@PathVariable("jobsId") String jobsId) {
ResultUtil resultUtil = new ResultUtil();
try {
jobService.delJobs(jobsId);
resultUtil.setCode(0);
} catch (Exception e) {
resultUtil.setCode(500);
e.printStackTrace();
}
return resultUtil;
}
@RequestMapping("/addJob")
@RequiresPermissions("job:job:save")
public String addJob(Model model) {
return "page/job/addJob";
}
@SysLog("添加任务信息")
@RequiresPermissions("job:job:save")
@RequestMapping("/toSaveJob")
@ResponseBody
public ResultUtil toSaveJob(TbJobs job) {
List
if (jobList.size() > 0) {
return ResultUtil.ok("添加的任务失败,存在重复字段值");
}
if (!CronExpression.isValidExpression(job.getCron())) {
return ResultUtil.ok("添加任务失败,时间表达式格式不正确");
}
try {
QuartzManagerUtil.addJob(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getJobGroupName(), Class.forName(job.getClassName()), job.getCron());
} catch (ClassNotFoundException e) {
e.printStackTrace();
return ResultUtil.error("添加失败,执行类不存在");
}
job.setStatus("0");
jobService.insertJob(job);
return ResultUtil.ok("添加任务成功");
}
@RequestMapping("/editJob/{jobId}")
@RequiresPermissions("job:job:update")
public String editJob(Model model, @PathVariable("jobId") String jobId) {
TbJobs job = jobService.selectByPrimaryKey(Long.parseLong(jobId));
model.addAttribute("job", job);
return "page/job/editJob";
}
@SysLog("修改任务信息")
@RequiresPermissions("job:job:update")
@RequestMapping("/toEditJob")
@ResponseBody
public ResultUtil toEditJob(TbJobs job) {
job.setStatus("0");
jobService.updateByPrimaryKey(job);
QuartzManagerUtil.modifyJobCron(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getTriggerGroupName(), job.getCron());
QuartzManagerUtil.resumeJob(job.getJobName(), job.getJobGroupName());
return ResultUtil.ok("修改任务成功");
}
@SysLog("启用任务")
@RequestMapping("/resumeJob/{jobId}")
@ResponseBody
public ResultUtil resumeJob(@PathVariable("jobId") String jobId) {
TbJobs job = jobService.selectByPrimaryKey(Long.parseLong(jobId));
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerState state = scheduler
.getTriggerState(TriggerKey.triggerKey(job.getTriggerName(), job.getTriggerGroupName()));
if (state.equals(TriggerState.NONE)) {
QuartzManagerUtil.addJob(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getJobGroupName(), Class.forName(job.getClassName()), job.getCron());
} else {
QuartzManagerUtil.resumeJob(job.getJobName(), job.getJobGroupName());
}
} catch (SchedulerException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
return ResultUtil.error("添加失败,执行类不存在");
}
job.setStatus("0");
jobService.updateByPrimaryKey(job);
return ResultUtil.ok();
}
@SysLog("停用任务")
@RequestMapping("/pauseJob/{jobId}")
@ResponseBody
public ResultUtil pauseJob(@PathVariable("jobId") String jobId) {
TbJobs job = jobService.selectByPrimaryKey(Long.parseLong(jobId));
QuartzManagerUtil.pauseJob(job.getJobName(), job.getJobGroupName());
job.setStatus("1");
jobService.updateByPrimaryKey(job);
return ResultUtil.ok();
}
@SysLog("立即运行一次任务")
@RequestMapping("/runOnce/{jobId}")
@ResponseBody
public ResultUtil runOnce(@PathVariable("jobId") String jobId) {
TbJobs job = jobService.selectByPrimaryKey(Long.parseLong(jobId));
QuartzManagerUtil.runOnce(job.getJobName(), job.getJobGroupName());
return ResultUtil.ok();
}
}
JobService代码
public interface JobService {
//获取所有任务
public ResultUtil selectJobs(Integer page,Integer limit);
//获取所有执行中的任务
public ResultUtil getExecutingJobList(Integer page,Integer limit);
//批量删除指定任务
public void delJobs(String jobsId);
//插入任务
public void insertJob(TbJobs job);
//根据任务Id查找任务
public TbJobs selectByPrimaryKey(Long jobId);
//根据任务ID更新任务信息
public void updateByPrimaryKey(TbJobs job);
//根据字段查找插入的任务是否有重复字段值
public List
//根据字段查找插入的任务是否有重复字段值2
public TbJobs selectByColumn2(TbJobs job);
//查找数据库中所有的任务信息
public List
public List
}
JobServiceImpl代码
@Service
public class JobServiceImpl implements JobService {
@Autowired
private TbJobsMapper jobMapper;
@Override
public ResultUtil selectJobs(Integer page, Integer limit) {
PageHelper.startPage(page, limit);
TbJobsExample example = new TbJobsExample();
List
PageInfo
ResultUtil resultUtil = new ResultUtil();
resultUtil.setCode(0);
resultUtil.setCount(pageInfo.getTotal());
resultUtil.setData(pageInfo.getList());
return resultUtil;
}
@Override
public ResultUtil getExecutingJobList(Integer page, Integer limit) {
PageHelper.startPage(page, limit);
List
List
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = null;
try {
scheduler = schedulerFactory.getScheduler();
for (TbJobs job : jobList) {
if (job.getStatus().equals("0")) {
TriggerState state = scheduler
.getTriggerState(TriggerKey.triggerKey(job.getTriggerName(), job.getTriggerGroupName()));
if (state.equals(TriggerState.NORMAL)) {
list.add(job);
}
}
}
} catch (SchedulerException e) {
e.printStackTrace();
}
PageInfo
ResultUtil resultUtil = new ResultUtil();
resultUtil.setCode(0);
resultUtil.setCount(pageInfo.getTotal());
resultUtil.setData(pageInfo.getList());
return resultUtil;
}
@Override
public void delJobs(String jobsId) {
String[] jobIds = jobsId.split(",");
for (String jobId : jobIds) {
TbJobs job = selectByPrimaryKey(Long.parseLong(jobId));
QuartzManagerUtil.deleteJob(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getTriggerGroupName());
jobMapper.deleteByPrimaryKey(Long.parseLong(jobId));
}
}
@Override
public void insertJob(TbJobs job) {
jobMapper.insert(job);
}
@Override
public TbJobs selectByPrimaryKey(Long jobId) {
return jobMapper.selectByPrimaryKey(jobId);
}
@Override
public void updateByPrimaryKey(TbJobs job) {
jobMapper.updateByPrimaryKey(job);
}
@Override
public List
return jobMapper.selectByColumn(job);
}
@Override
public TbJobs selectByColumn2(TbJobs job) {
return jobMapper.selectByColumn2(job);
}
@Override
public List
return jobMapper.selectAllJobs();
}
public List
return jobMapper.selectByExample(example);
}
}
JobMapper代码
public interface TbJobsMapper {
int countByExample(TbJobsExample example);
int deleteByExample(TbJobsExample example);
int deleteByPrimaryKey(Long jobId);
int insert(TbJobs record);
int insertSelective(TbJobs record);
List
TbJobs selectByPrimaryKey(Long jobId);
List
TbJobs selectByColumn2(TbJobs job);
List
int updateByExampleSelective(@Param("record") TbJobs record, @Param("example") TbJobsExample example);
int updateByExample(@Param("record") TbJobs record, @Param("example") TbJobsExample example);
int updateByPrimaryKeySelective(TbJobs record);
int updateByPrimaryKey(TbJobs record);
}
JobMapper.xml代码
and ${criterion.condition}
and ${criterion.condition} #{criterion.value}
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
and ${criterion.condition}
#{listItem}
and ${criterion.condition}
and ${criterion.condition} #{criterion.value}
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
and ${criterion.condition}
#{listItem}
JOB_ID, JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, CRON, CLASS_NAME,
STATUS
select
distinct
from tb_jobs
order by ${orderByClause}
select
from tb_jobs
where JOB_ID = #{jobId,jdbcType=BIGINT}
select
from TB_JOBS
where 1=1
select
from TB_JOBS
where 1=1
and JOB_NAME = #{jobName,jdbcType=VARCHAR}
and JOB_GROUP_NAME = #{jobGroupName,jdbcType=VARCHAR}
and TRIGGER_NAME = #{triggerName,jdbcType=VARCHAR}
and TRIGGER_GROUP_NAME = #{triggerGroupName,jdbcType=VARCHAR}
and CLASS_NAME = #{className,jdbcType=VARCHAR}
select
from TB_JOBS
where 1=1
and JOB_NAME = #{jobName,jdbcType=VARCHAR}
and JOB_GROUP_NAME = #{jobGroupName,jdbcType=VARCHAR}
and TRIGGER_NAME = #{triggerName,jdbcType=VARCHAR}
and TRIGGER_GROUP_NAME = #{triggerGroupName,jdbcType=VARCHAR}
and CLASS_NAME = #{className,jdbcType=VARCHAR}
delete from tb_jobs
where JOB_ID = #{jobId,jdbcType=BIGINT}
delete from tb_jobs
insert into tb_jobs (JOB_ID, JOB_NAME, JOB_GROUP_NAME,
TRIGGER_NAME, TRIGGER_GROUP_NAME, CRON,
CLASS_NAME, STATUS)
values (#{jobId,jdbcType=BIGINT}, #{jobName,jdbcType=VARCHAR}, #{jobGroupName,jdbcType=VARCHAR},
#{triggerName,jdbcType=VARCHAR}, #{triggerGroupName,jdbcType=VARCHAR}, #{cron,jdbcType=VARCHAR},
#{className,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR})
insert into tb_jobs
JOB_ID,
JOB_NAME,
JOB_GROUP_NAME,
TRIGGER_NAME,
TRIGGER_GROUP_NAME,
CRON,
CLASS_NAME,
STATUS,
#{jobId,jdbcType=BIGINT},
#{jobName,jdbcType=VARCHAR},
#{jobGroupName,jdbcType=VARCHAR},
#{triggerName,jdbcType=VARCHAR},
#{triggerGroupName,jdbcType=VARCHAR},
#{cron,jdbcType=VARCHAR},
#{className,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR},
select count(*) from tb_jobs
update tb_jobs
JOB_ID = #{record.jobId,jdbcType=BIGINT},
JOB_NAME = #{record.jobName,jdbcType=VARCHAR},
JOB_GROUP_NAME = #{record.jobGroupName,jdbcType=VARCHAR},
TRIGGER_NAME = #{record.triggerName,jdbcType=VARCHAR},
TRIGGER_GROUP_NAME = #{record.triggerGroupName,jdbcType=VARCHAR},
CRON = #{record.cron,jdbcType=VARCHAR},
CLASS_NAME = #{record.className,jdbcType=VARCHAR},
STATUS = #{record.status,jdbcType=VARCHAR},
update tb_jobs
set JOB_ID = #{record.jobId,jdbcType=BIGINT},
JOB_NAME = #{record.jobName,jdbcType=VARCHAR},
JOB_GROUP_NAME = #{record.jobGroupName,jdbcType=VARCHAR},
TRIGGER_NAME = #{record.triggerName,jdbcType=VARCHAR},
TRIGGER_GROUP_NAME = #{record.triggerGroupName,jdbcType=VARCHAR},
CRON = #{record.cron,jdbcType=VARCHAR},
CLASS_NAME = #{record.className,jdbcType=VARCHAR},
STATUS = #{record.status,jdbcType=VARCHAR}
update tb_jobs
JOB_NAME = #{jobName,jdbcType=VARCHAR},
JOB_GROUP_NAME = #{jobGroupName,jdbcType=VARCHAR},
TRIGGER_NAME = #{triggerName,jdbcType=VARCHAR},
TRIGGER_GROUP_NAME = #{triggerGroupName,jdbcType=VARCHAR},
CRON = #{cron,jdbcType=VARCHAR},
CLASS_NAME = #{className,jdbcType=VARCHAR},
STATUS = #{status,jdbcType=VARCHAR},
where JOB_ID = #{jobId,jdbcType=BIGINT}
update tb_jobs
set JOB_NAME = #{jobName,jdbcType=VARCHAR},
JOB_GROUP_NAME = #{jobGroupName,jdbcType=VARCHAR},
TRIGGER_NAME = #{triggerName,jdbcType=VARCHAR},
TRIGGER_GROUP_NAME = #{triggerGroupName,jdbcType=VARCHAR},
CRON = #{cron,jdbcType=VARCHAR},
CLASS_NAME = #{className,jdbcType=VARCHAR},
STATUS = #{status,jdbcType=VARCHAR}
where JOB_ID = #{jobId,jdbcType=BIGINT}
Tomcat启动就加载数据库中的任务
public class QuartzStartInitialize implements ApplicationListener
@Autowired
private JobService jobService;
private static final Logger logger = LoggerFactory.getLogger(QuartzStartInitialize.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent()==null){
List
if (jobList.size() > 0) {
for (TbJobs job : jobList) {
if (job.getStatus().equals("0")) {
if (CronExpression.isValidExpression(job.getCron())) {
QuartzManagerUtil.deleteJob(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getTriggerGroupName());
try {
QuartzManagerUtil.addJob(job.getJobName(), job.getJobGroupName(), job.getTriggerName(),
job.getTriggerGroupName(), Class.forName(job.getClassName()), job.getCron());
logger.info("定时任务"+job.getJobName()+": 开始启动");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}else{
logger.warn("定时任务"+job.getJobName()+": cron表达式不正确");
}
}
}
}
}
}
}
Spring配置
将上面的QuartzStartInitialize 类配置到applicationContext-dao.xml中。