SpingBoot+Quartz+数据库存储
1、Spring整合Quartz
2、读取数据库中表达式启动定时任务1(每5s执行)
3、更改定时任务状态(启用/禁用),定时任务1停止
4、读取数据库中表达式启动定时任务2(每5s执行),在对应作业类中打印定时任务2携带的参数
5、读取数据库中表达式启动定时任务3(每5s执行改成每20s执行),更改数据库定时任务表达式,定时任务3对应执行策略相应发生改变。
Spring整合Quartz
a、quartz调度框架是有内置表的
进入quartz的官网http://www.quartz-scheduler.org/,点击Downloads,
下载后在目录\docs\dbTables下有常用数据库创建quartz表的脚本,例如:“tables_mysql.sql”
table_mysql.sql
table_mysql_innodb.sql
上述两者所有的数据库引擎不一样
导入pom依赖
1
2 com.alibaba
3 druid-spring-boot-starter
4 1.1.10
5
c、在项目中添加quartz.properties文件(这样就不会加载自带的properties文件)
此文件的内容主要分为:scheduler,ThreadPool,JobStore,plugin,Datasources等部分,
覆盖properties文件的目的是覆盖默认的数据源,更换为druid的数据配置
d、自定义MyJobFactory,解决spring不能在quartz中注入bean的问题
e、创建调度器schedule,交给spring进行管理
f、创建自定义任务
g、更新quartz中的任务
自定义任务表与quartz内置表的区分
要搞清楚一个问题:从数据库读取任务信息动态生成定时任务,和把quartz持久化到数据库是没有关系的。
前者是我们自己定义的业务表,而后者是quartz使用自己的表来存储信息。
持久化到数据库后,就算服务器重启或是多个quartz节点也没关系,因为他们共享数据库中的任务信息。
创建项目
自定义业务表
1 --注意:job_name存放的任务类的全路径,在quartz中通过jobName和jobGroup来确定trigger的唯一性,所以这两列为联合唯一索引2 create table t_schedule_trigger3 (4 id int primary key auto_increment, --ID5 cron varchar(200) not null, --时间表达式6 status char(1) not null, -- 使用状态 0:禁用 1:启用7 job_name varchar(200) not null, --任务名称8 job_group varchar(200) not null, --任务分组9 unique index(job_name,job_group)10 );11
12 --额外添加到任务中的参数13 create table t_schedule_trigger_param14 (15 param_id int primary key auto_increment, --ID16 name varchar(200) not null, --参数名17 value varchar(512), --参数值18
19 schedule_trigger_id int not null, --外键:引用t_schedule_trigger(id)20 foreign key(schedule_trigger_id) references t_schedule_trigger(id)21 );
DruidConnectionProvider
1 packagecom.yuan.quartz02.utils;2
3 importcom.alibaba.druid.pool.DruidDataSource;4 importorg.quartz.SchedulerException;5 importorg.quartz.utils.ConnectionProvider;6
7 importjava.sql.Connection;8 importjava.sql.SQLException;9
10 /*
11 #============================================================================12 # JDBC13 #============================================================================14 org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate15 org.quartz.jobStore.useProperties:false16 org.quartz.jobStore.dataSource:qzDS17 #org.quartz.dataSource.qzDS.connectionProvider.class:org.quartz.utils.PoolingConnectionProvider18 org.quartz.dataSource.qzDS.connectionProvider.class:com.zking.q03.quartz.DruidConnectionProvider19 org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver20 org.quartz.dataSource.qzDS.URL:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-821 org.quartz.dataSource.qzDS.user:root22 org.quartz.dataSource.qzDS.password:root23 org.quartz.dataSource.qzDS.maxConnections:3024 org.quartz.dataSource.qzDS.validationQuery: select 025 */
26
27 /**
28 * [Druid连接池的Quartz扩展类]29 *30 * @ProjectName: []31 * @Author: [xuguang]32 * @CreateDate: [2015/11/10 17:58]33 * @Update: [说明本次修改内容] BY[xuguang][2015/11/10]34 * @Version: [v1.0]35 */
36 public class DruidConnectionProvider implementsConnectionProvider {37
38 /*
39 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~40 *41 * 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供set方法,Quartz框架自动注入值。42 *43 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~44 */
45
46 //JDBC驱动
47 publicString driver;48 //JDBC连接串
49 publicString URL;50 //数据库用户名
51 publicString user;52 //数据库用户密码
53 publicString password;54 //数据库最大连接数
55 public intmaxConnection;56 //数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。
57 publicString validationQuery;58
59 private booleanvalidateOnCheckout;60
61 private intidleConnectionValidationSeconds;62
63 publicString maxCachedStatementsPerConnection;64
65 privateString discardIdleConnectionsSeconds;66
67 public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;68
69 public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;70
71 //Druid连接池
72 privateDruidDataSource datasource;73
74 /*
75 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~76 *77 * 接口实现78 *79 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~80 */
81 public Connection getConnection() throwsSQLException {82 returndatasource.getConnection();83 }84
85 public void shutdown() throwsSQLException {86 datasource.close();87 }88 public void initialize() throwsSQLException{89 if (this.URL == null) {90 throw new SQLException("DBPool could not be created: DB URL cannot be null");91 }92
93 if (this.driver == null) {94 throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");95 }96
97 if (this.maxConnection < 0) {98 throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");99 }100
101 datasource = newDruidDataSource();102 try{103 datasource.setDriverClassName(this.driver);104 } catch(Exception e) {105 try{106 throw new SchedulerException("Problem setting driver class name on datasource: " +e.getMessage(), e);107 } catch(SchedulerException e1) {108 }109 }110
111 datasource.setUrl(this.URL);112 datasource.setUsername(this.user);113 datasource.setPassword(this.password);114 datasource.setMaxActive(this.maxConnection);115 datasource.setMinIdle(1);116 datasource.setMaxWait(0);117 datasource.setMaxPoolPreparedStatementPerConnectionSize(this.DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION);118
119 if (this.validationQuery != null) {120 datasource.setValidationQuery(this.validationQuery);121 if(!this.validateOnCheckout)122 datasource.setTestOnReturn(true);123 else
124 datasource.setTestOnBorrow(true);125 datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);126 }127 }128
129 /*
130 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~131 *132 * 提供get set方法133 *134 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~135 */
136 publicString getDriver() {137 returndriver;138 }139
140 public voidsetDriver(String driver) {141 this.driver =driver;142 }143
144 publicString getURL() {145 returnURL;146 }147
148 public voidsetURL(String URL) {149 this.URL =URL;150 }151
152 publicString getUser() {153 returnuser;154 }155
156 public voidsetUser(String user) {157 this.user =user;158 }159
160 publicString getPassword() {161 returnpassword;162 }163
164 public voidsetPassword(String password) {165 this.password =password;166 }167
168 public intgetMaxConnection() {169 returnmaxConnection;170 }171
172 public void setMaxConnection(intmaxConnection) {173 this.maxConnection =maxConnection;174 }175
176 publicString getValidationQuery() {177 returnvalidationQuery;178 }179
180 public voidsetValidationQuery(String validationQuery) {181 this.validationQuery =validationQuery;182 }183
184 public booleanisValidateOnCheckout() {185 returnvalidateOnCheckout;186 }187
188 public void setValidateOnCheckout(booleanvalidateOnCheckout) {189 this.validateOnCheckout =validateOnCheckout;190 }191
192 public intgetIdleConnectionValidationSeconds() {193 returnidleConnectionValidationSeconds;194 }195
196 public void setIdleConnectionValidationSeconds(intidleConnectionValidationSeconds) {197 this.idleConnectionValidationSeconds =idleConnectionValidationSeconds;198 }199
200 publicDruidDataSource getDatasource() {201 returndatasource;202 }203
204 public voidsetDatasource(DruidDataSource datasource) {205 this.datasource =datasource;206 }207 }
quartz.properties
1 #2 #============================================================================
3 # Configure Main Scheduler Properties 调度器属性4 #============================================================================
5 org.quartz.scheduler.instanceName: DefaultQuartzScheduler6 org.quartz.scheduler.instanceId =AUTO7 org.quartz.scheduler.rmi.export: false
8 org.quartz.scheduler.rmi.proxy: false
9 org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
10 org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool11 org.quartz.threadPool.threadCount= 10
12 org.quartz.threadPool.threadPriority: 5
13 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
14 org.quartz.jobStore.misfireThreshold: 60000
15 #============================================================================
16 # Configure JobStore17 #============================================================================
18 #存储方式使用JobStoreTX,也就是数据库19 org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX20 org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate21 #使用自己的配置文件22 org.quartz.jobStore.useProperties:true
23 #数据库中quartz表的表名前缀24 org.quartz.jobStore.tablePrefix:qrtz_25 org.quartz.jobStore.dataSource:qzDS26 #是否使用集群(如果项目只部署到 一台服务器,就不用了)27 org.quartz.jobStore.isClustered = true
28 #============================================================================
29 # Configure Datasources30 #============================================================================
31 #配置数据库源(org.quartz.dataSource.qzDS.maxConnections: c3p0配置的是有s的,druid数据源没有s)32 org.quartz.dataSource.qzDS.connectionProvider.class:com.yuan.quartz02.utils.DruidConnectionProvider33 org.quartz.dataSource.qzDS.driver: com.mysql.jdbc.Driver34 org.quartz.dataSource.qzDS.URL: jdbc:mysql://localhost:3306/j2ee?useUnicode=true&characterEncoding=utf8
35 org.quartz.dataSource.qzDS.user: root36 org.quartz.dataSource.qzDS.password: 12345
37 org.quartz.dataSource.qzDS.maxConnection: 10
MyJobFactory
1 packagecom.yuan.quartz02.utils;2
3 importlombok.extern.slf4j.Slf4j;4 importorg.quartz.spi.TriggerFiredBundle;5 importorg.springframework.beans.factory.annotation.Autowired;6 importorg.springframework.beans.factory.config.AutowireCapableBeanFactory;7 importorg.springframework.scheduling.quartz.AdaptableJobFactory;8 importorg.springframework.stereotype.Component;9
10 @Component11 @Slf4j12 public class MyJobFactory extendsAdaptableJobFactory {13
14 //这个对象Spring会帮我们自动注入进来
15 @Autowired16 privateAutowireCapableBeanFactory autowireCapableBeanFactory;17
18 //重写创建Job任务的实例方法
19 @Override20 protected Object createJobInstance(TriggerFiredBundle bundle) throwsException {21 Object jobInstance = super.createJobInstance(bundle);22 //通过以下方式,解决Job任务无法使用Spring中的Bean问题
23 autowireCapableBeanFactory.autowireBean(jobInstance);24 return super.createJobInstance(bundle);25 }26 }
QuartzConfiguration.java(quartz调度框架与spring框架整合的配置类,主要是要将org.quartz.Scheduler交给spring进行管理)
1 packagecom.yuan.quartz02.config;2
3 importcom.yuan.quartz02.utils.MyJobFactory;4 importorg.quartz.Scheduler;5 importorg.springframework.beans.factory.annotation.Autowired;6 importorg.springframework.beans.factory.config.PropertiesFactoryBean;7 importorg.springframework.context.annotation.Bean;8 importorg.springframework.context.annotation.Configuration;9 importorg.springframework.core.io.ClassPathResource;10 importorg.springframework.scheduling.quartz.SchedulerFactoryBean;11
12 importjava.io.IOException;13 importjava.util.Properties;14
15 @Configuration16 public classQuartzConfiguration {17
18 @Autowired19 privateMyJobFactory myJobFactory;20
21 //创建调度器工厂
22 @Bean23 publicSchedulerFactoryBean schedulerFactoryBean(){24 //1.创建SchedulerFactoryBean25 //2.加载自定义的quartz.properties配置文件26 //3.设置MyJobFactory
27
28 SchedulerFactoryBean factoryBean=newSchedulerFactoryBean();29 try{30 factoryBean.setQuartzProperties(quartzProperties());31 factoryBean.setJobFactory(myJobFactory);32 returnfactoryBean;33 } catch(IOException e) {34 throw newRuntimeException(e);35 }36 }37
38 @Bean39 public Properties quartzProperties() throwsIOException {40 PropertiesFactoryBean propertiesFactoryBean=newPropertiesFactoryBean();41 propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));42 propertiesFactoryBean.afterPropertiesSet();43 returnpropertiesFactoryBean.getObject();44 }45
46 @Bean(name="scheduler")47 publicScheduler scheduler(){48 returnschedulerFactoryBean().getScheduler();49 }50 }
案例中需要观察表数据变化的表
1 --自定义的业务表2 SELECT *FROM t_schedule_trigger;3 SELECT *FROM t_schedule_trigger_param;4
5 --quartz调度框架自带的表6 SELECT *FROM qrtz_scheduler_state;7 SELECT *FROM qrtz_cron_triggers;8 SELECT *FROM qrtz_simple_triggers9 SELECT *FROM qrtz_triggers;10 SELECT * FROM qrtz_job_details;
项目目录结构
导入pom依赖
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 4.0.0
5
6 org.springframework.boot
7 spring-boot-starter-parent
8 2.2.1.RELEASE
9
10
11 com.yuan
12 quartz02
13 0.0.1-SNAPSHOT
14 quartz02
15 Demo project for Spring Boot
16
17
18 1.8
19 5.1.44
20
21
22
23
24 org.springframework.boot
25 spring-boot-starter-jdbc
26
27
28 org.springframework.boot
29 spring-boot-starter-quartz
30
31
32 org.springframework.boot
33 spring-boot-starter-thymeleaf
34
35
36 org.springframework.boot
37 spring-boot-starter-web
38
39
40 org.mybatis.spring.boot
41 mybatis-spring-boot-starter
42 2.1.1
43
44
45
46 mysql
47 mysql-connector-java
48 ${mysql.version}
49 runtime
50
51
52 org.projectlombok
53 lombok
54 true
55
56
57 org.springframework.boot
58 spring-boot-starter-test
59 test
60
61
62 org.junit.vintage
63 junit-vintage-engine
64
65
66
67
68
69 com.alibaba
70 druid-spring-boot-starter
71 1.1.10
72
73
74 org.quartz-scheduler
75 quartz-jobs
76 2.2.1
77
78
79
80
81
82
83
84
85 src/main/resources
86
87
88
89 src/main/java
90
91 **/*.xml92 93 94 95 96 src/main/resources97 98 *.properties99 *.xml100 *.yml101 102 103 104
105
106 107 108 org.mybatis.generator109 mybatis-generator-maven-plugin110 1.3.2111 112 113 114 mysql115 mysql-connector-java116 ${mysql.version}117 118 119 120 true121 122 123
124 125 org.springframework.boot126 spring-boot-maven-plugin127 128 129 130
131
配置application.yml
1 server:2 servlet:3 context-path: /quartz4 spring:5 datasource:6 #1.JDBC7 type: com.alibaba.druid.pool.DruidDataSource8 driver-class-name: com.mysql.jdbc.Driver9 url: jdbc:mysql://localhost:3306/j2ee?useUnicode=true&characterEncoding=utf8
10 username: root11 password: 12345
12 druid:13 #2.连接池配置14 #初始化连接池的连接数量 大小,最小,最大15 initial-size: 5
16 min-idle: 5
17 max-active: 20
18 #配置获取连接等待超时的时间19 max-wait: 60000
20 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒21 time-between-eviction-runs-millis: 60000
22 # 配置一个连接在池中最小生存的时间,单位是毫秒23 min-evictable-idle-time-millis: 30000
24 validation-query: SELECT 1FROM DUAL25 test-while-idle: true
26 test-on-borrow: true
27 test-on-return: false
28 # 是否缓存preparedStatement,也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开29 pool-prepared-statements: true
30 max-pool-prepared-statement-per-connection-size: 20
31 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙32 filter:33 stat:34 merge-sql: true
35 slow-sql-millis: 5000
36 #3.基础监控配置37 web-stat-filter:38 enabled: true
39 url-pattern: /*
40 #设置不统计哪些URL41 exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"42 session-stat-enable: true43 session-stat-max-count: 10044 stat-view-servlet:45 enabled: true46 url-pattern: /druid/*47 reset-enable: true48 #设置监控页面的登录名和密码49 login-username: admin50 login-password: admin51 allow: 127.0.0.152 #deny: 192.168.1.10053
54 #显示日志55 logging:56 level:57 com.yuan.quartz02.mapper: debug
Quartz02Application
1 packagecom.yuan.quartz02;2
3 importorg.mybatis.spring.annotation.MapperScan;4 importorg.springframework.boot.SpringApplication;5 importorg.springframework.boot.autoconfigure.SpringBootApplication;6 importorg.springframework.scheduling.annotation.EnableScheduling;7 importorg.springframework.transaction.annotation.EnableTransactionManagement;8
9 @MapperScan("com.yuan.quartz02.mapper")10 @EnableTransactionManagement11 @EnableScheduling12 @SpringBootApplication13 public classQuartz02Application {14
15 public static voidmain(String[] args) {16 SpringApplication.run(Quartz02Application.class, args);17 }18
19 }
添加逆向生成代码generatorConfig.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 /p>
3 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>
22
23
24
25
26
27
28
29
30
31
32
33 targetProject="src/main/java">
34
35
36
37
38
39
40
41
42
43
44
45
46 targetProject="src/main/java">
47
48
49
50
51
52
53
54
55
56 targetProject="src/main/java" type="XMLMAPPER">
57
58
59
60
61
62
63 enableCountByExample="false" enableDeleteByExample="false"
64 enableSelectByExample="false" enableUpdateByExample="false">
65
66
67
68 enableCountByExample="false" enableDeleteByExample="false"
69 enableSelectByExample="false" enableUpdateByExample="false">
70
71
72
73
74
jdbc.properties
1 jdbc.driver=com.mysql.jdbc.Driver2 jdbc.url=jdbc:mysql://localhost:3306/j2ee?useUnicode=true&characterEncoding=UTF-8
3 jdbc.username=root4 jdbc.password=12345
ScheduleTriggerMapper
1 packagecom.yuan.quartz02.mapper;2
3 importcom.yuan.quartz02.model.ScheduleTrigger;4 importorg.springframework.stereotype.Repository;5
6 importjava.util.List;7
8 @Repository9 public interfaceScheduleTriggerMapper {10 intdeleteByPrimaryKey(Integer id);11
12 intinsert(ScheduleTrigger record);13
14 intinsertSelective(ScheduleTrigger record);15
16 ScheduleTrigger selectByPrimaryKey(Integer id);17
18 intupdateByPrimaryKeySelective(ScheduleTrigger record);19
20 intupdateByPrimaryKey(ScheduleTrigger record);21
22 /**
23 * 查询触发器中包含的所有任务24 *@return
25 */
26 ListqueryScheduleTriggerLst();27 }
在自动生成的ScheduleTriggerMapper.xml中添加
1
2 select
3 from t_schedule_trigger4
ScheduleTriggerParamMapper
1 packagecom.yuan.quartz02.mapper;2
3 importcom.yuan.quartz02.model.ScheduleTriggerParam;4 importorg.springframework.stereotype.Repository;5
6 importjava.util.List;7
8 @Repository9 public interfaceScheduleTriggerParamMapper {10 intdeleteByPrimaryKey(Integer param_id);11
12 intinsert(ScheduleTriggerParam record);13
14 intinsertSelective(ScheduleTriggerParam record);15
16 ScheduleTriggerParam selectByPrimaryKey(Integer param_id);17
18 intupdateByPrimaryKeySelective(ScheduleTriggerParam record);19
20 intupdateByPrimaryKey(ScheduleTriggerParam record);21
22 /**
23 * 查询出当前任务类对应所需的参数24 *@paramtriggerId25 *@return
26 */
27 ListqueryScheduleParamLst(Integer triggerId);28 }
在自动生成的ScheduleTriggerParamMapper.xml中添加
1
2 select
3 from t_schedule_trigger_param where schedule_trigger_id=#{triggerId}4
service层
ScheduleTriggerService
1 packagecom.yuan.quartz02.service;2
3 importcom.yuan.quartz02.model.ScheduleTrigger;4
5 importjava.util.List;6 public interfaceScheduleTriggerService {7 intdeleteByPrimaryKey(Integer id);8
9 intinsert(ScheduleTrigger record);10
11 intinsertSelective(ScheduleTrigger record);12
13 ScheduleTrigger selectByPrimaryKey(Integer id);14
15 intupdateByPrimaryKeySelective(ScheduleTrigger record);16
17 intupdateByPrimaryKey(ScheduleTrigger record);18
19 /**
20 * 查询触发器中包含的所有任务21 *@return
22 */
23 ListqueryScheduleTriggerLst();24
25 }
ScheduleTriggerServiceImpl
1 packagecom.yuan.quartz02.service.impl;2
3 importcom.yuan.quartz02.mapper.ScheduleTriggerMapper;4 importcom.yuan.quartz02.mapper.ScheduleTriggerParamMapper;5 importcom.yuan.quartz02.model.ScheduleTrigger;6 importcom.yuan.quartz02.model.ScheduleTriggerParam;7 importcom.yuan.quartz02.service.ScheduleTriggerService;8 import org.quartz.*;9 importorg.springframework.beans.factory.annotation.Autowired;10 importorg.springframework.scheduling.annotation.Scheduled;11 importorg.springframework.stereotype.Service;12
13 importjava.util.List;14
15 @Service16 public class ScheduleTriggerServiceImpl implementsScheduleTriggerService {17
18 @Autowired19 privateScheduleTriggerMapper scheduleTriggerMapper;20
21 @Autowired22 privateScheduleTriggerParamMapper scheduleTriggerParamMapper;23
24 @Autowired25 privateScheduler scheduler;26
27 @Scheduled(cron = "0/10 * * * * ?")28 public voidrefreshScheduler(){29 try{30 List scheduleTriggers =
31 scheduleTriggerMapper.queryScheduleTriggerLst();32 if(null!=scheduleTriggers){33 for(ScheduleTrigger scheduleTrigger : scheduleTriggers) {34 String cron = scheduleTrigger.getCron(); //表达式
35 String jobName = scheduleTrigger.getJob_name(); //任务名称
36 String jobGroup = scheduleTrigger.getJob_group(); //任务分组
37 String status = scheduleTrigger.getStatus(); //任务状态38
39 //JobName+JobGroup=Primary Key40 //根据jobName和jobGroup生成TriggerKey
41 TriggerKey triggerKey =
42 TriggerKey.triggerKey(jobName, jobGroup);43 //根据TriggerKey到Scheduler调度器中获取触发器
44 CronTrigger cronTrigger =(CronTrigger)45 scheduler.getTrigger(triggerKey);46
47 if(null==cronTrigger){48 if(status.equals("0"))49 continue;50 System.out.println("创建调度器");51 //创建任务详情
52 JobDetail jobDetail=
53 JobBuilder.newJob((Class extends Job>) Class.forName(jobName))54 .withIdentity(jobName,jobGroup)55 .build();56
57 //往Job任务中传递参数
58 JobDataMap jobDataMap =jobDetail.getJobDataMap();59 List params =
60 scheduleTriggerParamMapper.queryScheduleParamLst(scheduleTrigger.getId());61 for(ScheduleTriggerParam param : params) {62 jobDataMap.put(param.getName(),param.getValue());63 }64
65 //创建表达式调度器
66 CronScheduleBuilder cronSchedule =
67 CronScheduleBuilder.cronSchedule(cron);68
69 //创建Trigger
70 cronTrigger=TriggerBuilder.newTrigger()71 .withIdentity(jobName,jobGroup)72 .withSchedule(cronSchedule)73 .build();74
75 //将jobDetail和Trigger注入到scheduler调度器中
76 scheduler.scheduleJob(jobDetail,cronTrigger);77 }else{78 //System.out.println("Quartz 调度任务中已存在该任务");
79 if(status.equals("0")){80 JobKey jobKey =JobKey.jobKey(jobName, jobGroup);81 scheduler.deleteJob(jobKey);82 continue;83 }84 //调度器中的表达式
85 String cronExpression =
86 cronTrigger.getCronExpression();87
88 if(!cron.equals(cronExpression)){89 //创建表达式调度器
90 CronScheduleBuilder cronSchedule =
91 CronScheduleBuilder.cronSchedule(cron);92
93 //重构
94 cronTrigger=cronTrigger.getTriggerBuilder()95 .withIdentity(triggerKey)96 .withSchedule(cronSchedule)97 .build();98
99 //刷新调度器
100 scheduler.rescheduleJob(triggerKey,cronTrigger);101 }102 }103 }104 }105 } catch(Exception e) {106 e.printStackTrace();107 }108 }109
110 @Override111 public intdeleteByPrimaryKey(Integer id) {112 returnscheduleTriggerMapper.deleteByPrimaryKey(id);113 }114
115 @Override116 public intinsert(ScheduleTrigger record) {117 returnscheduleTriggerMapper.insert(record);118 }119
120 @Override121 public intinsertSelective(ScheduleTrigger record) {122 returnscheduleTriggerMapper.insertSelective(record);123 }124
125 @Override126 publicScheduleTrigger selectByPrimaryKey(Integer id) {127 returnscheduleTriggerMapper.selectByPrimaryKey(id);128 }129
130 @Override131 public intupdateByPrimaryKeySelective(ScheduleTrigger record) {132 returnscheduleTriggerMapper.updateByPrimaryKeySelective(record);133 }134
135 @Override136 public intupdateByPrimaryKey(ScheduleTrigger record) {137 returnscheduleTriggerMapper.updateByPrimaryKey(record);138 }139
140 @Override141 public ListqueryScheduleTriggerLst() {142 returnscheduleTriggerMapper.queryScheduleTriggerLst();143 }144 }
ScheduleTriggerParamService
1 packagecom.yuan.quartz02.service;2
3 importcom.yuan.quartz02.model.ScheduleTriggerParam;4
5 importjava.util.List;6
7 public interfaceScheduleTriggerParamService {8
9 /**
10 * 查询出当前任务类对应所需的参数11 *@paramtriggerId12 *@return
13 */
14 ListqueryScheduleParamLst(Integer triggerId);15 }
ScheduleTriggerParamServiceImpl
1 packagecom.yuan.quartz02.service.impl;2
3 importcom.yuan.quartz02.mapper.ScheduleTriggerParamMapper;4 importcom.yuan.quartz02.model.ScheduleTriggerParam;5 importcom.yuan.quartz02.service.ScheduleTriggerParamService;6 importorg.springframework.beans.factory.annotation.Autowired;7 importorg.springframework.stereotype.Service;8
9 importjava.util.List;10
11 @Service12 public class ScheduleTriggerParamServiceImpl implementsScheduleTriggerParamService {13
14 @Autowired15 privateScheduleTriggerParamMapper scheduleTriggerParamMapper;16
17 @Override18 public ListqueryScheduleParamLst(Integer triggerId) {19 returnscheduleTriggerParamMapper.queryScheduleParamLst(triggerId);20 }21 }
读取数据库中表达式启动定时任务
myjob
1 packagecom.yuan.quartz02.quartz;2
3 importlombok.extern.slf4j.Slf4j;4 importorg.quartz.Job;5 importorg.quartz.JobExecutionContext;6 importorg.quartz.JobExecutionException;7 importorg.springframework.stereotype.Component;8
9 importjava.util.Date;10
11 @Component12 @Slf4j13 public class MyJob implementsJob {14
15 @Override16 public void execute(JobExecutionContext jobExecutionContext) throwsJobExecutionException {17 System.out.println("MyJob是一个空的任务计划,时间:"+newDate().toLocaleString());18 }19 }
Spring自带定时任务每10s执行一次,查询自定义触发器表,
获取到具体的作业类及任务表达式,quartz的任务为每5s执行一次,所以打印如上
更改定时任务状态
更改数据库调度器表t_schedule_trigger的state状态
读取数据库中表达式启动定时任务
数据库表t_schedule_trigger配置
当禁用该触发器时,那么程序只会执行spring自带的定时任务,每10s执行一次查询,所以打印语句如上。
MyJob1
1 packagecom.yuan.quartz02.quartz;2
3 importcom.yuan.quartz02.service.ScheduleTriggerParamService;4 importlombok.extern.slf4j.Slf4j;5 import org.quartz.*;6 importorg.springframework.beans.factory.annotation.Autowired;7 importorg.springframework.stereotype.Component;8
9 importjava.util.Date;10
11 @Component12 @Slf4j13 public class MyJob1 implementsJob {14
15 @Autowired16 privateScheduleTriggerParamService scheduleTriggerParamService;17
18 @Override19 public void execute(JobExecutionContext jobExecutionContext) throwsJobExecutionException {20 JobDetail jobDetail =
21 jobExecutionContext.getJobDetail();22 JobDataMap jobDataMap =jobDetail.getJobDataMap();23 System.err.println(new Date().toLocaleString()+"-->携带参数个数:"+jobDataMap.size());24 }25 }
程序执行spring自带的定时任务,每10s执行一次查询,查询t_schedule_trigger表,
调度器表中有两个调度器,都是每5s执行一次,其中一个调度器是需要携带参数的,
携带的参数在t_schedule_trigger_param表中,所以一开始调度器启动的时候需要查询t_schedule_trigger_param表数据,最终打印语句如上。
更改定时任务规则
t_schedule_trigger
程序执行spring自带的定时任务,每10s执行一次查询,查询t_schedule_trigger表
控制器
QuartzController
1 packagecom.yuan.quartz02.controller;2
3 importcom.yuan.quartz02.model.ScheduleTrigger;4 importcom.yuan.quartz02.service.ScheduleTriggerService;5 importorg.springframework.beans.factory.annotation.Autowired;6 importorg.springframework.stereotype.Controller;7 importorg.springframework.web.bind.annotation.PathVariable;8 importorg.springframework.web.bind.annotation.RequestMapping;9 importorg.springframework.web.bind.annotation.ResponseBody;10 importorg.springframework.web.servlet.ModelAndView;11
12 importjava.util.List;13
14 @Controller15 @RequestMapping("/quartz")16 public classQuartzController {17
18 @Autowired19 privateScheduleTriggerService scheduleTriggerService;20
21 @RequestMapping("/list")22 publicModelAndView getAll(){23 ModelAndView modelAndView = newModelAndView();24 List list =scheduleTriggerService.queryScheduleTriggerLst();25 modelAndView.addObject("quartzList",list);26 modelAndView.setViewName("/index");27 returnmodelAndView;28 }29
30 @RequestMapping("/edit")31 publicString editStatus(ScheduleTrigger scheduleTrigger){32 int n =scheduleTriggerService.updateByPrimaryKeySelective(scheduleTrigger);33 return "redirect:/quartz/list";34 }35
36 @RequestMapping("/proSave/{id}")37 public ModelAndView proSave(@PathVariable(value = "id") Integer id){38 ModelAndView modelAndView=newModelAndView();39 ScheduleTrigger scheduleTrigger =scheduleTriggerService.selectByPrimaryKey(id);40 modelAndView.addObject("schedule",scheduleTrigger);41 modelAndView.setViewName("/edit");42 returnmodelAndView;43 }44
45 }
页面代码
index.html
1
2
3
4
5
quartz定时任务管理6
7
8
定时任务管理
9
10
11
任务id12
任务表达式13
任务状态14
job工作类15
job分组16
操作17
18
19
20
21
22
23
24
25 启动
26 停止
27 编辑
28
29
30
31
32
33
34
edit.html
1
2
3
4
5
编辑定时任务6
7
8
编辑定时任务
9
10
11 任务表达式:
12 job工作类:
13 job分组:
14
15
16
17
页面效果
谢谢观看!!!