1.java環境搭建,具體參考包中的webapp/resources/doc/平臺開發環境安裝Guide_V1.0.docx文檔html
2.使用源碼中的webapp/resources/doc/init.sql初始化表結構及數據前端
t_timetask 任務表java
t_timetask_log 任務運行日誌web
3.數據庫鏈接配置在cloud_parent中的pom.xml中,數據庫名稱ffxl_cloud,默認帳號root,密碼123456,一樣可在pom.xml中修改spring
4.運行quartz項目,此處注意,使用的端口號須要與platform_parent下pom.xml中的quartz.job.url的一致,程序中用的是8080端口,具體使用哪一個配置,請參考maven中profiles的使用sql
5.運行admin項目,注意,此處端口要與quartz不一樣,程序中用的是80端口,瀏覽器中輸入http://localhost/admin 運行結果如圖:數據庫
一、文件引入順序:lib_parent → platform_parent → cloud_parentapache
二、代碼結構json
quartz項目部分代碼瀏覽器
1.quartz項目啓動時,初始化數據庫中的定時任務
package com.ffxl.quartz.init; import java.util.ArrayList; import java.util.List; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import com.ffxl.cloud.model.STimetask; import com.ffxl.cloud.model.STimetaskExample; import com.ffxl.cloud.model.base.BaseSTimetaskExample.Criteria; import com.ffxl.cloud.model.warpper.ScheduleJob; import com.ffxl.cloud.service.STimetaskService; import com.ffxl.quartz.task.util.QuartzJobFactory; import com.ffxl.quartz.task.util.QuartzJobFactoryDisallowConcurrentExecution; /** * 根據上下文獲取spring類 * * @author */ public class InitQuartzJob implements ApplicationContextAware{ private static final Logger logger = LoggerFactory.getLogger(InitQuartzJob.class); private static ApplicationContext appCtx; public static SchedulerFactoryBean schedulerFactoryBean = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (this.appCtx == null) { this.appCtx = applicationContext; } } public static void init() { schedulerFactoryBean = (SchedulerFactoryBean) appCtx.getBean(SchedulerFactoryBean.class); Scheduler scheduler = schedulerFactoryBean.getScheduler(); try { logger.info(scheduler.getSchedulerName()); } catch (SchedulerException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // 這裏從數據庫中獲取任務信息數據 STimetaskService sTimetaskService = (STimetaskService) appCtx.getBean(STimetaskService.class); STimetaskExample example = new STimetaskExample(); Criteria c = example.createCriteria(); c.andJobStatusEqualTo("1"); // 已發佈的定時任務 List<STimetask> list = sTimetaskService.selectByExample(example); List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(); for (STimetask sTimetask : list) { ScheduleJob job1 = new ScheduleJob(); job1.setJobId(sTimetask.getId()); job1.setJobGroup(sTimetask.getGroupName()); // 任務組 job1.setJobName(sTimetask.getName());// 任務名稱 job1.setJobStatus(sTimetask.getJobStatus()); // 任務發佈狀態 job1.setIsConcurrent(sTimetask.getConcurrent() ? "1" : "0"); // 運行狀態 job1.setCronExpression(sTimetask.getCron()); job1.setBeanClass(sTimetask.getBeanName());// 一個以所給名字註冊的bean的實例 job1.setMethodName(sTimetask.getMethodName()); job1.setJobData(sTimetask.getJobData()); // 參數 jobList.add(job1); } for (ScheduleJob job : jobList) { try { addJob(job); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 添加任務 * * @param scheduleJob * @throws SchedulerException */ public static void addJob(ScheduleJob job) throws SchedulerException { if (job == null || !ScheduleJob.STATUS_RUNNING.equals(job.getJobStatus())) { return; } Scheduler scheduler = schedulerFactoryBean.getScheduler(); logger.debug(scheduler + "...........................................add"); TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 不存在,建立一個 if (null == trigger) { Class clazz = ScheduleJob.CONCURRENT_IS.equals(job.getIsConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class; JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).usingJobData("data", job.getJobData()).build(); jobDetail.getJobDataMap().put("scheduleJob", job); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); trigger = TriggerBuilder.newTrigger().withDescription(job.getJobId().toString()).withIdentity(job.getJobName(), job.getJobGroup()) .withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } else { // Trigger已存在,那麼更新相應的定時設置 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); // 按新的cronExpression表達式從新構建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).usingJobData("data", job.getJobData()).withSchedule(scheduleBuilder).build(); // 按新的trigger從新設置job執行 scheduler.rescheduleJob(triggerKey, trigger); } } }
2.提供job對應的操做服務
package com.ffxl.quartz.task; import java.io.BufferedInputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import org.apache.log4j.Logger; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerKey; import org.quartz.impl.matchers.GroupMatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; import com.ffxl.cloud.annotation.ControllerLogAnnotation; import com.ffxl.cloud.model.STimetask; import com.ffxl.cloud.model.warpper.ScheduleJob; import com.ffxl.platform.util.JsonResult; import com.ffxl.platform.util.StringUtil; import com.ffxl.quartz.init.InitQuartzJob; @Component @RequestMapping(value = "/opt") public class JobSerlvet { public final Logger log = Logger.getLogger(this.getClass()); @Autowired private SchedulerFactoryBean schedulerFactoryBean; /** * 獲取全部計劃中的任務列表 * * @return * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/getAllJob") @ResponseBody @ControllerLogAnnotation(description = "獲取全部計劃中的任務列表") public void getAllJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { Scheduler scheduler = schedulerFactoryBean.getScheduler(); GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); Set<JobKey> jobKeys = scheduler.getJobKeys(matcher); List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(); for (JobKey jobKey : jobKeys) { List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey); for (Trigger trigger : triggers) { ScheduleJob job = new ScheduleJob(); job.setJobId(trigger.getDescription());//description 放的是job的id job.setJobName(jobKey.getName()); job.setJobGroup(jobKey.getGroup()); job.setDescription("觸發器:" + trigger.getKey()); Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); job.setJobStatus(triggerState.name()); if (trigger instanceof CronTrigger) { CronTrigger cronTrigger = (CronTrigger) trigger; String cronExpression = cronTrigger.getCronExpression(); job.setCronExpression(cronExpression); } jobList.add(job); } } //輸出 if(jobList.size() >0){ JSONArray listArray=JSONArray.fromObject(jobList); Map<String,Object> m =new HashMap<String, Object>(); m.put("job", listArray); response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\",\"data\":"+m+"}"); out.close(); }else{ response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"沒有計劃任務\"}"); out.close(); } } /** * 全部正在運行的job * * @return * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/getRunningJob") @ResponseBody public void getRunningJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { Scheduler scheduler = schedulerFactoryBean.getScheduler(); List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs(); List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size()); for (JobExecutionContext executingJob : executingJobs) { ScheduleJob job = new ScheduleJob(); JobDetail jobDetail = executingJob.getJobDetail(); JobKey jobKey = jobDetail.getKey(); Trigger trigger = executingJob.getTrigger(); job.setJobName(jobKey.getName()); job.setJobGroup(jobKey.getGroup()); job.setDescription("觸發器:" + trigger.getKey()); Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); job.setJobStatus(triggerState.name()); if (trigger instanceof CronTrigger) { CronTrigger cronTrigger = (CronTrigger) trigger; String cronExpression = cronTrigger.getCronExpression(); job.setCronExpression(cronExpression); } jobList.add(job); } //輸出 if(jobList.size() >0){ JSONArray listArray=JSONArray.fromObject(jobList); Map<String,Object> m =new HashMap<String, Object>(); m.put("job", listArray); response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\",\"data\":"+m+"}"); out.close(); }else{ response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"沒有正在執行的任務\"}"); out.close(); } } /** * 添加任務 * * @param * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/addJob") @ResponseBody public void addJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { StringBuffer info=new StringBuffer(); ServletInputStream in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); ScheduleJob job = new ScheduleJob(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ job.setJobId(sTimetask.getId()); job.setJobGroup(sTimetask.getGroupName()); //任務組 job.setJobName(sTimetask.getName());// 任務名稱 job.setJobStatus(sTimetask.getJobStatus()); // 任務發佈狀態 job.setIsConcurrent(sTimetask.getConcurrent()?"1":"0"); // 運行狀態 job.setCronExpression(sTimetask.getCron()); job.setBeanClass(sTimetask.getBeanName());// 一個以所給名字註冊的bean的實例 job.setMethodName(sTimetask.getMethodName()); job.setJobData(sTimetask.getJobData()); //參數 } } InitQuartzJob.addJob(job); //輸入 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); } /** * 暫停一個job * * @param scheduleJob * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/pauseJob") @ResponseBody public void pauseJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { StringBuffer info=new StringBuffer(); ServletInputStream in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName()); scheduler.pauseJob(jobKey); //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); }else{ //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"任務不存在\"}"); out.close(); } } } /** * 恢復一個job * * @param scheduleJob * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/resumeJob") @ResponseBody public void resumeJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { StringBuffer info=new StringBuffer(); ServletInputStream in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName()); scheduler.resumeJob(jobKey); //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); }else{ //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"任務不存在\"}"); out.close(); } } } /** * 刪除一個job * * @param scheduleJob * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/deleteJob") @ResponseBody public void deleteJob(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { StringBuffer info=new StringBuffer(); ServletInputStream in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName()); scheduler.deleteJob(jobKey); //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); }else{ //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"任務不存在\"}"); out.close(); } } } /** * 當即執行job * * @param scheduleJob * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/runAJobNow") @ResponseBody public void runAJobNow(HttpServletRequest request,HttpServletResponse response) throws SchedulerException, IOException { StringBuffer info=new StringBuffer(); ServletInputStream in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName()); scheduler.triggerJob(jobKey); //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); }else{ //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"任務不存在\"}"); out.close(); } } } /** * 更新job時間表達式 * * @param scheduleJob * @throws SchedulerException * @throws IOException */ @RequestMapping(value="/updateJobCron") @ResponseBody public void updateJobCron(HttpServletRequest request,HttpServletResponse response) throws SchedulerException{ try { StringBuffer info=new StringBuffer(); ServletInputStream in; in = request.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); byte[] buffer=new byte[1024]; int iRead; while((iRead=buf.read(buffer))!=-1){ info.append(new String(buffer,0,iRead,"UTF-8")); } // 釋放資源 buf.close(); in.close(); if(info!=null&&!StringUtil.isEmpty(info.toString())){ JSONObject json = JSONObject.parseObject(info.toString()); STimetask sTimetask = JSONObject.toJavaObject(json, STimetask.class); if(sTimetask !=null){ Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName()); TriggerKey triggerKey = TriggerKey.triggerKey(sTimetask.getName(), sTimetask.getGroupName()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(sTimetask.getCron()); trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); scheduler.rescheduleJob(triggerKey, trigger); //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"2000\",\"message\":\"成功\"}"); out.close(); }else{ //輸出 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.write("{\"code\":\"5000\",\"message\":\"任務不存在\"}"); out.close(); } } }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.編寫 定時清除timeTaskLog 7天以前的記錄
@Component public class TimeTaskLogDispatchController { private static final Logger LOGGER = Logger.getLogger(TimeTaskLogDispatchController.class); /** * 定時清除timeTaskLog 7天以前的記錄 */ public void deleteTimeTaskLog(String data) { LOGGER.info("【定時清除timeTaskLog 7天以前的記錄】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>開始執行"); STimetaskLogService bActiveService = (STimetaskLogService) ApplicationContextUtils.getBean(STimetaskLogService.class); Date currentDate = new Date(); int day = -7; Date deleteDate = DateUtil.getAfterNumDay(currentDate, day); int ret = bActiveService.deleteLog(deleteDate); if(ret >0){ LOGGER.info("【定時清除timeTaskLog 7天以前的記錄】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>執行成功"); }else{ LOGGER.info("【定時清除timeTaskLog 7天以前的記錄】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>執行失敗"); } } }
4.dispatcher-servlet.xml中添加以下配置
<!-- 初始化springUtils --> <bean id="springUtils" class="com.ffxl.quartz.task.util.SpringUtils" /> <!-- 初始化Scheduler --> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" /> <!-- 初始化job --> <bean id="initQuartzJob" class="com.ffxl.quartz.init.InitQuartzJob" init-method="init" lazy-init="false" />
admin項目部分代碼
1.可視化項目的controller層
package com.ffxl.admin.controller.task; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpSession; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.ffxl.admin.controller.BaseController; import com.ffxl.admin.util.DataTablesUtil; import com.ffxl.cloud.model.STimetask; import com.ffxl.cloud.model.warpper.ScheduleJob; import com.ffxl.cloud.service.STimetaskService; import com.ffxl.platform.constant.Const; import com.ffxl.platform.core.Page; import com.ffxl.platform.exception.BusinessException; import com.ffxl.platform.util.CronUtil; import com.ffxl.platform.util.DateUtil; import com.ffxl.platform.util.HttpConnectUtil; import com.ffxl.platform.util.JsonDateValueProcessor; import com.ffxl.platform.util.JsonResult; import com.ffxl.platform.util.Message; import com.ffxl.platform.util.StringUtil; /** * 定時任務 * @author wison * */ @Controller @RequestMapping(value = "/task") public class TimeTaskController extends BaseController { private static String JOB_URL = Const.QUARTZ_JOB_URL; private static String ALL_JOB = JOB_URL+"/opt/getAllJob"; //全部計劃中的任務列表 private static String RUNNING_JOB = JOB_URL+"/opt/getRunningJob";//全部正在運行的job private static String ADD_JOB = JOB_URL+"/opt/addJob";//添加任務 private static String PAUSE_JOB =JOB_URL+ "/opt/pauseJob";//暫停一個job private static String RESUME_JOB = JOB_URL+"/opt/resumeJob";//恢復一個job private static String DELETE_JOB = JOB_URL+"/opt/deleteJob";//刪除一個job private static String RUNA_JOB =JOB_URL+ "/opt/runAJobNow";//當即執行job private static String UPDATE_JOB = JOB_URL+"/opt/updateJobCron";//更新job時間表達式 private static final Logger logger = LoggerFactory.getLogger(TimeTaskController.class); @Autowired private STimetaskService stimetaskService; @InitBinder public void initBinder(WebDataBinder binder) { DateFormat fmt = new SimpleDateFormat(DateUtil.STANDARD_DATE_FORMAT_STR); CustomDateEditor dateEditor = new CustomDateEditor(fmt, true); binder.registerCustomEditor(Date.class, dateEditor); } /** * 列表頁面跳轉 * @return */ @RequestMapping(value="/list") public ModelAndView userList(STimetask task){ ModelAndView mv = this.getModelAndView(); mv.setViewName("system/timeTaskList"); return mv; } /** * 列表 * @return */ @RequestMapping(value="/task_list") @ResponseBody public JsonResult taskList(DataTablesUtil dataTables, STimetask task, Page page, HttpSession session){ List<STimetask> list = stimetaskService.selectByPage(task, page); // 查詢task的運行狀態 String result = HttpConnectUtil.httpRequest(RUNNING_JOB, Const.REQUEST_METHOD_POST, null); if(result!=null){ JSONObject jsonResult = JSONObject.fromObject(result); Map<String, ScheduleJob> map = new HashMap<String, ScheduleJob>(); if( jsonResult.get("code").equals("2000")){ JSONObject js = (JSONObject) jsonResult.get("data"); JSONArray dataArray = (JSONArray) js.get("job"); if(dataArray.size() > 0){ List<ScheduleJob> jobList = JSONArray.toList(dataArray,ScheduleJob.class); for(ScheduleJob job: jobList){ map.put(job.getJobId().toString(), job); } } } for(STimetask st: list){ if(map.containsKey(st.getId())){ st.setConcurrent(true); } } } // 查詢task的計劃狀態 String planResult = HttpConnectUtil.httpRequest(ALL_JOB, Const.REQUEST_METHOD_POST, null); if(planResult!=null){ JSONObject jsonPlanResult = JSONObject.fromObject(planResult); Map<String, ScheduleJob> planMap = new HashMap<String, ScheduleJob>(); if(jsonPlanResult.get("code").equals("2000")){ JSONObject js = (JSONObject) jsonPlanResult.get("data"); JSONArray dataArray = (JSONArray) js.get("job"); if(dataArray.size() > 0){ List<ScheduleJob> jobList = JSONArray.toList(dataArray,ScheduleJob.class); for(ScheduleJob job: jobList){ planMap.put(job.getJobId().toString(), job); } } } for(STimetask st: list){ if(planMap.containsKey(st.getId())){ String status = planMap.get(st.getId()).getJobStatus(); st.setPlanStatus(status); } } } //返回dataTable所需數據 dataTables = this.getDataTables(page, dataTables, list); return new JsonResult("2000", dataTables); } /** * 當即執行一次job * 用於測試任務是否正確 * @param id * @return */ @RequestMapping(value="/run_task2job") @ResponseBody public JsonResult run_task2job(String id){ //查詢task STimetask stimetask = stimetaskService.selectByPrimaryKey(id); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor()); JSONObject jsonArray = JSONObject.fromObject(stimetask,jsonConfig); String result = HttpConnectUtil.httpRequest(RUNA_JOB, Const.REQUEST_METHOD_POST, jsonArray.toString()); logger.info(result); if(result ==null){ return new JsonResult("5000", "定時項目未啓動",null); }else{ return new JsonResult("2000", null); } } /** * 添加job到計劃列表 * @param id * @return */ @RequestMapping(value="/add_task2job") @ResponseBody public JsonResult add_task2job(String id){ //查詢task STimetask stimetask = stimetaskService.selectByPrimaryKey(id); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor()); JSONObject jsonArray = JSONObject.fromObject(stimetask,jsonConfig); String result = HttpConnectUtil.httpRequest(ADD_JOB, Const.REQUEST_METHOD_POST, jsonArray.toString()); logger.info(result); if(result ==null){ return new JsonResult("5000", "定時項目未啓動",null); }else{ return new JsonResult("2000", null); } } /** * 從計劃列表中暫停job * @param id * @return */ @RequestMapping(value="/stop_task2job") @ResponseBody public JsonResult stop_task2job(String id){ //查詢task STimetask stimetask = stimetaskService.selectByPrimaryKey(id); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor()); JSONObject jsonArray = JSONObject.fromObject(stimetask,jsonConfig); String result = HttpConnectUtil.httpRequest(PAUSE_JOB, Const.REQUEST_METHOD_POST, jsonArray.toString()); logger.info(result); if(result ==null){ return new JsonResult("5000", "定時項目未啓動",null); }else{ return new JsonResult("2000", null); } } /** * 從計劃列表中移除job * @param id * @return */ @RequestMapping(value="/remove_task2job") @ResponseBody public JsonResult remove_task2job(String id){ //查詢task STimetask stimetask = stimetaskService.selectByPrimaryKey(id); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor()); JSONObject jsonArray = JSONObject.fromObject(stimetask,jsonConfig); String result = HttpConnectUtil.httpRequest(DELETE_JOB, Const.REQUEST_METHOD_POST, jsonArray.toString()); logger.info(result); if(result ==null){ return new JsonResult("5000", "定時項目未啓動",null); }else{ return new JsonResult("2000", null); } } /** * 變動job狀態 * @param id * @return */ @RequestMapping(value="/update_task") @ResponseBody public JsonResult update_task(String ids,String type){ //查詢task String[] idArray = ids.split(","); Map<String,String> selectedIdMap = new HashMap<String,String>(); List<String> idList = new ArrayList<String>(); for (int i = 0; i < idArray.length; i++) { idList.add(idArray[i]); } int ret = stimetaskService.updatebyOperate(idList,type); if(ret >0){ return new JsonResult(true); }else{ return new JsonResult(false); } } /** * 刪除job * @param id * @return */ @RequestMapping(value="/delete_task") @ResponseBody public JsonResult delete_task(String ids){ //查詢task String[] idArray = ids.split(","); Map<String,String> selectedIdMap = new HashMap<String,String>(); List<String> idList = new ArrayList<String>(); for (int i = 0; i < idArray.length; i++) { idList.add(idArray[i]); } int ret = stimetaskService.deleteByIds(idList); if(ret >0){ return new JsonResult(true); }else{ return new JsonResult(false); } } /** * 詳情頁面 * @return */ @RequestMapping(value="/task_detail") public ModelAndView detail(String id){ ModelAndView mv = this.getModelAndView(); STimetask model = new STimetask(); model = stimetaskService.selectByPrimaryKey(id); mv.addObject("model", model); mv.setViewName("system/timeTaskDetail"); return mv; } /** * 解析cron * @return */ @RequestMapping(value="/analysis_cron") @ResponseBody public JsonResult analysisCron(String cron){ try { Date date = new Date(); String dateStr = DateUtil.formatStandardDatetime(date); List<String> dateList = CronUtil.cronAlgBuNums(cron, dateStr, 5); return new JsonResult("2000", dateList); } catch (Exception e) { e.printStackTrace(); return new JsonResult("5000", null); } } /** * 驗證名稱是否存在 * @param id * @param groupName * @param name * @return * */ @RequestMapping(value="/check_name") @ResponseBody public Boolean check_name(String id, String groupName, String name){ if(StringUtil.isEmpty(groupName,name)){ throw new BusinessException(Message.M4003); } STimetask task = new STimetask(); task.setId(id); task.setGroupName(groupName); task.setName(name); STimetask queryTask = stimetaskService.checkName(task); if(queryTask !=null){ logger.debug("組.任務名 exists,return false"); return false; }else{ logger.debug("組.任務名 not exists,return true"); return true; } } /** * 保存 * @return */ @RequestMapping(value="/task_save") @ResponseBody public JsonResult userSave(STimetask task, HttpSession session){ //獲取系統操做人員 String longName = "admin"; task.setModifyUserId(longName); try{ int ret= stimetaskService.insertOrUpdateByUser(task,longName); if(ret > 0){ return new JsonResult("2000",task); }else{ return new JsonResult("5000"); } }catch(BusinessException e){ return new JsonResult("5001",e.getMessage(),null); } } }
2.前端頁面
能夠看到在這裏我把定時任務的狀態分爲兩大類,任務狀態跟業務有關,分爲已發佈和未發佈;計劃狀態跟定時任務的運行有關,分爲None,正常運行,已暫停,任務執行中,線程阻塞,未計劃,錯誤
2.1計劃狀態
function formatPlan(value, rowData, rowIndex){ if(value=="None"){ return "<span class='text-danger'>None</span>" } if(value=="NORMAL"){ return "<span class='text-success'>正常運行</span>" } if(value=="PAUSED"){ return "<span class='text-yellow'>已暫停</span>" } if(value=="COMPLETE"){ return "<span class='text-success'>任務執行中</span>" } if(value=="BLOCKED"){ return "<span class='text-danger'>線程阻塞</span>" } if(value=="ERROR"){ return "<span class='text-danger'>錯誤</span>" }else{ return "<span class='text-danger'>未計劃</span>" } }
2.2操做邏輯
function formatOpt(value, rowData, rowIndex) { var msg = ""; msg+="<a href='#' class='btnstyle' onclick='showDetail(\"" + rowData.id + "\")'>編輯</a>"; //已發佈, if(rowData.jobStatus=='1'){ var value = rowData.planStatus; if(value=="None"|| value==null){ msg +='<a href="#"class="btnstyle" onclick="addJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="定時任務按照計劃開始執行" >計劃</a>'; } if(value=="NORMAL"){ msg += '<a href="#"class="btnstyle" onclick="runJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="緊執行一次" >當即執行</a>' + '<a href="#"class="btnstyle" onclick="stopJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="定時任務暫時中止執行" >暫停</a>' +'<a href="#"class="btnstyle" onclick="removeJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="定時任務從計劃列表中移除" >移除</a>'; } if(value=="PAUSED"){ msg += '<a href="#"class="btnstyle" onclick="runJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="緊執行一次" >當即執行</a>' + '<a href="#"class="btnstyle" onclick="addJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="定時任務按照計劃開始執行" >計劃</a>' +'<a href="#"class="btnstyle" onclick="removeJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="定時任務從計劃列表中移除" >移除</a>'; } if(value=="COMPLETE"){ msg += '<a href="#"class="btnstyle" onclick="runJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="緊執行一次" >當即執行</a>' } if(value=="BLOCKED"){ msg += '<a href="#"class="btnstyle" onclick="runJob(\''+rowData.id+'\')" ' +'onMouseOver="popTip(this,\' '+rowData+' \' )" class="btn btn-info btn-xs" data-toggle="tooltip"' +' data-placement="top" title="緊執行一次" >當即執行</a>' } if(value=="ERROR"){ } } return msg; }
簡單概述爲:已發佈的定時任務出現【計劃】按鈕;執行【計劃】後,定時任務正常運行,且出現【當即執行】【暫停】【移除】三個按鈕,【當即執行】用於測試當前定時任務的業務邏輯是否正確,【暫停】很容易理解,就是把當前任務暫停,及時到達cron定義的時間,定時任務也不會執行,【移除】僅僅是把計劃列表中相應的任務暫時清除掉,你能夠理解爲清除緩存中的定時任務,並非物理刪除
3.定時任務詳情
3.點擊規則彈出頁面以下,可自行修改界面,這裏我是從網上隨便找了個插件,而後按照本身想要的修改下源碼