Spring整合Quartz实现定时任务的时间更新,暂停和启用(不需要重启项目并且配置多数据源)

时间:2022-05-16 21:36:22

这是一套独立的定时系统,暂时不涉及与外界三方系统的交互,如有需求可自己根据场景来修改。

配置

项目基于spring4+mybatis3+quartz2.2.1来构建的,pom文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.spdb</groupId>
<artifactId>spdbTimer</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>

<properties>
<!-- spring版本号 -->
<spring.version>4.0.2.RELEASE</spring.version>
<!-- mybatis版本号 -->
<mybatis.version>3.2.6</mybatis.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<comLog.version>1.1.1</comLog.version>
<jackson.version>1.9.13</jackson.version>
<webVersion>3.0</webVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier><!--指定jdk版本 -->
</dependency>
<!-- mybatis核心包 -->
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 导入java ee jar 包 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- 导入Mysql数据库链接jar包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<!-- JSTL标签类 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 日志文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${comLog.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-lgpl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-lgpl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-smile</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
<version>${jackson.version}</version>
</dependency>

<!-- spring 核心jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mybatis分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.0.0</version>
</dependency>
<!-- SQLSERVER连接包 -->
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- 格式化对象,方便输出日志 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<!-- log end -->
<!-- 上传组件包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<!-- spring-ldap-core -->
<dependency>
<groupId>com.sun</groupId>
<artifactId>ldapbp</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<!-- org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>dev</env>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
<profile>
<id>online</id>
<properties>
<env>online</env>
</properties>
</profile>
</profiles>

<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<outputDirectory>${basedir}/src/main/webapp/WEB-INF/classes</outputDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<outputDirectory>${basedir}/src/main/webapp/WEB-INF/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/env/${env}</directory>
<targetPath>${basedir}/src/main/webapp/WEB-INF/classes/conf</targetPath>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

好处及实现

整个项目通过无配置文件无手动添加bean组件的方式自动加载任务并执行,具体的实现核心如下:

package com.spdb.hs.base.quartz;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
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.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import com.spdb.hs.base.annotation.QuartzJob;
import com.spdb.hs.timer.model.SchedulerJob;
import com.spdb.hs.timer.service.iservice.ISchedulerJobService;

public class QuartzJobSchedulerListener implements ApplicationListener<ContextRefreshedEvent> {

private Logger log = Logger.getLogger(QuartzJobSchedulerListener.class);

@Autowired
private Scheduler scheduler;
@Autowired
private ISchedulerJobService jobService;

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {

try {
ApplicationContext applicationContext = event.getApplicationContext();
loadCronTriggers(applicationContext);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}

@SuppressWarnings("unchecked")
private void loadCronTriggers(ApplicationContext applicationContext) {
//获取所有有注解QuartzJob的Job
Map<String,Object> quartzJobBeans = applicationContext.getBeansWithAnnotation(QuartzJob.class);
//获取所有job名字
Set<String> jobNames = quartzJobBeans.keySet();
List<SchedulerJob> jobList = new ArrayList<SchedulerJob>();

try {
for (String jobName : jobNames) {
//反射获取任务类对象,并获取注解信息,入库
Object obj = quartzJobBeans.get(jobName);
if(obj.getClass().isAnnotationPresent(QuartzJob.class)){
QuartzJob quartzJob = obj.getClass().getAnnotation(QuartzJob.class);
String cronExp = quartzJob.cron();
String groupName = quartzJob.groupName();
String desc = quartzJob.desc();
//检查数据库存在性,不存在则添加
if(jobService.getByNameAndGroup(jobName,groupName)==null){
jobList.add(addJob(jobName, quartzJob, desc));
}

//判断执行器中此任务是否存在不存在则添加到执行器中
if(!isJobExist(jobName, groupName)){
JobKey jobKey = new JobKey(jobName, groupName);
JobDetail job = JobBuilder
.newJob((Class<? extends Job>)obj.getClass())
.withIdentity(jobKey)
.build();

CronTrigger cronTrigger = TriggerBuilder
.newTrigger()
.withIdentity(jobName + "_trigger", groupName)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
.build();


scheduler.scheduleJob(job, cronTrigger);

}
}
}

//入库定时任务
if(jobList.size()>0){
try {
Integer count = jobService.addLst(jobList);
if(count==0){
//插入失败
log.error("定时任务入库失败.......");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
} catch (SchedulerException e) {
log.error(e.getMessage());
}

}

private boolean isJobExist(String jobName, String groupName) {

try {
return scheduler.checkExists(new JobKey(jobName,groupName));
} catch (SchedulerException e) {
log.error(e.getMessage(), e);
return false;
}
}

private SchedulerJob addJob(String jobName, QuartzJob quartzJob, String desc) {
SchedulerJob schedulerJob = new SchedulerJob();
schedulerJob.setCronExp(quartzJob.cron());
schedulerJob.setJobGroup(quartzJob.groupName());
schedulerJob.setJobName(jobName);
schedulerJob.setJobDesc(StringUtils.isNotBlank(desc)?desc:null);
return schedulerJob;
}

}

可以很清楚的看到我们这个类是ApplicationListener的实现类,ApplicationListener的实现类表示在spring容器完全加载完成后自动回去干的事,不需要我们管理,那么我们就可以通过自定义注解的方式让我们的任务执行类配置这个注解通过applicationContext.getBeansWithAnnotation(QuartzJob.class);来获取所有拥有这个直接的任务实现类。此注解的配置如下,由于要入库,所以此注解需要的其实就是以往我们需要在配置文件中添加的一些信息:

package com.spdb.hs.base.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 用注解来反射读取注解中的cron表达式,用来在web启动的时候自动录入数据库
* @author zhy
*
*/

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface QuartzJob {
String cron();//表达式
String groupName();//任务组名
String desc();//任务描述

}

具体的任务执行类:

package com.spdb.hs.timer.job;

import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import com.spdb.hs.base.annotation.QuartzJob;
import com.spdb.hs.base.constants.QuartzJobGroupConstants;

@QuartzJob( cron="0/15 * * * * ?",groupName=QuartzJobGroupConstants.GROUP_GET, desc = "测试专用")
@Component
public class MyTestJob extends QuartzJobBean {

protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("THE FIRST JOB HAS RUN AND THE TIME IS :" + new Date().toString());

}

}

基于此配置你就可以实现在项目启动完成后定时任务的自动入库与执行,由于任务祖名和触发器组名要区分开来,你可以在操作触发器的时候加个自定义后缀,我们这里添加的是”_trigger”,效果如下:

 scheduler.resumeTrigger(TriggerKey.triggerKey(jobName+"_trigger", groupName));// 重启触发器 

这些配置好后,我们只需要向外提供修改指定任务时间和暂停启动指定任务的接口即可做到定时任务的系统不重启更新,这其中涉及到quartz底层自己管理的11张数据表,我们可以不用管他,以及一张我自定义的统筹任务表,这些表在 :定时任务整合项目中有sql文件,你可以转换成你需要的sql。

具体修改流程其实就是一个restful风格的请求

Controller

package com.spdb.hs.timer.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.spdb.hs.timer.service.iservice.ISchedulerJobService;
import com.spdb.hs.timer.vo.PacketHead;
import com.spdb.hs.timer.vo.ResultVo;

@Controller
@RequestMapping(value="/qrtz")
public class QuartzController {

private Logger log = Logger.getLogger(QuartzController.class);

@Autowired
private ISchedulerJobService shedulerJobService;

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午3:48:01
* 修改时间:2017年7月27日 下午3:48:01
* Description: 修改指定定时任务执行时间
*
*/

@RequestMapping("upd")
@ResponseBody
public ResultVo doUpdate(@RequestParam(value="jobName",required=true) String jobName,
@RequestParam(value="groupName",required=true) String groupName,
@RequestParam(value="cronExp",required=true) String cronExp){
ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.updSchedulerJob(jobName,groupName,cronExp);
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}
}

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午3:50:12
* 修改时间:2017年7月27日 下午3:50:12
* Description: 移除指定定时任务
*
*/

@RequestMapping("remove")
@ResponseBody
public ResultVo doRemove(@RequestParam(value="jobName",required=true) String jobName,
@RequestParam(value="groupName",required=true) String groupName){

ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.removeJob(jobName,groupName);
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("定时任务移除失败......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}
}

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午3:58:57
* 修改时间:2017年7月27日 下午3:58:57
* Description: 停止指定定时任务
*
*/

@RequestMapping("pause")
@ResponseBody
public ResultVo doPause(@RequestParam(value="jobName",required=true) String jobName,
@RequestParam(value="groupName",required=true) String groupName){

ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.pauseJob(jobName,groupName);
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("定时任务停止失败......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}
}

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午3:58:57
* 修改时间:2017年7月27日 下午3:58:57
* Description: 停止指定定时任务
*
*/

@RequestMapping("resume")
@ResponseBody
public ResultVo doResume(@RequestParam(value="jobName",required=true) String jobName,
@RequestParam(value="groupName",required=true) String groupName){

ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.resumeJob(jobName,groupName);
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("定时任务停止失败......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}
}

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午4:25:45
* 修改时间:2017年7月27日 下午4:25:45
* Description: 停止所有定时任务
*
*/

@RequestMapping("shutdown")
@ResponseBody
public ResultVo doShutDown(){
ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.shutDownAll();
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("定时任务停止失败......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}

}

/**
*
* 方法描述:
* 创建人:zhy
* 创建时间:2017年7月27日 下午4:25:45
* 修改时间:2017年7月27日 下午4:25:45
* Description: 开始所有定时任务
*
*/

@RequestMapping("startAll")
@ResponseBody
public ResultVo doStartAll(){
ResultVo vo = new ResultVo();
try {
boolean flag = shedulerJobService.startAll();
if(flag){
return vo;
}else{
vo.setErrorCode(PacketHead.JSON_ERR_BAD);
vo.setErrorMsg("定时任务停止失败......");
return vo;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
vo.setErrorCode(PacketHead.JSON_ERR_SYS);
vo.setErrorMsg("更新定时任务失败.......");
return vo;
}

}

}

具体实现层

package com.spdb.hs.timer.service.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.spdb.hs.timer.dao.SchedulerJobDao;
import com.spdb.hs.timer.model.SchedulerJob;
import com.spdb.hs.timer.service.iservice.ISchedulerJobService;

@Service
public class SchdelerJobService implements ISchedulerJobService {

private Logger log = Logger.getLogger(SchdelerJobService.class);

@Autowired
private SchedulerJobDao schedulerJobDao;
@Autowired
private Scheduler scheduler;

@Override
public SchedulerJob getByNameAndGroup(String jobName, String jobGroup) {
return schedulerJobDao.findByNameAndGroup(jobName,jobGroup);
}

@Override
public Integer addLst(List<SchedulerJob> jobList) {
return schedulerJobDao.insertLst(jobList);
}

@Override
public boolean updSchedulerJob(String jobName, String groupName, String cronExp) {
boolean flag = false;
try {
//修改当前执行器中相应的定时任务时间
if(!scheduler.checkExists(new JobKey(jobName,groupName))){
return flag;
}else{
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(TriggerKey.triggerKey(jobName+"_trigger",groupName));
if(trigger==null){
return flag;
}else{
String oldCronExp= trigger.getCronExpression();
if(!oldCronExp.equalsIgnoreCase(cronExp)){
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(jobName+"_trigger",groupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronExp));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 修改一个任务的触发时间
scheduler.rescheduleJob(TriggerKey.triggerKey(jobName+"_trigger",groupName), trigger);
}
}
}

//修改主表记录数据
SchedulerJob schedulerJob = schedulerJobDao.findByNameAndGroup(jobName, groupName);
if(schedulerJob!=null){
schedulerJob.setCronExp(cronExp);
Integer count = schedulerJobDao.modifyJob(schedulerJob);
if(count==1){
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
}

} catch (SchedulerException e) {
throw new RuntimeException(e);
}
return flag;
}

@Override
public boolean removeJob(String jobName, String groupName) {
boolean flag = false;
try {
if(scheduler.checkExists(JobKey.jobKey(jobName, groupName))){
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName+"_trigger", groupName));// 停止触发器
scheduler.unscheduleJob(TriggerKey.triggerKey(jobName+"_trigger", groupName));// 移除触发器
scheduler.deleteJob(JobKey.jobKey(jobName, groupName));// 删除任务

//修改主表记录数据
SchedulerJob schedulerJob = schedulerJobDao.findByNameAndGroup(jobName, groupName);
if(schedulerJob!=null){
schedulerJob.setJobStatus(Short.valueOf("2"));//0 启用,1 暂定使用 2 不再使用
Integer count = schedulerJobDao.modifyJob(schedulerJob);
if(count==1){
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return flag;
}

@Override
public boolean pauseJob(String jobName, String groupName) {
boolean flag = false;
try {
if(scheduler.checkExists(JobKey.jobKey(jobName, groupName))){
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName+"_trigger", groupName));// 停止触发器
//修改主表记录数据
SchedulerJob schedulerJob = schedulerJobDao.findByNameAndGroup(jobName, groupName);
if(schedulerJob!=null){
schedulerJob.setJobStatus(Short.valueOf("1"));//0 启用,1 暂定使用 2 不再使用
Integer count = schedulerJobDao.modifyJob(schedulerJob);
if(count==1){
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return flag;
}

@Override
public boolean resumeJob(String jobName, String groupName) {
boolean flag = false;
try {
if(scheduler.checkExists(JobKey.jobKey(jobName, groupName))){
scheduler.resumeTrigger(TriggerKey.triggerKey(jobName+"_trigger", groupName));// 重启触发器
//修改主表记录数据
SchedulerJob schedulerJob = schedulerJobDao.findByNameAndGroup(jobName, groupName);
if(schedulerJob!=null){
schedulerJob.setJobStatus(Short.valueOf("0"));//0 启用,1 暂定使用 2 不再使用
Integer count = schedulerJobDao.modifyJob(schedulerJob);
if(count==1){
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return flag;
}

@Override
public boolean shutDownAll() {
boolean flag = false;
try {
if (!scheduler.isShutdown()) {
scheduler.pauseAll();
scheduler.shutdown();
}
//修改主表记录数据,将所有任务的任务状态改为停止状态
Integer count = schedulerJobDao.pauseAll();
if(count>0){
//修改成功
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
return flag;
}

@Override
public boolean startAll() {
boolean flag = false;
try {
if (!scheduler.isStarted()) {
scheduler.start();
}
//修改主表记录数据,将所有任务的任务状态改为停止状态
Integer count = schedulerJobDao.startAll();
if(count>0){
//修改成功
flag = true;
}else{
log.error(" The Error Count is :" + count);
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
return flag;
}
}

数据库11张表都是由Quartz自己维护的,我们不需要维护这些东西,只需要维护我们自定义的一张统筹表,我们可以根据这张表联查在页面上显示定时任务数量,状态以及不重启自动修改定时时间。

整个项目已经过实战,由于简单化,没有加上资源访问限制,这里可以根据自己的业务需求自己添加。

注:如果是添加了新的定时任务的话,由于源码的不同步,暂时是达不到不重启自动添加的效果,如果您有好的处理方法请留言交流谢谢