这里是我真实项目中使用的,个人认为是比较全一点的,如果不足,还希望多多包涵或者补充
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
<version>2.2.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.5version>
dependency>
#默认或是自己改名字都行
org.quartz.scheduler.instanceName=HeaelrJeanQuartzScheduler
#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.jobFactory.class=org.quartz.simpl.SimpleJobFactory
org.quartz.scheduler.autoStartup=true
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=30
org.quartz.threadPool.threadPriority=5
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
rg.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#misfireThreshold是用来设置调度引擎对触发器超时的忍耐时间,简单来说 假设misfireThreshold=6000(单位毫秒)。
#那么它的意思说当一个触发器超时时间如果大于misfireThreshold的值 就认为这个触发器真正的超时(也叫Misfires)。
org.quartz.jobStore.misfireThreshold=60000
#存储的JobDataMaps是否都为String类型
org.quartz.jobStore.useProperties=true
# 数据源 我们自己配置
org.quartz.jobStore.dataSource=healerjean
# 数据源使用quartz配置
#org.quartz.jobStore.tablePrefix = QRTZ_
#org.quartz.jobStore.dataSource = myDS
#
#
##配置数据源
#数据库中quartz表的表名前缀
#
#org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/com_hlj_quartz?characterEncoding=utf-8
#org.quartz.dataSource.myDS.user = root
#org.quartz.dataSource.myDS.password = 123456
#org.quartz.dataSource.myDS.maxConnections = 5
spring.application.name=quartz
spring.profiles.active=demo
#freemarker
spring.freemarker.charset=UTF-8
spring.freemarker.cache=true
spring.freemarker.enabled=true
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.expose-spring-macro-helpers=true
spring.freemarker.request-context-attribute=request
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=
#aop
spring.aop.auto=true
spring.aop.proxy-target-class=true
#spring data jpa properties
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database=MYSQL
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.data.jpa.repositories.enabled=true
#log level
logging.level.root=info
logging.level.org.springframework=ERROR
logging.level.org.mybatis=ERROR
logging.level.org.mybatis.example.BlogMapper=debug
#logging.level.com.duodian.youhui.dao.mybatis.coupon=debug
#static
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
#
#
##出现错误时, 直接抛出异常 路径访问错误也抛出异常
#spring.mvc.throw-exception-if-no-handler-found=true
#spring.resources.add-mappings=false
server.port=8080
########################################################
###datasource mysql
########################################################
spring.datasource.url=jdbc:mysql://localhost:3306/com_hlj_demo?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
#datasource healerjean 这个我们自己配置
healerjean.datasource.url=jdbc:mysql://localhost:3306/com_hlj_quartz?characterEncoding=utf-8
healerjean.datasource.username=root
healerjean.datasource.password=123456
healerjean.datasource.driver-class-name=com.mysql.jdbc.Driver
logging.config=classpath:logback.xml
package com.hlj;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
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 org.springframework.scheduling.quartz.SpringBeanJobFactory;
import javax.sql.DataSource;
/**
* 类描述:
* 创建人: HealerJean
*/
@Configuration
public class QuartzConfig {
@Value("${healerjean.datasource.url}")
private String healerjeanUrl;
@Value("${healerjean.datasource.username}")
private String healerjeanname;
@Value("${healerjean.datasource.password}")
private String healerjeanPassword;
@Bean
public SpringBeanJobFactory jobFactory (){
return new SpringBeanJobFactory();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean (SpringBeanJobFactory jobFactory) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setDataSource(createAdmore());
schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactoryBean.setGlobalJobListeners(new com.duodian.admore.quartz.core.event.HealerJeanJobListener());
schedulerFactoryBean.setOverwriteExistingJobs(true);
return schedulerFactoryBean;
}
/**
* 单独为定时任务创建一个单独的datasource
*/
private DataSource createAdmore(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(healerjeanUrl);
druidDataSource.setUsername(healerjeanname);
druidDataSource.setPassword(healerjeanPassword);
druidDataSource.setMaxActive(10);
druidDataSource.setInitialSize(5);
druidDataSource.setTestWhileIdle(true);
druidDataSource.setMaxWait(2500);
druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
druidDataSource.setMinEvictableIdleTimeMillis(300000);
return druidDataSource;
}
}
其实有用的,也就是第3个
package com.duodian.admore.quartz.core.event;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
/**
* 类描述:
* 创建人: HealerJean
*/
@Slf4j
public class HealerJeanJobListener implements JobListener {
private static final String LISTENER_NAME = "healerjean.job.listener";
@Override
public String getName() {
return LISTENER_NAME;
}
/**
* 任务执行之前执行
*/
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
log.info(jobExecutionContext.getJobDetail().getKey() + " to be execute");
}
/**
*
* 任务取消
* 这个方法正常情况下不执行,但是如果当TriggerListener中的vetoJobExecution方法返回true时,那么执行这个方法.
* 需要注意的是 如果方法(2)执行 那么(1),(3)这个俩个方法不会执行,因为任务被终止了嘛.
*/
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
log.info(jobExecutionContext.getJobDetail().getKey() + " vetoed");
}
/**
任务执行完成后执行,jobException如果它不为空则说明任务在执行过程中出现了异常
*/
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
if (e != null){
String jobName = jobExecutionContext.getJobDetail().getKey().getName();
String errMsg = e.getMessage();
log.error(jobExecutionContext.getJobDetail().getKey() + " execute failure");
log.error(e.getMessage(),e);
} else {
log.info(jobExecutionContext.getJobDetail().getKey() + " execute success");
}
}
}
package com.hlj.quartz.core.schedule;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Set;
/**
* HealerJean
* quartz job调度核心类
*/
@Component
public class HealerJeanScheduler {
private Logger logger = LoggerFactory.getLogger(HealerJeanScheduler.class);
private final static String TRIGGER_PERFIX = "t_";
@Resource
private Scheduler scheduler;
public <T extends Job> void startJob(String jobId, String cron, Class<T> t, String jobDesc) throws SchedulerException {
JobDetail job = JobBuilder.newJob(t).withIdentity(jobId).withDescription(jobDesc).build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(TRIGGER_PERFIX + jobId).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
scheduler.scheduleJob(job, trigger);
logger.info(jobId + " start at " + new Date());
}
public void resetJob(String jobId,String corn) {
try {
if (scheduler.checkExists(new JobKey(jobId))){
JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobId));
logger.info("name:"+jobDetail.getKey().getName());
logger.info("group:"+jobDetail.getKey().getGroup());
TriggerKey triggerKey = TriggerKey.triggerKey(TRIGGER_PERFIX+jobDetail.getKey().getName(), jobDetail.getKey().getGroup());
//获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(corn);
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey,trigger);
logger.info(jobId + " reset at " + new Date());
}
} catch (SchedulerException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
/****
* 暂停任务
*/
public void pauseJob(String jobId) {
try {
if (scheduler.checkExists(new JobKey(jobId))){
scheduler.pauseJob(new JobKey(jobId));
logger.info(jobId + " pause at " + new Date());
}
} catch (SchedulerException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
/**
* 删除任务
* @param jobId
*/
public void deleteJob(String jobId) {
try {
if (scheduler.checkExists(new JobKey(jobId))){
scheduler.deleteJob(new JobKey(jobId));
logger.info(jobId + " delete at " + new Date());
}
} catch (SchedulerException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
/**
* 暂停重启
* @param jobId
*/
public void resumeJob(String jobId) {
try {
if (scheduler.checkExists(new JobKey(jobId))){
scheduler.resumeJob(new JobKey(jobId));
logger.info(jobId + " resume at " + new Date());
}
} catch (SchedulerException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
/**
* 获取所有的任务 的 JobKey
* @return
*/
public Set<JobKey> currentJobs(){
try {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
return scheduler.getJobKeys(matcher);
} catch (SchedulerException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
/**
* 获取任务详情 JobDetail
* @param jobKey
* @return
*/
public JobDetail getJobDetail(JobKey jobKey){
try {
return scheduler.getJobDetail(jobKey);
} catch (SchedulerException e) {
throw new RuntimeException();
}
}
/**
* 获取触发器 Trigger
* @param jobKey
* @return
*/
public Trigger getJobTrigger(JobKey jobKey){
try {
return scheduler.getTrigger(new TriggerKey(TRIGGER_PERFIX + jobKey.getName()));
} catch (SchedulerException e) {
throw new RuntimeException();
}
}
/**
* 获取触发器 任务的执行状态
* @param jobKey
* @return
*/
public Trigger.TriggerState getTriggerState(JobKey jobKey){
try {
return scheduler.getTriggerState(new TriggerKey(TRIGGER_PERFIX + jobKey.getName()));
} catch (SchedulerException e) {
throw new RuntimeException();
}
}
}
package com.hlj.quartz.job;
import org.quartz.*;
import org.springframework.stereotype.Component;
/**
* @Description
* @Author HealerJean
* @Date 2018/3/23 下午4:19.
*/
@Component
public class MyTask implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
//可以通过context拿到执行当前任务的quartz中的很多信息,如当前是哪个trigger在执行该任务
CronTrigger trigger = (CronTrigger) context.getTrigger();
TriggerKey triggerKey =trigger.getKey() ;
String corn = trigger.getCronExpression();
System.out.println("任务规则 :"+corn);
System.out.println("triggerKey Name:"+triggerKey.getName()); //t_jobId
System.out.println("triggerKey group:"+triggerKey.getGroup()); //t_jobId
System.out.println("----------------------");
JobKey jobKey = context.getJobDetail().getKey() ;
System.out.println("jobKey getName"+jobKey.getName()); //jobId
System.out.println("jobKey getGroup"+jobKey.getGroup()); //DEFAULT
Scheduler scheduler = context.getScheduler();
System.out.println("scheduler.getCalendarNames()"+scheduler.getCalendarNames());
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
System.out.println(jobDetail.getClass().toString());
}catch (Exception e){
e.printStackTrace();
}
System.out.println("执行任务中");
}
}
package com.hlj.web.quartz;
import com.hlj.data.general.ResponseBean;
import com.hlj.quartz.core.schedule.HealerJeanScheduler;
import com.hlj.web.quartz.vo.JobDetailBean;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 类描述:
* 创建人: HealerJean
*/
@Controller
@RequestMapping("quartz")
public class QuartzController {
private Logger logger = LoggerFactory.getLogger(QuartzController.class);
@Resource
private HealerJeanScheduler scheduler;
@RequestMapping("jobList")
@ResponseBody
public List<JobDetailBean> login(){
Set<JobKey> jobKeySet = scheduler.currentJobs();
List<JobDetailBean> jobDetailList = new ArrayList<>();
for (JobKey jobKey : jobKeySet){
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
Trigger trigger = scheduler.getJobTrigger(jobKey);
JobDetailBean detailBean = new JobDetailBean();
detailBean.setJobId(jobKey.getName());
detailBean.setJobDesc(jobDetail.getDescription());
detailBean.setCron(((CronTrigger)trigger).getCronExpression());
detailBean.setJobClass(jobDetail.getJobClass().toString());
detailBean.setPreviousFireTime(trigger.getPreviousFireTime());
detailBean.setNextFireTime(trigger.getNextFireTime());
Trigger.TriggerState triggerState = scheduler.getTriggerState(jobKey);
detailBean.setJobStatus(triggerState.name());
jobDetailList.add(detailBean);
}
return jobDetailList;
}
@RequestMapping("create")
@ResponseBody
public ResponseBean create(String jobId, String jobCron, String jobClass, String jobDesc){
try {
scheduler.startJob(jobId,jobCron,Class.forName(jobClass).asSubclass(Job.class),jobDesc);
return ResponseBean.buildSuccess();
} catch (Exception e) {
logger.error(e.getMessage(),e);
return ResponseBean.buildFailure(e.getMessage());
}
}
@RequestMapping("update")
@ResponseBody
public ResponseBean update(String jobId,String jobCron,String jobClass,String jobDesc){
try {
scheduler.resetJob(jobId,jobCron);
return ResponseBean.buildSuccess();
} catch (Exception e) {
logger.error(e.getMessage(),e);
return ResponseBean.buildFailure(e.getMessage());
}
}
@RequestMapping("delete")
@ResponseBody
public ResponseBean delete(String jobId){
try {
scheduler.deleteJob(jobId);
return ResponseBean.buildSuccess();
} catch (Exception e) {
logger.error(e.getMessage(),e);
return ResponseBean.buildFailure(e.getMessage());
}
}
@RequestMapping("pause")
@ResponseBody
public ResponseBean pause(String jobId){
try {
scheduler.pauseJob(jobId);
return ResponseBean.buildSuccess();
} catch (Exception e) {
logger.error(e.getMessage(),e);
return ResponseBean.buildFailure(e.getMessage());
}
}
@RequestMapping("resume")
@ResponseBody
public ResponseBean start(String jobId){
try {
scheduler.resumeJob(jobId);
return ResponseBean.buildSuccess();
} catch (Exception e) {
logger.error(e.getMessage(),e);
return ResponseBean.buildFailure(e.getMessage());
}
}
}
2019-02-20 17:57:25.830 [http-nio-8080-exec-6] INFO c.h.q.c.schedule.HealerJeanScheduler - name:test
2019-02-20 17:57:25.830 [http-nio-8080-exec-6] INFO c.h.q.c.schedule.HealerJeanScheduler - group:DEFAULT
2019-02-20 17:57:25.853 [http-nio-8080-exec-6] INFO c.h.q.c.schedule.HealerJeanScheduler - test reset at Wed Feb 20 17:57:25 CST 2019
2019-02-20 17:58:00.019 [HeaelrJeanQuartzScheduler_Worker-1] INFO c.d.a.q.c.e.HealerJeanJobListener - DEFAULT.test to be execute
任务规则 :0 58 17 * * ?
triggerKey Name:t_test
triggerKey group:DEFAULT
----------------------
jobKey getNametest
jobKey getGroupDEFAULT
scheduler.getCalendarNames()[]
class com.hlj.quartz.job.MyTask
执行任务中
2019-02-20 17:58:00.029 [HeaelrJeanQuartzScheduler_Worker-1] INFO c.d.a.q.c.e.HealerJeanJobListener - DEFAULT.test execute success