spring中使用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當系統中的該條任務未添加但數據庫中存的卻是已啟用時,此時會禁用失敗。。。

 

以上為本人根據實際項目經驗總結並參考其他博主的文章寫成,如有錯誤內容請指正。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM