系統用來每天插入視圖數據。。。
一、數據庫表設計
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 }

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 }
二、系統定時任務類(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.CronTrigger。在quartz1.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,並將需要傳遞的參數放入到JobDetail的Map中;
⑩①、用表達式調度構建器生成新的觸發器,將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 }
三、計划任務執行類(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 }
四、工具類(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 }
五、配置文件
在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 }
服務層:

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 }
服務層中的修改定時任務不知為啥用不了,所以在控制層中要修改任務時就直接先刪除再新增。。。
有一個BUG當系統中的該條任務未添加但數據庫中存的卻是已啟用時,此時會禁用失敗。。。