Quartz动态添加定时任务执行sql(服务启动添加+手动添加)

系统用来每天插入视图数据。。。

一、数据库表设计

1、接口配置表(t_m_db_interface_config

 

2、接口日志表(t_m_db_interface_log

 

3、前端配置页面

查询页面:

新增及修改页面:

第一个sql一般用来删除原有数据,第二个sql一般用来插入新数据,多条sql可以写在一起,代码中做了批处理,用分号隔开(英文的分号)。

不配置临界时间点时sql示例:delete from table_ where BUSSINESS_DATE>=DATE_FORMAT(NOW(),'%Y-%m-%d');

配置临界时间点sql示例:delete from table_ where BUSSINESS_DATE>=DATE_FORMAT(?,'%Y-%m-%d');

时间条件可自己修改,注意的是如果sql中有?号则说明配置了临界时间点,代码中会根据设置的临界时间点来确定是今天还是昨天。

4、单表类

上述两张表的字段设计可根据实际需求灵活调整。

按mvc的开发模式,写出上述两个表对应的对码。也可以Mybatis工具自动分包生成。

分别位于com.dbs.dmsmdm.(controller/service/mapper/bean).simple路径下。

xml映射文件位于resources/mybatis+同上路径下。

这里只贴出bean层代码,Controllor、Service、dao、mapper就不贴出来了。

前面的@ApiModelProperty注解为自定义的注解,请忽略。。。

  1 package com.dbs.dmsmdm.bean.simple;
  2 
  3 import com.dbs.dms.uibase.bean.BaseBean;
  4 import java.util.Date;
  5 
  6 import org.springframework.format.annotation.DateTimeFormat;
  7 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  8 import com.fasterxml.jackson.annotation.JsonFormat;
  9 import com.dbs.dms.uibase.annotations.ApiModel;
 10 import com.dbs.dms.uibase.annotations.ApiModelProperty;
 11 import com.dbs.dms.translate.TranslateBean;
 12 import com.dbs.dms.translate.TranslateBeanSerializer;
 13 /**
 14  * 接口配置表
 15  * 实体类对应的数据表为:  t_m_db_interface_config
 16  * @author $Author
 17  * @date Tue Apr 17 11:21:18 GMT+08:00 2018
 18  */
 19 @ApiModel(value ="DbInterfaceConfigBean")
 20 public class DbInterfaceConfigBean extends BaseBean {
 21     public static final String ATTR_INTERFACE_CONFIG_ID = "interfaceConfigId";
 22     public static final String ATTR_INTERFACE_CODE = "interfaceCode";
 23     public static final String ATTR_INTERFACE_NAME = "interfaceName";
 24     public static final String ATTR_FROM_SYSTEM = "fromSystem";
 25     public static final String ATTR_TO_SYSTEM = "toSystem";
 26     public static final String ATTR_FREQENCY = "freqency";
 27     public static final String ATTR_FREQENCY_TYPE = "freqencyType";
 28     public static final String ATTR_BEGIN_RUN_TIME = "beginRunTime";
 29     public static final String ATTR_NEXT_RUN_TIME = "nextRunTime";
 30     public static final String ATTR_TIME_RUN_YESTERDAY = "timeRunYesterday";
 31     public static final String ATTR_BEFORE_SQL = "beforeSql";
 32     public static final String ATTR_RUN_SQL = "runSql";
 33     public static final String ATTR_AFTER_SQL = "afterSql";
 34     
 35     @ApiModelProperty(value = "INTERFACE_CONFIG_ID",label = "接口配置",dataType="varchar(36)",length="36",primary=true,required=true)
 36     private String interfaceConfigId;
 37 
 38     @ApiModelProperty(value = "INTERFACE_CODE",label = "接口编码",dataType="varchar(50)",length="50")
 39     private String interfaceCode;
 40 
 41     @ApiModelProperty(value = "INTERFACE_NAME",label = "接口名称",dataType="varchar(200)",length="200")
 42     private String interfaceName;
 43 
 44     @ApiModelProperty(value = "FROM_SYSTEM",label = "源系统:DB0081",dataType="varchar(20)",length="20")
 45     private String fromSystem;
 46 
 47     @ApiModelProperty(value = "TO_SYSTEM",label = "目标系统:DB0081",dataType="varchar(20)",length="20")
 48     private String toSystem;
 49 
 50     @ApiModelProperty(value = "FREQENCY",label = "接口频率",dataType="integer",length="0")
 51     private Integer freqency;
 52 
 53     @ApiModelProperty(value = "FREQENCY_TYPE",label = "频率类别:DB0082",dataType="varchar(2)",length="2")
 54     private String freqencyType;
 55 
 56     @ApiModelProperty(value = "BEGIN_RUN_TIME",label = "开始运行时间",dataType="datetime",length="0")
 57     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 58     private Date beginRunTime;
 59 
 60     @ApiModelProperty(value = "NEXT_RUN_TIME",label = "下次运行时间",dataType="datetime",length="0")
 61     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 62     private Date nextRunTime;
 63 
 64     @ApiModelProperty(value = "TIME_RUN_YESTERDAY",label = "N点之前执行前一天数据",dataType="integer",length="0")
 65     private Integer timeRunYesterday;
 66 
 67     @ApiModelProperty(value = "CREATOR",label = "创建人",dataType="varchar(50)",length="50",comment="创建人")
 68     private String creator;
 69 
 70     @ApiModelProperty(value = "CREATED_DATE",label = "创建时间",dataType="datetime",length="0",comment="创建时间")
 71     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 72     private Date createdDate;
 73 
 74     @ApiModelProperty(value = "MODIFIER",label = "最后更新人员",dataType="varchar(50)",length="50",comment="最后更新人员")
 75     private String modifier;
 76 
 77     @ApiModelProperty(value = "LAST_UPDATED_DATE",label = "最后更新时间",dataType="timestamp",length="0",comment="最后更新时间")
 78     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 79     private Date lastUpdatedDate;
 80 
 81     @ApiModelProperty(value = "IS_ENABLE",label = "是否可用",dataType="varchar(2)",length="2",comment="是否可用 1启用,0禁用,2删除")
 82     private String isEnable;
 83 
 84     @ApiModelProperty(value = "UPDATE_CONTROL_ID",label = "并发控制字段",dataType="varchar(36)",length="36",comment="并发控制字段")
 85     private String updateControlId;
 86 
 87     public String getInterfaceConfigId() {
 88         return interfaceConfigId;
 89     }
 90 
 91     public void setInterfaceConfigId(String interfaceConfigId) {
 92         this.interfaceConfigId = interfaceConfigId;
 93     }
 94 
 95     public String getInterfaceCode() {
 96         return interfaceCode;
 97     }
 98 
 99     public void setInterfaceCode(String interfaceCode) {
100         this.interfaceCode = interfaceCode;
101     }
102 
103     public String getInterfaceName() {
104         return interfaceName;
105     }
106 
107     public void setInterfaceName(String interfaceName) {
108         this.interfaceName = interfaceName;
109     }
110 
111     public String getFromSystem() {
112         return fromSystem;
113     }
114 
115     public void setFromSystem(String fromSystem) {
116         this.fromSystem = fromSystem;
117     }
118 
119     public String getToSystem() {
120         return toSystem;
121     }
122 
123     public void setToSystem(String toSystem) {
124         this.toSystem = toSystem;
125     }
126 
127     public Integer getFreqency() {
128         return freqency;
129     }
130 
131     public void setFreqency(Integer freqency) {
132         this.freqency = freqency;
133     }
134 
135     public String getFreqencyType() {
136         return freqencyType;
137     }
138 
139     public void setFreqencyType(String freqencyType) {
140         this.freqencyType = freqencyType;
141     }
142 
143     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
144     public Date getBeginRunTime() {
145         return beginRunTime;
146     }
147 
148     public void setBeginRunTime(Date beginRunTime) {
149         this.beginRunTime = beginRunTime;
150     }
151 
152     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
153     public Date getNextRunTime() {
154         return nextRunTime;
155     }
156 
157     public void setNextRunTime(Date nextRunTime) {
158         this.nextRunTime = nextRunTime;
159     }
160 
161     public Integer getTimeRunYesterday() {
162         return timeRunYesterday;
163     }
164 
165     public void setTimeRunYesterday(Integer timeRunYesterday) {
166         this.timeRunYesterday = timeRunYesterday;
167     }
168 
169     public String getCreator() {
170         return creator;
171     }
172 
173     public void setCreator(String creator) {
174         this.creator = creator;
175     }
176 
177     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
178     public Date getCreatedDate() {
179         return createdDate;
180     }
181 
182     public void setCreatedDate(Date createdDate) {
183         this.createdDate = createdDate;
184     }
185 
186     public String getModifier() {
187         return modifier;
188     }
189 
190     public void setModifier(String modifier) {
191         this.modifier = modifier;
192     }
193 
194     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
195     public Date getLastUpdatedDate() {
196         return lastUpdatedDate;
197     }
198 
199     public void setLastUpdatedDate(Date lastUpdatedDate) {
200         this.lastUpdatedDate = lastUpdatedDate;
201     }
202 
203     public String getIsEnable() {
204         return isEnable;
205     }
206 
207     public void setIsEnable(String isEnable) {
208         this.isEnable = isEnable;
209     }
210 
211     public String getUpdateControlId() {
212         return updateControlId;
213     }
214 
215     public void setUpdateControlId(String updateControlId) {
216         this.updateControlId = updateControlId;
217     }
218 }
DbInterfaceConfigBean
  1 package com.dbs.dmsmdm.bean.simple;
  2 
  3 import com.dbs.dms.uibase.bean.BaseBean;
  4 import java.util.Date;
  5 
  6 import org.springframework.format.annotation.DateTimeFormat;
  7 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  8 import com.fasterxml.jackson.annotation.JsonFormat;
  9 import com.dbs.dms.uibase.annotations.ApiModel;
 10 import com.dbs.dms.uibase.annotations.ApiModelProperty;
 11 import com.dbs.dms.translate.TranslateBean;
 12 import com.dbs.dms.translate.TranslateBeanSerializer;
 13 /**
 14  * 接口运行日志
 15  * 实体类对应的数据表为:  t_m_db_interface_log
 16  * @author $Author
 17  * @date Tue Apr 17 11:21:18 GMT+08:00 2018
 18  */
 19 @ApiModel(value ="DbInterfaceLogBean")
 20 public class DbInterfaceLogBean extends BaseBean {
 21     public static final String ATTR_IFTERFACE_LOG_ID = "ifterfaceLogId";
 22     public static final String ATTR_INTERFACE_CODE = "interfaceCode";
 23     public static final String ATTR_INTERFACE_NAME = "interfaceName";
 24     public static final String ATTR_FROM_SYSTEM = "fromSystem";
 25     public static final String ATTR_TO_SYSTEM = "toSystem";
 26     public static final String ATTR_ERROR_TIME = "errorTime";
 27     public static final String ATTR_ERROR_MSG = "errorMsg";
 28     
 29     @ApiModelProperty(value = "IFTERFACE_LOG_ID",label = "IFTERFACE_LOG_ID",dataType="varchar(36)",length="36",primary=true,required=true,comment="ID")
 30     private String ifterfaceLogId;
 31 
 32     @ApiModelProperty(value = "INTERFACE_CODE",label = "接口编码",dataType="varchar(50)",length="50",comment="接口编码")
 33     private String interfaceCode;
 34 
 35     @ApiModelProperty(value = "INTERFACE_NAME",label = "接口名称",dataType="varchar(200)",length="200",comment="接口名称")
 36     private String interfaceName;
 37 
 38     @ApiModelProperty(value = "FROM_SYSTEM",label = "源系统",dataType="varchar(20)",length="20",comment="源系统:DB0081")
 39     private String fromSystem;
 40 
 41     @ApiModelProperty(value = "TO_SYSTEM",label = "目标系统",dataType="varchar(20)",length="20",comment="目标系统:DB0081")
 42     private String toSystem;
 43 
 44     @ApiModelProperty(value = "ERROR_TIME",label = "错误时间",dataType="datetime",length="0",comment="错误时间")
 45     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 46     private Date errorTime;
 47 
 48     @ApiModelProperty(value = "CREATOR",label = "创建人",dataType="varchar(50)",length="50",comment="创建人")
 49     private String creator;
 50 
 51     @ApiModelProperty(value = "CREATED_DATE",label = "创建时间",dataType="datetime",length="0",comment="创建时间")
 52     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 53     private Date createdDate;
 54 
 55     @ApiModelProperty(value = "MODIFIER",label = "最后更新人员",dataType="varchar(50)",length="50",comment="最后更新人员")
 56     private String modifier;
 57 
 58     @ApiModelProperty(value = "LAST_UPDATED_DATE",label = "最后更新时间",dataType="timestamp",length="0",comment="最后更新时间")
 59     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 60     private Date lastUpdatedDate;
 61 
 62     @ApiModelProperty(value = "IS_ENABLE",label = "是否可用",dataType="varchar(2)",length="2",comment="是否可用 1启用,0禁用")
 63     private String isEnable;
 64 
 65     @ApiModelProperty(value = "UPDATE_CONTROL_ID",label = "并发控制字段",dataType="varchar(36)",length="36",comment="并发控制字段")
 66     private String updateControlId;
 67 
 68     @ApiModelProperty(value = "ERROR_MSG",label = "错误信息",dataType="text",length="0",comment="记录数据库报错信息")
 69     private String errorMsg;
 70 
 71     public String getIfterfaceLogId() {
 72         return ifterfaceLogId;
 73     }
 74 
 75     public void setIfterfaceLogId(String ifterfaceLogId) {
 76         this.ifterfaceLogId = ifterfaceLogId;
 77     }
 78 
 79     public String getInterfaceCode() {
 80         return interfaceCode;
 81     }
 82 
 83     public void setInterfaceCode(String interfaceCode) {
 84         this.interfaceCode = interfaceCode;
 85     }
 86 
 87     public String getInterfaceName() {
 88         return interfaceName;
 89     }
 90 
 91     public void setInterfaceName(String interfaceName) {
 92         this.interfaceName = interfaceName;
 93     }
 94 
 95     public String getFromSystem() {
 96         return fromSystem;
 97     }
 98 
 99     public void setFromSystem(String fromSystem) {
100         this.fromSystem = fromSystem;
101     }
102 
103     public String getToSystem() {
104         return toSystem;
105     }
106 
107     public void setToSystem(String toSystem) {
108         this.toSystem = toSystem;
109     }
110 
111     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
112     public Date getErrorTime() {
113         return errorTime;
114     }
115 
116     public void setErrorTime(Date errorTime) {
117         this.errorTime = errorTime;
118     }
119 
120     public String getCreator() {
121         return creator;
122     }
123 
124     public void setCreator(String creator) {
125         this.creator = creator;
126     }
127 
128     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
129     public Date getCreatedDate() {
130         return createdDate;
131     }
132 
133     public void setCreatedDate(Date createdDate) {
134         this.createdDate = createdDate;
135     }
136 
137     public String getModifier() {
138         return modifier;
139     }
140 
141     public void setModifier(String modifier) {
142         this.modifier = modifier;
143     }
144 
145     @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
146     public Date getLastUpdatedDate() {
147         return lastUpdatedDate;
148     }
149 
150     public void setLastUpdatedDate(Date lastUpdatedDate) {
151         this.lastUpdatedDate = lastUpdatedDate;
152     }
153 
154     public String getIsEnable() {
155         return isEnable;
156     }
157 
158     public void setIsEnable(String isEnable) {
159         this.isEnable = isEnable;
160     }
161 
162     public String getUpdateControlId() {
163         return updateControlId;
164     }
165 
166     public void setUpdateControlId(String updateControlId) {
167         this.updateControlId = updateControlId;
168     }
169 
170     public String getErrorMsg() {
171         return errorMsg;
172     }
173 
174     public void setErrorMsg(String errorMsg) {
175         this.errorMsg = errorMsg;
176     }
177 }
DbInterfaceLogBean

二、系统定时任务类(InitQuartzJob)

参考地址:https://blog.csdn.net/u014723529/article/details/51291289

1、Quartz工具版本说明

spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。 

原因:spring对于quartz的支持实现,org.springframework.scheduling.quartz.CronTriggerBean继承了org.quartz.CronTriggerquartz1.x系列中org.quartz.CronTrigger是个类,而在quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器(trigger

开发所选版本:spring5.x系列quartz以及quartz-jobs版本2.3.0

2、开发流程

①、类实现ApplicationContextAware接口,重写方法,获取上下文application,写一个init()方法初始化;

②、在初始化方法中通过上下文获取调度工厂SchedulerFactoryBean;

③、通过调度工厂生产调度Scheduler

④、获取数据库资源;

⑤、通过单表类的服务层访问接口配置表,得到集合;

⑥、遍历接口配置集合,忽略掉null的对象和状态为不可用的对象(1)

⑦、根据接口对象的接口编码得到触发器键TriggerKey;

⑧、然后用调度构建出触发器CronTrigger,相当于在spring配置文件中定义的bean id=”myTrigger”;

⑨、再根据接口类型、接口频率、运行日期、运行时间生成Cron表达式;

⑩、当触发器不存在时,将执行任务的类绑定给JobDetail,并将需要传递的参数放入到JobDetailMap中;

⑩①、用表达式调度构建器生成新的触发器,将JobDetail和触发器添加到调度中,到此已完成动态调度任务的添加;

⑩②、如果触发器已经存在,则只需要用表达式调度构建器生成新的触发器,将新触发器添加到调度中。

代码如下:

  1 package com.dbs.stat.quartz;
  2 
  3 import java.util.Calendar;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 
  8 import javax.sql.DataSource;
  9 
 10 import org.quartz.CronScheduleBuilder;
 11 import org.quartz.CronTrigger;
 12 import org.quartz.JobBuilder;
 13 import org.quartz.JobDataMap;
 14 import org.quartz.JobDetail;
 15 import org.quartz.Scheduler;
 16 import org.quartz.SchedulerException;
 17 import org.quartz.TriggerBuilder;
 18 import org.quartz.TriggerKey;
 19 import org.slf4j.Logger;
 20 import org.slf4j.LoggerFactory;
 21 import org.springframework.beans.BeansException;
 22 import org.springframework.beans.factory.annotation.Autowired;
 23 import org.springframework.context.ApplicationContext;
 24 import org.springframework.context.ApplicationContextAware;
 25 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 26 import org.springframework.stereotype.Component;
 27 
 28 import com.dbs.dmsmdm.bean.simple.DbInterfaceConfigBeanWithBLOBs;
 29 import com.dbs.dmsmdm.service.simple.DbInterfaceConfigBeanService;
 30 import com.dbs.dmsmdm.service.simple.DbInterfaceLogBeanService;
 31 
 32 /**
 33  * 时间调度类,动态添加定时任务
 34  * 
 35  * @author yeting
 36  *
 37  */
 38 @Component
 39 public class InitQuartzJob implements ApplicationContextAware {
 40     private static final Logger logger = LoggerFactory.getLogger(InitQuartzJob.class);// 日志
 41     private static ApplicationContext applicationContext;// 上下文
 42     public static SchedulerFactoryBean schedulerFactoryBean = null;// 调度工厂
 43 
 44     @Autowired
 45     DbInterfaceConfigBeanService dbInterfaceConfigBeanService;//注入接口配置表的服务层
 46     
 47     @Autowired
 48     DbInterfaceLogBeanService dbInterfaceLogBeanService;//注入接口运行日志表的服务层
 49 
 50     @Override
 51     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 52         if (null == this.applicationContext) {
 53             this.applicationContext = applicationContext;// 获取上下文
 54         }
 55 
 56     }
 57 
 58     /**
 59      * 初始化方法
 60      */
 61     public void init() {
 62         DataSource dataSource = (DataSource)applicationContext.getBean("dataSource");//连接数据库的资源
 63         schedulerFactoryBean = (SchedulerFactoryBean) applicationContext.getBean(SchedulerFactoryBean.class);// 通过上下文获取调度工厂
 64         Scheduler scheduler = schedulerFactoryBean.getScheduler();// 通过调度工厂获取Scheduler
 65         try {
 66             logger.info(scheduler.getSchedulerName());// 输出日志信息
 67         } catch (SchedulerException e1) {
 68             e1.printStackTrace();
 69         }
 70 
 71         List<DbInterfaceConfigBeanWithBLOBs> interfaceslist = dbInterfaceConfigBeanService.selectAllBean();//查询接口配置表
 72         for (DbInterfaceConfigBeanWithBLOBs interfaceConfigBean : interfaceslist) {//遍历集合
 73             if (null == interfaceConfigBean) {
 74                 continue;//空对象时进入下一轮循环
 75             }
 76             if (!"1".equals(interfaceConfigBean.getIsEnable())){
 77                 continue;//状态为不可用时进入下一轮循环
 78             }
 79             
 80             logger.debug(scheduler + "...........................................add");// 输出日志信息
 81             TriggerKey triggerKey = TriggerKey.triggerKey(interfaceConfigBean.getInterfaceConfigId());// 根据id得到触发器名
 82             CronTrigger trigger=null;
 83             try {
 84                 trigger = (CronTrigger) scheduler.getTrigger(triggerKey);// 获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
 85             } catch (SchedulerException e1) {
 86                 e1.printStackTrace();
 87             }
 88             
 89             Map<String,Object> map=new HashMap<>();//将需要传递给执行任务类的数据放入map中
 90             map.put("interfaceConfigBean", interfaceConfigBean);
 91             map.put("dbInterfaceConfigBeanService", dbInterfaceConfigBeanService);
 92             map.put("dbInterfaceLogBeanService", dbInterfaceLogBeanService);
 93             map.put("dataSource", dataSource);
 94             
 95             //利用工具类根据接口属性得到表达式
 96             String CronExpression=QuartzUtil.getCronExpression(interfaceConfigBean.getFreqencyType(), 
 97                                 interfaceConfigBean.getFreqency(),
 98                                 QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime()));
 99             
100             if (null == trigger) {//如果触发器不存在,就创建一个
101                 Class clazz =QuartzJobFactory.class;//执行计划任务的类
102                 
103                 JobDetail jobDetail = JobBuilder.newJob(clazz)
104                         .withIdentity(interfaceConfigBean.getInterfaceCode())
105                         .usingJobData(new JobDataMap(map))
106                         .build();// 任务执行类,任务名,数据数组
107                 
108                 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(CronExpression);//表达式调度构建器
109                 trigger = TriggerBuilder.newTrigger()//构建新的trigger
110                         .withIdentity(interfaceConfigBean.getInterfaceConfigId())
111                         .withSchedule(scheduleBuilder)
112                         .build();
113                 try {
114                     scheduler.scheduleJob(jobDetail, trigger);//设置调度任务
115                 } catch (SchedulerException e) {
116                     e.printStackTrace();
117                 }
118             } else {//如果触发器已存在,那么更新相应的定时设置;
119                 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(CronExpression);
120                 trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
121                         .usingJobData(new JobDataMap(map))
122                         .withSchedule(scheduleBuilder).build();//按新的cronExpression表达式重新构建trigger;
123                 try {
124                     scheduler.rescheduleJob(triggerKey, trigger);//按新的trigger重新设置job执行
125                 } catch (SchedulerException e) {
126                     e.printStackTrace();
127                 }
128             }
129             
130             interfaceConfigBean.setNextRunTime(QuartzUtil.getBeginRunTime(Calendar.getInstance(),interfaceConfigBean.getFreqencyType(),
131                     interfaceConfigBean.getFreqency(),QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime())));
132             if(dbInterfaceConfigBeanService.updateOneBean(interfaceConfigBean)==1){//更新可运行接口的下次执行时间
133                 logger.info("{}接口的下次执行时间为:{}",interfaceConfigBean.getInterfaceCode(), 
134                         interfaceConfigBean.getNextRunTime());
135             }
136         }
137     }
138 }
InitQuartzJob

三、计划任务执行类(QuartzJobFactory)

1、开发流程

①、类实现Job接口,写一个execute方法,定时任务启动时会执行该方法;

②、在方法中接收JobDetail传过来的参数,包括数据库资源、接口配置对象信息等;

③、用数据库资源得到数据库连接,用JDBC技术执行sql语句,并将异常信息写入接口日志表;

④、更新数据库中对应接口对象的下次执行时间,关闭资源;

2、执行说明

①、可用状态不为‘1’的接口不会执行,且其下次执行时间会为null

②、使用trim()方法去掉sql语句前后空格,程序只能识别以‘create’、‘insert’、‘update’、‘delete’开头的sql语句。

③、sql识别通不过的接口或报异常的接口的可用状态会被修改为‘0’,下次执行时间会被修改为null

代码如下:

  1 package com.dbs.stat.quartz;
  2 
  3 import java.sql.Connection;
  4 import java.sql.ResultSet;
  5 import java.sql.SQLException;
  6 import java.sql.Statement;
  7 import java.util.Calendar;
  8 import java.util.Date;
  9 
 10 import javax.sql.DataSource;
 11 
 12 import org.apache.commons.lang3.StringUtils;
 13 import org.quartz.Job;
 14 import org.quartz.JobDataMap;
 15 import org.quartz.JobExecutionContext;
 16 import org.quartz.JobExecutionException;
 17 import org.slf4j.Logger;
 18 import org.slf4j.LoggerFactory;
 19 import org.springframework.stereotype.Component;
 20 
 21 import com.dbs.dmsmdm.bean.simple.DbInterfaceConfigBeanWithBLOBs;
 22 import com.dbs.dmsmdm.bean.simple.DbInterfaceLogBean;
 23 import com.dbs.dmsmdm.service.simple.DbInterfaceConfigBeanService;
 24 import com.dbs.dmsmdm.service.simple.DbInterfaceLogBeanService;
 25 
 26 /**
 27  * 计划任务执行类 
 28  * 
 29  * @author yeting
 30  *
 31  */
 32 @Component
 33 public class QuartzJobFactory implements Job{
 34     public static final Logger logger = LoggerFactory.getLogger(QuartzJobFactory.class);
 35 
 36     /**
 37      * 任务执行方法
 38      */
 39     public void execute(JobExecutionContext context) throws JobExecutionException {
 40         Connection conn = null;
 41         Statement st=null;
 42         ResultSet rs=null;
 43         JobDataMap jobDataMap=context.getJobDetail().getJobDataMap();
 44         DataSource dataSource = (DataSource) jobDataMap.get("dataSource");//接收数据库连接资源
 45         DbInterfaceConfigBeanService dbInterfaceConfigBeanService=(DbInterfaceConfigBeanService) jobDataMap.get("dbInterfaceConfigBeanService");
 46         DbInterfaceLogBeanService dbInterfaceLogBeanService=(DbInterfaceLogBeanService) jobDataMap.get("dbInterfaceLogBeanService");
 47         DbInterfaceConfigBeanWithBLOBs interfaceConfigBean = (DbInterfaceConfigBeanWithBLOBs) jobDataMap.get("interfaceConfigBean");
 48         DbInterfaceLogBean interfaceLogBean=(DbInterfaceLogBean) QuartzUtil.getInitializedObject(new DbInterfaceLogBean(), 
 49                 interfaceConfigBean, 1);//初始化日志对象
 50         String beforeSql=interfaceConfigBean.getBeforeSql();
 51         String runSql=interfaceConfigBean.getRunSql();
 52         String afterSql=interfaceConfigBean.getAfterSql();
 53         Calendar calendar=Calendar.getInstance();//任务启动时间日历类
 54         
 55         logger.info("{}任务启动中。。。",interfaceConfigBean.getInterfaceCode());
 56         if(!"1".equals(interfaceConfigBean.getIsEnable())){
 57             return;//状态不可用就结束方法
 58         }
 59         logger.info("{}接口已启动",interfaceConfigBean.getInterfaceCode());
 60         
 61         boolean flag=true;
 62         try {
 63             conn= dataSource.getConnection();
 64             conn.setAutoCommit(false);//打开事务边界,就是取消自动提交,改为手动
 65             st=conn.createStatement();
 66             
 67 /*            st.addBatch("sqls[i]");
 68             st.executeBatch();*/
 69             
 70             if(StringUtils.isNotBlank(beforeSql)){
 71                 beforeSql=beforeSql.trim();
 72                 if(QuartzUtil.getBooleanByCheckSql(beforeSql)){
 73                     String sqls[]=beforeSql.split(";");
 74                     for(int i=0;i<sqls.length;i++){
 75                         sqls[i]=QuartzUtil.getSqlByTimeRunYesterday(sqls[i],interfaceConfigBean.getTimeRunYesterday());
 76                         st.addBatch(sqls[i]);
 77                     }
 78                     logger.debug("{}接口 beforeSql执行中,共{}条",interfaceConfigBean.getInterfaceCode(),sqls.length);
 79                     st.executeBatch();
 80                 }else{
 81                     flag=false;
 82                     interfaceLogBean.setErrorMsg("beforeSql ERROR");
 83                     dbInterfaceLogBeanService.insertSystemLog(interfaceLogBean);
 84                     return;
 85                 }
 86             }
 87             
 88             if(StringUtils.isNotBlank(runSql)){//判断语句是否为空
 89                 runSql=runSql.trim();//去掉前后空格
 90                 if(QuartzUtil.getBooleanByCheckSql(runSql)){//判断语句是否可用
 91                     String sqls[]=runSql.split(";");//将多条语句按 ;切分开
 92                     for(int i=0;i<sqls.length;i++){
 93                         sqls[i]=QuartzUtil.getSqlByTimeRunYesterday(sqls[i],interfaceConfigBean.getTimeRunYesterday());
 94                         st.addBatch(sqls[i]);// 将所有的SQL语句添加到Statement中进行批处理
 95                     }
 96                     logger.debug("{}接口 runSql执行中,共{}条",interfaceConfigBean.getInterfaceCode(),sqls.length);// 输出日志信息
 97                     st.executeBatch();// 一次执行多条SQL语句
 98                 }else{
 99                     flag=false;
100                     interfaceLogBean.setErrorMsg("runSql ERROR");
101                     dbInterfaceLogBeanService.insertSystemLog(interfaceLogBean);//将错误信息插入到日志表
102                     return;
103                 }
104             }
105             
106             if(StringUtils.isNotBlank(afterSql)){
107                 afterSql=afterSql.trim();
108                 if(QuartzUtil.getBooleanByCheckSql(afterSql)){
109                     String sqls[]=afterSql.split(";");
110                     for(int i=0;i<sqls.length;i++){
111                         sqls[i]=QuartzUtil.getSqlByTimeRunYesterday(sqls[i],interfaceConfigBean.getTimeRunYesterday());
112                         st.addBatch(sqls[i]);
113                     }
114                     logger.debug("{}接口 afterSql执行中,共{}条",interfaceConfigBean.getInterfaceCode(),sqls.length);
115                     st.executeBatch();
116                 }else{
117                     flag=false;
118                     interfaceLogBean.setErrorMsg("afterSql ERROR");
119                     dbInterfaceLogBeanService.insertSystemLog(interfaceLogBean);
120                     return;
121                 }
122             }
123             
124             if(flag==true){
125                 interfaceLogBean.setErrorMsg("SUCCESS");
126                 dbInterfaceLogBeanService.insertSystemLog(interfaceLogBean);//将成功信息插入到日志表
127             }
128             
129             conn.commit();//提交事务,正常结束
130         } catch (Exception e) {//捕获所有异常
131             e.printStackTrace();
132             try {
133                 conn.rollback();//有异常发生就回滚事务,是为了保证释放锁
134             } catch (SQLException e1) {
135                 e1.printStackTrace();
136             }
137             
138             flag=false;
139             interfaceLogBean.setErrorMsg("ERROR:"+e.getMessage());
140             dbInterfaceLogBeanService.insertSystemLog(interfaceLogBean);//将错误信息插入到日志表
141         } finally {
142             if(flag==true){//利用工具类根据接口属性,设置接口的下次运行时间 
143                 interfaceConfigBean.setNextRunTime(QuartzUtil.getNextRunTime(calendar,
144                                             interfaceConfigBean.getFreqencyType(),interfaceConfigBean.getFreqency(),
145                                             QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime())));
146             }else{
147                 interfaceConfigBean.setIsEnable("0");//将接口状态设置为不可用
148                 interfaceConfigBean.setNextRunTime(null);//接口的下次运行时间为null
149             }
150 
151             if(dbInterfaceConfigBeanService.updateOneBean(interfaceConfigBean)==1){//更新接口对象
152                 logger.debug("{}接口信息已更新,下次执行时间:{}",interfaceConfigBean.getInterfaceCode(), 
153                         interfaceConfigBean.getNextRunTime());    
154             }else{
155                 logger.debug("{}接口信息更新失败",interfaceConfigBean.getInterfaceCode());
156             }
157             
158             QuartzUtil.closeAll(conn, st, rs);//关闭数据库资源
159             logger.info("{}接口已关闭",interfaceConfigBean.getInterfaceCode());
160         }
161     }
162 }
QuartzJobFactory

四、工具类(QuartzUtil)

本人表示写得很烂,工具类代码里面涉及到业务的代码请忽略。。。

  1 package com.dbs.stat.quartz;
  2 
  3 import java.sql.Connection;
  4 import java.sql.ResultSet;
  5 import java.sql.SQLException;
  6 import java.sql.Statement;
  7 import java.text.SimpleDateFormat;
  8 import java.util.Calendar;
  9 import java.util.Date;
 10 
 11 import com.dbs.dmsmdm.bean.simple.DbInterfaceConfigBeanWithBLOBs;
 12 import com.dbs.dmsmdm.bean.simple.DbInterfaceLogBean;
 13 
 14 /**
 15  * 工具类,优化代码结构
 16  * @author yeting
 17  *
 18  */
 19 public class QuartzUtil {
 20     
 21     /**
 22      * 将日期对象转换为日时分秒数组
 23      * @author yeting
 24      * @param beginRunTime 日期对象
 25      * @return 返回日时分秒数组
 26      */
 27     public static int[] getFormatTime(Date beginRunTime){
 28         int runtime[]=null;
 29         String Hms="";
 30         if(null != beginRunTime){
 31             SimpleDateFormat sdf=new SimpleDateFormat("dd HH:mm:ss");
 32             Hms=sdf.format(beginRunTime);
 33             
 34             runtime=new int[4];
 35             runtime[0]=Integer.valueOf(Hms.substring(0, 2));
 36             runtime[1]=Integer.valueOf(Hms.substring(3, 5));
 37             runtime[2]=Integer.valueOf(Hms.substring(6, 8));
 38             runtime[3]=Integer.valueOf(Hms.substring(9));
 39         }else{
 40             runtime=new int[]{1,0,0,0};//默认值
 41         }
 42         return runtime;
 43     }
 44     
 45     /**
 46      * 根据接口属性生成表达式
 47      * @author yeting
 48      * @param freqencyType 频率类型
 49      * @param freqency 频率值
 50      * @param runTime 日时分秒数组
 51      * @return 返回表达式
 52      */
 53     public static String getCronExpression(String freqencyType,int freqency,int[] runTime){
 54         String CronExpression="";//根据接口的执行频率写表达式
 55         switch(freqencyType){
 56             case "1"://从某分某秒开始,之后每几分钟/次
 57                 CronExpression=runTime[3]+" "+runTime[2]+"/"+(freqency%60!=0?freqency%60:59)+" * * * ?";
 58                 break;
 59             case "2"://从某时某分某秒开始,之后每几小时/次
 60                 CronExpression=runTime[3]+" "+runTime[2]+" "+runTime[1]+"/"+(freqency%24!=0?freqency%24:23)+" * * ?";
 61                 break;
 62             case "3"://某时某分某秒固定执行,每几天/次
 63                 CronExpression=runTime[3]+" "+runTime[2]+" "+runTime[1]+" */"+(freqency%31!=0?freqency%31:31)+" * ?";
 64                 break;
 65             case "4"://某天某时某分某秒固定执行,每几月/次
 66                 CronExpression=runTime[3]+" "+runTime[2]+" "+runTime[1]+" "+runTime[0]+" */"+(freqency%12!=0?freqency%12:12)+" ?";
 67                 break;
 68             default://默认每月1号凌晨00:00:00执行
 69                 CronExpression="0 0 0 1 * ?";
 70                 break;
 71         }
 72         return CronExpression;
 73     }
 74     
 75     /**
 76      * 计算任务的第一次运行时间
 77      * @author yeting
 78      * @param calendar 当前时间日历类
 79      * @param freqencyType 频率类型
 80      * @param freqency 频率
 81      * @param runTime 日时分秒数组
 82      * @return 返回日期对象
 83      */
 84     public static Date getBeginRunTime(Calendar calendar,String freqencyType,int freqency,int[] runTime){
 85         switch (freqencyType) {
 86         case "1"://分钟/次
 87             freqency=(freqency%60!=0?freqency%60:59);
 88             for(int i=0;i<59;i++){
 89                 if(runTime[2]+freqency*i<60){
 90                     if(runTime[2]+freqency*i>=calendar.get(Calendar.MINUTE)){//如果现在分钟小于下次运行分钟,那么取下次运行分钟
 91                         calendar.set(Calendar.MINUTE, runTime[2]+freqency*i);
 92                         break;
 93                     }
 94                     if(runTime[2]+freqency*i==calendar.get(Calendar.MINUTE)){//如果现在分钟等于下次运行分钟
 95                         if(runTime[3]>=calendar.get(Calendar.SECOND)){//如果现在秒钟小于等于开始运行秒钟,那么取开始运行分钟
 96                             calendar.set(Calendar.MINUTE, runTime[2]+freqency*i);
 97                             break;
 98                         }    
 99                     }
100                 }else{//否则就到下一个小时
101                     calendar.set(Calendar.MINUTE, runTime[2]);
102                     calendar.add(Calendar.HOUR_OF_DAY, 1);
103                     break;
104                 }
105             }
106             calendar.set(Calendar.SECOND, runTime[3]);
107             break;
108         case "2"://小时/次
109             freqency=(freqency%24!=0?freqency%24:23);
110             for(int i=0;i<24;i++){
111                 if(runTime[1]+freqency*i<24){
112                     if(runTime[1]+freqency*i>calendar.get(Calendar.HOUR_OF_DAY)){
113                         calendar.set(Calendar.HOUR_OF_DAY, runTime[1]+freqency*i);
114                         break;
115                     }
116                     if(runTime[1]+freqency*i==calendar.get(Calendar.HOUR_OF_DAY)){
117                         if(runTime[2]>calendar.get(Calendar.MINUTE)){
118                             calendar.set(Calendar.HOUR_OF_DAY, runTime[1]+freqency*i);
119                             break;
120                         }
121                         if(runTime[2]==calendar.get(Calendar.MINUTE)){
122                             if(runTime[3]>=calendar.get(Calendar.SECOND)){
123                                 calendar.set(Calendar.HOUR_OF_DAY, runTime[1]+freqency*i);
124                                 break;
125                             }
126                         }    
127                     }
128                 }else{
129                     calendar.set(Calendar.HOUR_OF_DAY, runTime[1]);
130                     calendar.add(Calendar.DAY_OF_MONTH, 1);
131                     break;
132                 }
133             }
134             calendar.set(Calendar.SECOND, runTime[3]);
135             calendar.set(Calendar.MINUTE, runTime[2]);
136             break;
137         case "3"://天/次
138             Boolean b=false;
139             if(runTime[1]>calendar.get(Calendar.HOUR_OF_DAY)){
140                 b=true;
141             }
142             if(runTime[1]==calendar.get(Calendar.HOUR_OF_DAY)){
143                 if(runTime[2]>calendar.get(Calendar.MINUTE)){
144                     b=true;
145                 }
146                 if(runTime[2]==calendar.get(Calendar.MINUTE)){
147                     if(runTime[3]>=calendar.get(Calendar.SECOND)){
148                         b=true;
149                     }
150                 }    
151             }
152             if(b==false){
153                 calendar.add(Calendar.DAY_OF_MONTH,1);
154             }
155             calendar.set(Calendar.HOUR_OF_DAY, runTime[1]);
156             calendar.set(Calendar.MINUTE, runTime[2]);
157             calendar.set(Calendar.SECOND, runTime[3]);
158             break;
159         case "4"://月/次
160             Boolean bb=false;
161             if(runTime[0]>calendar.get(Calendar.DAY_OF_MONTH)){
162                 bb=true;
163             }
164             if(runTime[0]==calendar.get(Calendar.DAY_OF_MONTH)){
165                 if(runTime[1]>calendar.get(Calendar.HOUR_OF_DAY)){
166                     bb=true;
167                 }
168                 if(runTime[1]==calendar.get(Calendar.HOUR_OF_DAY)){
169                     if(runTime[2]>calendar.get(Calendar.MINUTE)){
170                         bb=true;
171                     }
172                     if(runTime[2]==calendar.get(Calendar.MINUTE)){
173                         if(runTime[3]>=calendar.get(Calendar.SECOND)){
174                             bb=true;
175                         }
176                     }    
177                 }
178             }
179             if(bb==false){
180                 calendar.add(Calendar.MONTH,1);
181             }
182             calendar.set(Calendar.DAY_OF_MONTH,runTime[0]);
183             calendar.set(Calendar.HOUR_OF_DAY, runTime[1]);
184             calendar.set(Calendar.MINUTE, runTime[2]);
185             calendar.set(Calendar.SECOND, runTime[3]);
186             break;
187         default:
188             calendar.add(Calendar.MONTH,1);
189             break;
190         }
191         
192         Date date=calendar.getTime(); 
193         return date;
194     }
195     
196     /**
197      * 任务启动后计算下次运行时间
198      * @author yeting
199      * @param Calendar 任务启动时的时间日历类
200      * @param freqencyType 频率类型
201      * @param freqency 频率
202      * @param runTime 日时分秒数组
203      * @return 返回日期对象
204      */
205     public static Date getNextRunTime(Calendar calendar,String freqencyType,int freqency,int[] runTime){
206         switch (freqencyType) {
207         case "1"://分钟/次
208             freqency=(freqency%60!=0?freqency%60:59);
209             if(calendar.get(Calendar.MINUTE)+freqency>59){//超过59分钟,就重新从某分开始
210                 calendar.add(Calendar.HOUR_OF_DAY, 1);
211                 calendar.set(Calendar.MINUTE, runTime[2]);
212             }else{//否则分钟加上频率值
213                 calendar.add(Calendar.MINUTE,freqency);
214             }
215             break;
216         case "2"://小时/次
217             freqency=(freqency%24!=0?freqency%24:23);
218             if(calendar.get(Calendar.HOUR_OF_DAY)+freqency>23){//超过23小时,就重新从某小时开始
219                 calendar.add(Calendar.DAY_OF_MONTH, 1);
220                 calendar.set(Calendar.HOUR_OF_DAY, runTime[1]);
221             }else{//否则小时加上频率值
222                 calendar.add(Calendar.HOUR_OF_DAY,freqency);
223             }
224             break;
225         case "3"://天/次
226             calendar.add(Calendar.DAY_OF_MONTH,(freqency%31!=0?freqency%31:31));
227             break;
228         case "4"://月/次
229             calendar.add(Calendar.MONTH,(freqency%12!=0?freqency%12:12));
230             break;
231         default:
232             calendar.add(Calendar.MONTH,1);
233             break;
234         }
235         
236         Date date=calendar.getTime(); 
237         return date;
238     }
239     
240     /**
241      * 初始化对象
242      * @param interfaceLogBean 日志对象
243      * @param interfaceConfigBean 接口对象
244      * @param type 类型  为1时初始化日志对象
245      * @return 返回对象
246      */
247     public static Object getInitializedObject(DbInterfaceLogBean interfaceLogBean,
248                                     DbInterfaceConfigBeanWithBLOBs interfaceConfigBean,int type){
249         Object obj=null;
250         switch(type){
251         case 1:
252             interfaceLogBean.setInterfaceCode(interfaceConfigBean.getInterfaceCode());
253             interfaceLogBean.setInterfaceName(interfaceConfigBean.getInterfaceName());
254             interfaceLogBean.setFromSystem(interfaceConfigBean.getFromSystem());
255             interfaceLogBean.setToSystem(interfaceConfigBean.getToSystem());
256             interfaceLogBean.setErrorTime(new Date());
257             interfaceLogBean.setCreatedDate(new Date());
258             interfaceLogBean.setCreator("System");
259             interfaceLogBean.setModifier("System");
260             interfaceLogBean.setLastUpdatedDate(new Date());
261             interfaceLogBean.setIsEnable("1");
262             obj=interfaceLogBean;
263             break;
264         }
265         return obj;
266     }
267     
268     /**
269      * 判断sql语句是否可用
270      * @param sql 语句
271      * @return 可用返回true,不可用返回false
272      */
273     public static boolean getBooleanByCheckSql(String sql){
274         boolean flag=false;
275         if(sql.length()>6){
276             if("create".equalsIgnoreCase(sql.substring(0, 6))||"insert".equalsIgnoreCase(sql.substring(0, 6))
277                     ||"update".equalsIgnoreCase(sql.substring(0, 6))||"delete".equalsIgnoreCase(sql.substring(0, 6))){
278                 flag=true;
279             }else{
280                 flag=false;
281             }
282         }
283         return flag;
284     }
285     
286     /**
287      * 根据临界时间点修改sql语句的时间字段(?)
288      * @param sql 语句
289      * @param timeRunYesterday 临界时间点
290      * @return 返回原sql或替换时间条件后的sql
291      */
292     public static String getSqlByTimeRunYesterday(String sql,int timeRunYesterday){
293         Calendar calendar=Calendar.getInstance();
294         String newTime="NOW()";
295         
296         if(timeRunYesterday>0 && timeRunYesterday<=23){
297             int nowHour=calendar.get(Calendar.HOUR_OF_DAY);
298             if(nowHour<timeRunYesterday){
299                 calendar.add(Calendar.DAY_OF_MONTH, -1);//当前时间小于临界时间点,就执行前一天的数据
300                 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
301                 newTime="'"+sdf.format(calendar.getTime())+"'";
302             }
303         }
304 
305         //替换时间条件
306         if(0<sql.indexOf("?") || 0<sql.indexOf("?")){
307             sql=sql.replace("?", newTime);
308             sql=sql.replace("?", newTime);
309         }
310         return sql;
311     }
312     
313     /**
314      * 关闭数据库资源
315      * @param conn 连接
316      * @param st 火箭车
317      * @param rs 结果集
318      */
319     public static void closeAll(Connection conn,Statement st,ResultSet rs){
320         if(rs!=null){
321             try {
322                 rs.close();
323             } catch (SQLException e) {
324                 e.printStackTrace();
325             }
326         }
327         if(st!=null){
328             try {
329                 st.close();
330             } catch (SQLException e) {
331                 e.printStackTrace();
332             }
333         }
334         if(conn!=null){
335             try {
336                 conn.close();
337             } catch (SQLException e) {
338                 e.printStackTrace();
339             }
340         }
341     }
342 }
QuartzUtil

五、配置文件

applicationContext.xml文件中注册上述(二+三)两个类,如下:

1 <!-- 初始化Scheduler -->
2     <bean id="schedulerFactoryBean"
3     class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />
4     <!-- 初始化job -->
5     <bean id="initQuartzJob" class="com.dbs.stat.quartz.InitQuartzJob"
6         init-method="init" lazy-init="false" />
配置文件

六、其他说明

1、页面输入设定的规则说明

(?代表执行频率)

①、?分钟/次:指定每?分钟执行一次。

详细解释:第一次启动时间为距离当前时间最近的下一分钟整,以后每隔?分钟启动一次;

②、?小时/次:指定每?小时执行一次。

详细解释: 第一次启动时间为距离当前时间最近的下一小时整,以后每隔?小时启动一次;

③、?天/次:指定每?天执行一次。

详细解释: 需要指定某个时间点(时分秒)

第一次启动时间为距离当前时间最近的下一个时间点,以后每隔?天启动一次;

④、?月/次:指定每?月执行一次。

详细解释: 需要指定某个时间点(天时分秒),目前只能指定1-28号执行,如果指定其他时间则默认为一个月的最后一天执行。

第一次启动时间为距离当前时间最近的下一个时间点,以后每隔?月启动一次;

⑤、?星期/次:暂未指定。

2、其他说明

如遇到复杂的定时任务,可在表中加一个Cron_Expression字段,直接写入表达式,在程序中直接获取该字段。

至此已完成 服务启动添加————————————————————————————————————————————————————

接下来是实现 手动添加 ————————————————————————————————————————————————————

七、实现手动添加的代码

控制层:

  1 package com.dbs.stat.controller.quartzmanager;
  2 
  3 import java.util.Calendar;
  4 import java.util.HashMap;
  5 import java.util.Map;
  6 
  7 import javax.sql.DataSource;
  8 
  9 import org.quartz.CronTrigger;
 10 import org.quartz.Scheduler;
 11 import org.quartz.SchedulerException;
 12 import org.quartz.SchedulerFactory;
 13 import org.quartz.TriggerKey;
 14 import org.quartz.impl.StdSchedulerFactory;
 15 import org.springframework.beans.factory.annotation.Autowired;
 16 import org.springframework.context.ApplicationContext;
 17 import org.springframework.context.support.ClassPathXmlApplicationContext;
 18 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 19 import org.springframework.stereotype.Controller;
 20 import org.springframework.web.bind.annotation.RequestMapping;
 21 import org.springframework.web.bind.annotation.ResponseBody;
 22 
 23 import com.dbs.dms.config.AppUtil;
 24 import com.dbs.dms.uibase.Result;
 25 import com.dbs.dms.uibase.controller.BaseController;
 26 import com.dbs.dmsmdm.bean.simple.DbInterfaceConfigBeanWithBLOBs;
 27 import com.dbs.dmsmdm.service.simple.DbInterfaceConfigBeanService;
 28 import com.dbs.dmsmdm.service.simple.DbInterfaceLogBeanService;
 29 import com.dbs.stat.quartz.QuartzJobFactory;
 30 import com.dbs.stat.quartz.QuartzUtil;
 31 import com.dbs.stat.service.quartzmanager.QuartzManagerService;
 32 
 33 
 34 /**
 35  *  手动管理定时任务
 36  *  
 37  * @author yeting
 38  *
 39  */
 40 @Controller
 41 @RequestMapping("/quartz/Manager")
 42 public class QuartzManagerController extends BaseController{
 43     
 44     @Autowired
 45     AppUtil appUtil;
 46     
 47     @Autowired
 48     DbInterfaceConfigBeanService dbInterfaceConfigBeanService;//注入接口配置表的服务层
 49     
 50     @Autowired
 51     DbInterfaceLogBeanService dbInterfaceLogBeanService;//注入接口运行日志表的服务层
 52     
 53     @Autowired
 54     QuartzManagerService quartzManagerService;//注入管理服务层
 55     
 56     /**
 57      * 修改定时任务
 58      */
 59     @RequestMapping("/change")
 60     @ResponseBody
 61     public Result changeJob(DbInterfaceConfigBeanWithBLOBs interfaceConfigBean) { 
 62         DataSource dataSource = (DataSource)appUtil.getBean("dataSource");;//获取数据库连接资源
 63         SchedulerFactoryBean schedulerFactoryBean=(SchedulerFactoryBean)appUtil.getBean(SchedulerFactoryBean.class);
 64         Map<String,Object> map=new HashMap<>();//将需要传递给执行任务类的数据放入map中
 65         map.put("interfaceConfigBean", interfaceConfigBean);
 66         map.put("dbInterfaceConfigBeanService", dbInterfaceConfigBeanService);
 67         map.put("dbInterfaceLogBeanService", dbInterfaceLogBeanService);
 68         map.put("dataSource", dataSource);
 69         
 70         Boolean b=false;
 71         CronTrigger trigger=null;
 72         Scheduler scheduler=null;
 73         int effect=0;
 74         try {
 75             scheduler= schedulerFactoryBean.getScheduler();
 76             TriggerKey triggerKey = TriggerKey.triggerKey(interfaceConfigBean.getInterfaceConfigId());//id为触发器名
 77             trigger = (CronTrigger) scheduler .getTrigger(triggerKey);  
 78         } catch (SchedulerException e) {
 79             e.printStackTrace();
 80         }
 81         
 82         
 83         switch(interfaceConfigBean.getIsEnable()){
 84         case "0"://启用操作
 85             interfaceConfigBean.setIsEnable("1");//将状态改为启用
 86             interfaceConfigBean.setNextRunTime(QuartzUtil.getBeginRunTime(Calendar.getInstance(),interfaceConfigBean.getFreqencyType(),
 87                     interfaceConfigBean.getFreqency(),QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime())));
 88             map.put("interfaceConfigBean", interfaceConfigBean);//将最新的对象传递过去!!很重要
 89             if (trigger == null) {  
 90                 b=quartzManagerService.addJob(interfaceConfigBean, QuartzJobFactory.class, map,scheduler);//新增 
 91             }else{
 92                 b=quartzManagerService.removeJob(interfaceConfigBean,scheduler);//停用
 93                 b=quartzManagerService.addJob(interfaceConfigBean, QuartzJobFactory.class, map,scheduler);//新增 
 94             }
 95             break; 
 96         case "1"://禁用操作
 97             if (trigger != null) {
 98                 interfaceConfigBean.setIsEnable("0");//将状态改为停用
 99                 interfaceConfigBean.setNextRunTime(null);
100                 b=quartzManagerService.removeJob(interfaceConfigBean,scheduler);//停用
101             }
102             break;
103         }
104 
105         if(b==false){//操作失败
106             effect=0;
107         }else{
108             effect=dbInterfaceConfigBeanService.updateOneBean(interfaceConfigBean);//操作成功更新运行接口
109         }
110         return buildDbResult(effect, null);
111     }
112 }
QuartzManagerController

服务层:

  1 package com.dbs.stat.service.quartzmanager;
  2 
  3 import java.util.Map;
  4 
  5 import org.quartz.CronScheduleBuilder;
  6 import org.quartz.CronTrigger;
  7 import org.quartz.JobBuilder;
  8 import org.quartz.JobDataMap;
  9 import org.quartz.JobDetail;
 10 import org.quartz.JobKey;
 11 import org.quartz.Scheduler;
 12 import org.quartz.SchedulerException;
 13 import org.quartz.SchedulerFactory;
 14 import org.quartz.Trigger;
 15 import org.quartz.TriggerBuilder;
 16 import org.quartz.TriggerKey;
 17 import org.quartz.impl.StdSchedulerFactory;
 18 import org.slf4j.Logger;
 19 import org.slf4j.LoggerFactory;
 20 import org.springframework.stereotype.Service;
 21 
 22 import com.dbs.dmsmdm.bean.simple.DbInterfaceConfigBeanWithBLOBs;
 23 import com.dbs.stat.controller.quartzmanager.QuartzManagerController;
 24 import com.dbs.stat.quartz.QuartzJobFactory;
 25 import com.dbs.stat.quartz.QuartzUtil;
 26 
 27 @Service
 28 public class QuartzManagerService {
 29     private static final Logger logger = LoggerFactory.getLogger(QuartzManagerController.class);// 日志
 30 
 31     /**
 32      * 新增一个运行任务
 33      * @param interfaceConfigBean 接口对象
 34      * @param clazz 执行任务的类
 35      * @param map 传递给执行任务对象的数据数组
 36      * @param scheduler 调度对象
 37      * @return 成功返回true,异常返回false
 38      */
 39     public Boolean addJob(DbInterfaceConfigBeanWithBLOBs interfaceConfigBean,Class clazz,Map<String,Object> map,Scheduler scheduler){
 40         Boolean b=true;
 41         try {     
 42             JobDetail jobDetail= JobBuilder.newJob(QuartzJobFactory.class)
 43                     .withIdentity(interfaceConfigBean.getInterfaceCode())
 44                     .setJobData(new JobDataMap(map))
 45                     .build();// 任务执行类,任务名,任务组,数据数组
 46             
 47             String CronExpression=QuartzUtil.getCronExpression(interfaceConfigBean.getFreqencyType(), 
 48                                 interfaceConfigBean.getFreqency(),
 49                                 QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime()));
 50             CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(CronExpression);//表达式调度构建器
 51             
 52             TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器
 53             triggerBuilder.withIdentity(interfaceConfigBean.getInterfaceConfigId());// 触发器名
 54             triggerBuilder.startNow();
 55             triggerBuilder.withSchedule(scheduleBuilder);// 触发器时间设定 
 56             
 57             CronTrigger trigger = (CronTrigger) triggerBuilder.build();//创建Trigger对象
 58             scheduler.scheduleJob(jobDetail, trigger);// 调度容器设置JobDetail和Trigger   
 59             if (!scheduler.isShutdown()) { // 启动  
 60                 scheduler.start();  
 61             }
 62             logger.debug("{}...........................运行任务添加成功",interfaceConfigBean.getInterfaceCode());// 输出日志信息
 63         } catch (SchedulerException e) {
 64             b=false;
 65             e.printStackTrace();
 66             logger.info("{}...........................运行任务添加失败",interfaceConfigBean.getInterfaceCode());// 输出日志信息
 67         }
 68         return b;
 69     }
 70     
 71     /**
 72      * 修改一个运行任务(不可用)
 73      * @param interfaceConfigBean 接口对象
 74      * @param trigger CronTrigger对象
 75      * @param map 数据集合
 76      * @param scheduler 调度对象
 77      * @return 成功返回true,异常返回false
 78      */
 79     public Boolean modifyJob(DbInterfaceConfigBeanWithBLOBs interfaceConfigBean,CronTrigger trigger,Map<String,Object> map,Scheduler scheduler){
 80         Boolean b=true;
 81         try {  
 82             TriggerKey triggerKey = TriggerKey.triggerKey(interfaceConfigBean.getInterfaceConfigId());// 根据id得到触发器名
 83             
 84             String CronExpression=QuartzUtil.getCronExpression(interfaceConfigBean.getFreqencyType(), 
 85                     interfaceConfigBean.getFreqency(),
 86                     QuartzUtil.getFormatTime(interfaceConfigBean.getBeginRunTime()));
 87             CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(CronExpression);//表达式调度构建器
 88             
 89             /*trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
 90                     .usingJobData(new JobDataMap(map))
 91                     .withSchedule(scheduleBuilder).build();//按新的cronExpression表达式重新构建trigger;
 92 */            
 93             JobKey jobKey = trigger.getJobKey();
 94             JobDetail detail = scheduler.getJobDetail(jobKey);
 95             detail.getJobDataMap().put("interfaceConfigBean", interfaceConfigBean);//重新给JobDetail中的数据赋值
 96             
 97             scheduler.rescheduleJob(triggerKey, trigger);//修改
 98             logger.debug("{}...........................运行任务修改成功",interfaceConfigBean.getInterfaceCode());// 输出日志信息
 99         } catch (SchedulerException e) {
100             b=false;
101             e.printStackTrace();
102             logger.info("{}...........................运行任务修改失败",interfaceConfigBean.getInterfaceCode());// 输出日志信息
103         }
104         return b;
105     }
106     
107     /**
108      * 移除一个运行任务
109      * @param interfaceConfigBean 接口对象
110      * @param scheduler 调度对象
111      * @return 成功返回true,异常返回false
112      */
113     public Boolean removeJob(DbInterfaceConfigBeanWithBLOBs interfaceConfigBean,Scheduler scheduler){
114         Boolean b=true;
115         try {  
116             TriggerKey triggerKey = TriggerKey.triggerKey(interfaceConfigBean.getInterfaceConfigId());// 根据id得到触发器名
117             scheduler.pauseTrigger(triggerKey);// 停止触发器  
118             scheduler.unscheduleJob(triggerKey);// 移除触发器  
119             scheduler.deleteJob(JobKey.jobKey(interfaceConfigBean.getInterfaceCode()));//删除任务 
120             logger.debug("{}...........................运行任务移除成功",interfaceConfigBean.getInterfaceCode());// 输出日志信息
121         } catch (SchedulerException e) {
122             b=false;
123             e.printStackTrace();
124             logger.info("{}...........................运行任务移除失败",interfaceConfigBean.getInterfaceCode());// 输出日志信息
125         }
126         return b;
127     }
128     
129     /**
130      * @param scheduler 调度对象
131      * 移除所有任务
132      */
133     public  void shutdownJobs(Scheduler scheduler) {  
134         try {  
135             if (!scheduler.isShutdown()) {  
136                 scheduler.shutdown();  
137             }  
138         } catch (Exception e) {  
139             throw new RuntimeException(e);  
140         }  
141     } 
142 }
QuartzManagerService

服务层中的修改定时任务不知为啥用不了,所以在控制层中要修改任务时就直接先删除再新增。。。

有一个BUG当系统中的该条任务未添加但数据库中存的却是已启用时,此时会禁用失败。。。

以上为本人根据实际项目经验总结并参考其他博主的文章写成,如有错误内容请指正。。。

猜你喜欢

转载自www.cnblogs.com/wlxslsb/p/9623817.html