Browse Source

新增执行策略

RuoYi 6 years ago
parent
commit
9a64a3ba4c

+ 16 - 4
src/main/java/com/ruoyi/common/constant/ScheduleConstants.java

@@ -7,10 +7,22 @@ package com.ruoyi.common.constant;
  */
 public interface ScheduleConstants
 {
-    /**
-     * 任务调度参数key
-     */
-    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
+
+    public static final String TASK_CLASS_NAME = "__TASK_CLASS_NAME__";
+
+    public static final String TASK_PROPERTIES = "__TASK_PROPERTIES__";
+
+    /** 默认 */
+    public static final String MISFIRE_DEFAULT = "0";
+
+    /** 立即触发执行 */
+    public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+    /** 触发一次执行 */
+    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+    /** 不触发立即执行 */
+    public static final String MISFIRE_DO_NOTHING = "3";
 
     public enum Status
     {

+ 35 - 0
src/main/java/com/ruoyi/common/exception/job/TaskException.java

@@ -0,0 +1,35 @@
+package com.ruoyi.common.exception.job;
+
+/**
+ * 计划策略异常
+ * 
+ * @author ruoyi
+ */
+public class TaskException extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    private Code code;
+
+    public TaskException(String msg, Code code)
+    {
+        this(msg, code, null);
+    }
+
+    public TaskException(String msg, Code code, Exception nestedEx)
+    {
+        super(msg, nestedEx);
+        this.code = code;
+    }
+
+    public Code getCode()
+    {
+        return code;
+    }
+
+    public enum Code
+    {
+        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+    }
+
+}

+ 15 - 0
src/main/java/com/ruoyi/project/monitor/job/domain/Job.java

@@ -2,6 +2,7 @@ package com.ruoyi.project.monitor.job.domain;
 
 import java.io.Serializable;
 
+import com.ruoyi.common.constant.ScheduleConstants;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.framework.web.domain.BaseEntity;
 
@@ -38,6 +39,10 @@ public class Job extends BaseEntity implements Serializable
     @Excel(name = "执行表达式 ")
     private String cronExpression;
 
+    /** cron计划策略 */
+    @Excel(name = "计划策略 ")
+    private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
+
     /** 任务状态(0正常 1暂停) */
     @Excel(name = "任务状态")
     private String status;
@@ -102,6 +107,16 @@ public class Job extends BaseEntity implements Serializable
         this.cronExpression = cronExpression;
     }
 
+    public String getMisfirePolicy()
+    {
+        return misfirePolicy;
+    }
+
+    public void setMisfirePolicy(String misfirePolicy)
+    {
+        this.misfirePolicy = misfirePolicy;
+    }
+
     public String getStatus()
     {
         return status;

+ 1 - 1
src/main/java/com/ruoyi/project/monitor/job/util/ScheduleJob.java

@@ -33,7 +33,7 @@ public class ScheduleJob extends QuartzJobBean
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException
     {
         Job job = new Job();
-        BeanUtils.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstants.JOB_PARAM_KEY));
+        BeanUtils.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
 
         IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class);
 

+ 40 - 12
src/main/java/com/ruoyi/project/monitor/job/util/ScheduleUtils.java

@@ -13,6 +13,8 @@ import org.quartz.TriggerKey;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.exception.job.TaskException.Code;
 import com.ruoyi.project.monitor.job.domain.Job;
 
 /**
@@ -25,14 +27,12 @@ public class ScheduleUtils
 {
     private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
 
-    private final static String JOB_NAME = "TASK_";
-
     /**
      * 获取触发器key
      */
     public static TriggerKey getTriggerKey(Long jobId)
     {
-        return TriggerKey.triggerKey(JOB_NAME + jobId);
+        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId);
     }
 
     /**
@@ -40,7 +40,7 @@ public class ScheduleUtils
      */
     public static JobKey getJobKey(Long jobId)
     {
-        return JobKey.jobKey(JOB_NAME + jobId);
+        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId);
     }
 
     /**
@@ -70,14 +70,14 @@ public class ScheduleUtils
             JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build();
 
             // 表达式调度构建器
-            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+            cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
 
             // 按新的cronExpression表达式构建一个新的trigger
-            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId()))
-                    .withSchedule(scheduleBuilder).build();
+            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId())).withSchedule(cronScheduleBuilder).build();
 
             // 放入参数,运行时的方法可以获取
-            jobDetail.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
+            jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
 
             scheduler.scheduleJob(jobDetail, trigger);
 
@@ -91,6 +91,10 @@ public class ScheduleUtils
         {
             log.error(e.getMessage());
         }
+        catch (TaskException e)
+        {
+            log.error(e.getMessage());
+        }
     }
 
     /**
@@ -103,15 +107,16 @@ public class ScheduleUtils
             TriggerKey triggerKey = getTriggerKey(job.getJobId());
 
             // 表达式调度构建器
-            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+            cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
 
             CronTrigger trigger = getCronTrigger(scheduler, job.getJobId());
 
             // 按新的cronExpression表达式重新构建trigger
-            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
+            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
 
             // 参数
-            trigger.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
+            trigger.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
 
             scheduler.rescheduleJob(triggerKey, trigger);
 
@@ -126,6 +131,10 @@ public class ScheduleUtils
         {
             log.error(e.getMessage());
         }
+        catch (TaskException e)
+        {
+            log.error(e.getMessage());
+        }
     }
 
     /**
@@ -138,7 +147,7 @@ public class ScheduleUtils
         {
             // 参数
             JobDataMap dataMap = new JobDataMap();
-            dataMap.put(ScheduleConstants.JOB_PARAM_KEY, job);
+            dataMap.put(ScheduleConstants.TASK_PROPERTIES, job);
 
             scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
             rows = 1;
@@ -194,4 +203,23 @@ public class ScheduleUtils
             log.error(e.getMessage());
         }
     }
+
+    public static CronScheduleBuilder handleCronScheduleMisfirePolicy(Job job, CronScheduleBuilder cb)
+            throws TaskException
+    {
+        switch (job.getMisfirePolicy())
+        {
+            case ScheduleConstants.MISFIRE_DEFAULT:
+                return cb;
+            case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
+                return cb.withMisfireHandlingInstructionIgnoreMisfires();
+            case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
+                return cb.withMisfireHandlingInstructionFireAndProceed();
+            case ScheduleConstants.MISFIRE_DO_NOTHING:
+                return cb.withMisfireHandlingInstructionDoNothing();
+            default:
+                throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
+                        + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
+        }
+    }
 }

+ 5 - 1
src/main/resources/mybatis/monitor/JobMapper.xml

@@ -11,6 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<result property="methodName"     column="method_name"     />
 		<result property="methodParams"   column="method_params"   />
 		<result property="cronExpression" column="cron_expression" />
+		<result property="misfirePolicy"  column="misfire_policy"  />
 		<result property="status"         column="status"          />
 		<result property="createBy"       column="create_by"       />
 		<result property="createTime"     column="create_time"     />
@@ -20,7 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</resultMap>
 	
 	<sql id="selectJobVo">
-        select job_id, job_name, job_group, method_name, method_params, cron_expression, status, create_by, create_time, remark from sys_job
+        select job_id, job_name, job_group, method_name, method_params, cron_expression, misfire_policy, status, create_by, create_time, remark from sys_job
     </sql>
 	
 	<select id="selectJobList" parameterType="Job" resultMap="JobResult">
@@ -66,6 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="methodName != null and methodName != ''">method_name = #{methodName},</if>
  			<if test="methodParams != null and methodParams != ''">method_params = #{methodParams},</if>
  			<if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
  			<if test="status !=null">status = #{status},</if>
  			<if test="remark != null and remark != ''">remark = #{remark},</if>
  			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
@@ -83,6 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="methodName != null and methodName != ''">method_name,</if>
  			<if test="methodParams != null and methodParams != ''">method_params,</if>
  			<if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
  			<if test="status != null and status != ''">status,</if>
  			<if test="remark != null and remark != ''">remark,</if>
  			<if test="createBy != null and createBy != ''">create_by,</if>
@@ -94,6 +97,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="methodName != null and methodName != ''">#{methodName},</if>
  			<if test="methodParams != null and methodParams != ''">#{method_params},</if>
  			<if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
+ 			<if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
  			<if test="status != null and status != ''">#{status},</if>
  			<if test="remark != null and remark != ''">#{remark},</if>
  			<if test="createBy != null and createBy != ''">#{createBy},</if>

+ 11 - 1
src/main/resources/templates/monitor/job/add.html

@@ -2,6 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <meta charset="utf-8">
 <head th:include="include :: header"></head>
+<link href="/ajax/libs/iCheck/custom.css" th:href="@{/ajax/libs/iCheck/custom.css}" rel="stylesheet"/>
 <body class="white-bg">
 	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
 		<form class="form-horizontal m" id="form-job-add">
@@ -26,7 +27,7 @@
 			<div class="form-group">
 				<label class="col-sm-3 control-label ">方法参数:</label>
 				<div class="col-sm-8">
-					<input class="form-control" type="text" name="params" id="params"/>
+					<input class="form-control" type="text" name="methodParams" id="methodParams"/>
 				</div>
 			</div>
 			<div class="form-group">
@@ -35,6 +36,14 @@
 					<input class="form-control" type="text" name="cronExpression" id="cronExpression"/>
 				</div>
 			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">执行策略:</label>
+				<div class="col-sm-8">
+					<label class="checkbox-inline i-checks"> <input type="radio" name="misfirePolicy" value="1" /> 继续执行 </label> 
+					<label class="checkbox-inline i-checks"> <input type="radio" name="misfirePolicy" value="2" /> 一次执行 </label> 
+					<label class="checkbox-inline i-checks"> <input type="radio" name="misfirePolicy" value="3" /> 放弃执行 </label>
+				</div>
+			</div>
 			<div class="form-group">
 				<label class="col-sm-3 control-label">状态:</label>
 				<div class="col-sm-8" th:with="type=${@dictService.selectDictData('sys_job_status')}">
@@ -59,6 +68,7 @@
 		</form>
 	</div>
 	<div th:include="include::footer"></div>
+	<script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
 	<script type="text/javascript">
 		var prefix = ctx + "monitor/job"
 	

+ 11 - 1
src/main/resources/templates/monitor/job/edit.html

@@ -2,6 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <meta charset="utf-8">
 <head th:include="include :: header"></head>
+<link href="/ajax/libs/iCheck/custom.css" th:href="@{/ajax/libs/iCheck/custom.css}" rel="stylesheet"/>
 <body class="white-bg">
 	<div class="wrapper wrapper-content animated fadeInRight ibox-content">
 		<form class="form-horizontal m" id="form-job-edit" th:object="${job}">
@@ -27,7 +28,7 @@
 			<div class="form-group">
 				<label class="col-sm-3 control-label ">方法参数:</label>
 				<div class="col-sm-8">
-					<input class="form-control" type="text" name="params" id="params" th:field="*{params}"/>
+					<input class="form-control" type="text" name="methodParams" id="methodParams" th:field="*{methodParams}"/>
 				</div>
 			</div>
 			<div class="form-group">
@@ -36,6 +37,14 @@
 					<input class="form-control" type="text" name="cronExpression" id="cronExpression" th:field="*{cronExpression}"/>
 				</div>
 			</div>
+			<div class="form-group">
+				<label class="col-sm-3 control-label">执行策略:</label>
+				<div class="col-sm-8">
+					<label class="checkbox-inline i-checks"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="1" /> 继续执行 </label> 
+					<label class="checkbox-inline i-checks"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="2" /> 一次执行 </label> 
+					<label class="checkbox-inline i-checks"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="3" /> 放弃执行 </label>
+				</div>
+			</div>
 			<div class="form-group">
 				<label class="col-sm-3 control-label">状态:</label>
 				<div class="col-sm-8" th:with="type=${@dictService.selectDictData('sys_job_status')}">
@@ -60,6 +69,7 @@
 		</form>
 	</div>
 	<div th:include="include::footer"></div>
+	<script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
 	<script type="text/javascript">
 		var prefix = ctx + "monitor/job"
 	

+ 2 - 1
src/main/resources/templates/system/user/user.html

@@ -126,7 +126,8 @@
 		        },
 		        {
 		            field: 'email',
-		            title: '邮箱'
+		            title: '邮箱',
+		            visible: false
 		        },
 		        {
 		            field: 'phonenumber',

+ 1 - 1
src/main/resources/templates/tool/gen/gen.html

@@ -17,7 +17,7 @@
 								表描述:<input type="text" name="tableComment"/>
 							</li>
 							<li class="time">
-								<label>创建时间: </label>
+								<label>时间: </label>
 								<input type="text" class="layui-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
 								<span>-</span>
 								<input type="text" class="layui-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>