Browse Source

优化定时调度和脚本

zhouhao 7 years ago
parent
commit
e35052ce4b
25 changed files with 1316 additions and 135 deletions
  1. 34 0
      hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/Sqls.java
  2. 12 12
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-dao/hsweb-system-schedule-dao-mybatis/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/schedule/ScheduleJobMapper.xml
  3. 115 105
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-entity/src/main/java/org/hswebframework/web/entity/schedule/ScheduleJobEntity.java
  4. 12 12
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-entity/src/main/java/org/hswebframework/web/entity/schedule/SimpleScheduleJobEntity.java
  5. 5 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/pom.xml
  6. 12 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleJobExecutor.java
  7. 4 1
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleJobService.java
  8. 12 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleTriggerBuilder.java
  9. 46 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DefaultScriptScheduleJobExecutor.java
  10. 19 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DynamicJob.java
  11. 42 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DynamicJobFactory.java
  12. 117 2
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/SimpleScheduleJobService.java
  13. 30 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/SmartScheduleTriggerBuilder.java
  14. 5 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/pom.xml
  15. 51 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/AutoCreateTable.java
  16. 81 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/ScheduleAutoConfiguration.java
  17. 84 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/SchedulerProperties.java
  18. 2 2
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/hsweb-starter.js
  19. 247 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-h2-create.sql
  20. 143 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-mysql-create.sql
  21. 157 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-oracle-create.sql
  22. 39 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/test/java/org/hswebframework/web/schedule/test/DynamicScheduleTests.java
  23. 35 0
      hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/test/java/org/hswebframework/web/schedule/test/ScheduleTests.java
  24. 9 0
      hsweb-system/hsweb-system-schedule/pom.xml
  25. 3 1
      hsweb-system/hsweb-system-script/hsweb-system-script-service/hsweb-system-script-service-simple/src/main/java/org/hswebframework/web/service/script/simple/SimpleScriptService.java

+ 34 - 0
hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/Sqls.java

@@ -0,0 +1,34 @@
+package org.hswebframework.web;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class Sqls {
+
+    public static List<String> parse(String sqlText) {
+        String[] list = sqlText.split("[\n]");
+        List<String> sqlList = new ArrayList<>();
+        List<String> tmp = new ArrayList<>();
+        Stream.of(list)
+                .filter(s -> !s.startsWith("--") && s.trim().length() != 0)
+                .forEach(s1 -> {
+                    if (s1.trim().endsWith(";")) {
+                        s1 = s1.trim();
+                        tmp.add(s1.substring(0, s1.length() - 1));
+                        sqlList.add(String.join("\n", tmp.toArray(new String[tmp.size()])));
+                        tmp.clear();
+                    } else {
+                        tmp.add(s1);
+                    }
+                });
+        sqlList.add(String.join("\n", tmp.toArray(new String[tmp.size()])));
+        tmp.clear();
+        return sqlList;
+    }
+}

+ 12 - 12
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-dao/hsweb-system-schedule-dao-mybatis/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/schedule/ScheduleJobMapper.xml

@@ -4,16 +4,16 @@
         "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.hswebframework.web.dao.schedule.ScheduleJobDao">
     <resultMap id="ScheduleJobResultMap" type="org.hswebframework.web.entity.schedule.SimpleScheduleJobEntity">
-              <id property="id" column="u_id" javaType="string" jdbcType="VARCHAR"/>
-            <result property="name" column="name" javaType="String" jdbcType="VARCHAR"/>
-            <result property="remark" column="remark" javaType="String" jdbcType="VARCHAR"/>
-            <result property="quartz_config" column="quartz_config" javaType="String" jdbcType="clob"/>
-            <result property="script" column="script" javaType="String" jdbcType="CLOB"/>
-            <result property="language" column="language" javaType="String" jdbcType="VARCHAR"/>
-            <result property="enabled" column="enabled" javaType="Long" jdbcType="DECIMAL"/>
-            <result property="parameters" column="parameters" javaType="String" jdbcType="CLOB"/>
-            <result property="type" column="type" javaType="String" jdbcType="VARCHAR"/>
-            <result property="tags" column="tags" javaType="String" jdbcType="VARCHAR"/>
+        <id property="id" column="u_id" javaType="string" jdbcType="VARCHAR"/>
+        <result property="name" column="name" javaType="String" jdbcType="VARCHAR"/>
+        <result property="remark" column="remark" javaType="String" jdbcType="VARCHAR"/>
+        <result property="quartzConfig" column="quartz_config" javaType="String" jdbcType="CLOB"/>
+        <result property="script" column="script" javaType="String" jdbcType="CLOB"/>
+        <result property="language" column="language" javaType="String" jdbcType="VARCHAR"/>
+        <result property="status" column="status" javaType="Byte" jdbcType="DECIMAL"/>
+        <result property="parameters" column="parameters" javaType="String" jdbcType="CLOB"/>
+        <result property="type" column="type" javaType="String" jdbcType="VARCHAR"/>
+        <result property="tags" column="tags" javaType="String" jdbcType="VARCHAR"/>
     </resultMap>
 
     <!--用于动态生成sql所需的配置-->
@@ -21,8 +21,8 @@
         <bind name="resultMapId" value="'ScheduleJobResultMap'"/>
         <bind name="tableName" value="'s_schedule_job'"/>
     </sql>
-  
-    <insert id="insert" parameterType="org.hswebframework.web.entity.schedule.SimpleScheduleJobEntity" >
+
+    <insert id="insert" parameterType="org.hswebframework.web.entity.schedule.SimpleScheduleJobEntity">
         <include refid="config"/>
         <include refid="BasicMapper.buildInsertSql"/>
     </insert>

+ 115 - 105
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-entity/src/main/java/org/hswebframework/web/entity/schedule/ScheduleJobEntity.java

@@ -1,131 +1,141 @@
 package org.hswebframework.web.entity.schedule;
+
 import org.hswebframework.web.commons.entity.GenericEntity;
 
 /**
-* 调度任务 实体
-* @author hsweb-generator-online
-*/
-public interface ScheduleJobEntity extends GenericEntity<String>{
+ * 调度任务 实体
+ *
+ * @author hsweb-generator-online
+ */
+public interface ScheduleJobEntity extends GenericEntity<String> {
  /*-------------------------------------------
     |               属性名常量               |
     ===========================================*/
-     /**
+    /**
      * 任务名称
      */
-     String name="name";
-     /**
+    String name         = "name";
+    /**
      * 备注
      */
-     String remark="remark";
-     /**
+    String remark       = "remark";
+    /**
      * 定时调度配置
      */
-     String quartz_config="quartz_config";
-     /**
+    String quartzConfig = "quartzConfig";
+    /**
      * 执行脚本
      */
-     String script="script";
-     /**
+    String script       = "script";
+    /**
      * 脚本语言
      */
-     String language="language";
-     /**
+    String language     = "language";
+    /**
      * 是否启用
      */
-     String enabled="enabled";
-     /**
+    String status       = "status";
+    /**
      * 启动参数
      */
-     String parameters="parameters";
-     /**
+    String parameters   = "parameters";
+    /**
      * 任务类型
      */
-     String type="type";
-     /**
+    String type         = "type";
+    /**
      * 标签
      */
-     String tags="tags";
-    
-        /**
-        * @return 任务名称
-        */
-        String getName();
-
-        /**
-        * @param  name  任务名称
-        */
-        void setName(String name);
-        /**
-        * @return 备注
-        */
-        String getRemark();
-
-        /**
-        * @param  remark  备注
-        */
-        void setRemark(String remark);
-        /**
-        * @return 定时调度配置
-        */
-        String getQuartz_config();
-
-        /**
-        * @param  quartz_config  定时调度配置
-        */
-        void setQuartz_config(String quartz_config);
-        /**
-        * @return 执行脚本
-        */
-        String getScript();
-
-        /**
-        * @param  script  执行脚本
-        */
-        void setScript(String script);
-        /**
-        * @return 脚本语言
-        */
-        String getLanguage();
-
-        /**
-        * @param  language  脚本语言
-        */
-        void setLanguage(String language);
-        /**
-        * @return 是否启用
-        */
-        Long getEnabled();
-
-        /**
-        * @param  enabled  是否启用
-        */
-        void setEnabled(Long enabled);
-        /**
-        * @return 启动参数
-        */
-        String getParameters();
-
-        /**
-        * @param  parameters  启动参数
-        */
-        void setParameters(String parameters);
-        /**
-        * @return 任务类型
-        */
-        String getType();
-
-        /**
-        * @param  type  任务类型
-        */
-        void setType(String type);
-        /**
-        * @return 标签
-        */
-        String getTags();
-
-        /**
-        * @param  tags  标签
-        */
-        void setTags(String tags);
-      
+    String tags         = "tags";
+
+    /**
+     * @return 任务名称
+     */
+    String getName();
+
+    /**
+     * @param name 任务名称
+     */
+    void setName(String name);
+
+    /**
+     * @return 备注
+     */
+    String getRemark();
+
+    /**
+     * @param remark 备注
+     */
+    void setRemark(String remark);
+
+    /**
+     * @return 定时调度配置
+     */
+    String getQuartzConfig();
+
+    /**
+     * @param quartzConfig 定时调度配置
+     */
+    void setQuartzConfig(String quartzConfig);
+
+    /**
+     * @return 执行脚本
+     */
+    String getScript();
+
+    /**
+     * @param script 执行脚本
+     */
+    void setScript(String script);
+
+    /**
+     * @return 脚本语言
+     */
+    String getLanguage();
+
+    /**
+     * @param language 脚本语言
+     */
+    void setLanguage(String language);
+
+    /**
+     * @return 是否启用
+     */
+    Byte getStatus();
+
+    /**
+     * @param status 是否启用
+     */
+    void setStatus(Byte status);
+
+    /**
+     * @return 启动参数
+     */
+    String getParameters();
+
+    /**
+     * @param parameters 启动参数
+     */
+    void setParameters(String parameters);
+
+    /**
+     * @return 任务类型
+     */
+    String getType();
+
+    /**
+     * @param type 任务类型
+     */
+    void setType(String type);
+
+    /**
+     * @return 标签
+     */
+    String getTags();
+
+    /**
+     * @param tags 标签
+     */
+    void setTags(String tags);
+
 }

+ 12 - 12
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-entity/src/main/java/org/hswebframework/web/entity/schedule/SimpleScheduleJobEntity.java

@@ -11,13 +11,13 @@ public class SimpleScheduleJobEntity extends SimpleGenericEntity<String> impleme
   		//备注
         private String remark;
   		//定时调度配置
-        private String quartz_config;
+        private String quartzConfig;
   		//执行脚本
         private String script;
   		//脚本语言
         private String language;
   		//是否启用
-        private Long enabled;
+        private Byte   status;
   		//启动参数
         private String parameters;
   		//任务类型
@@ -54,15 +54,15 @@ public class SimpleScheduleJobEntity extends SimpleGenericEntity<String> impleme
         /**
         * @return  定时调度配置
         */
-        public String getQuartz_config(){
-			return this.quartz_config;
+        public String getQuartzConfig(){
+			return this.quartzConfig;
         }
 
         /**
-        * @param  quartz_config  定时调度配置
+        * @param  quartzConfig  定时调度配置
         */
-        public void setQuartz_config(String quartz_config){
-        	this.quartz_config=quartz_config;
+        public void setQuartzConfig(String quartzConfig){
+        	this.quartzConfig = quartzConfig;
         }
         /**
         * @return  执行脚本
@@ -93,15 +93,15 @@ public class SimpleScheduleJobEntity extends SimpleGenericEntity<String> impleme
         /**
         * @return  是否启用
         */
-        public Long getEnabled(){
-			return this.enabled;
+        public Byte getStatus(){
+			return this.status;
         }
 
         /**
-        * @param  enabled  是否启用
+        * @param  status  是否启用
         */
-        public void setEnabled(Long enabled){
-        	this.enabled=enabled;
+        public void setStatus(Byte status){
+        	this.status = status;
         }
         /**
         * @return  启动参数

+ 5 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/pom.xml

@@ -22,5 +22,10 @@
             <artifactId>hsweb-system-schedule-dao-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 12 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleJobExecutor.java

@@ -0,0 +1,12 @@
+package org.hswebframework.web.service.schedule;
+
+import java.util.Map;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public interface ScheduleJobExecutor {
+    Object doExecuteJob(String jobId, Map<String, Object> parameter);
+}

+ 4 - 1
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleJobService.java

@@ -4,10 +4,13 @@ import org.hswebframework.web.entity.schedule.ScheduleJobEntity;
 import org.hswebframework.web.service.CrudService;
 
 /**
- *  调度任务 服务类
+ * 调度任务 服务类
  *
  * @author hsweb-generator-online
  */
 public interface ScheduleJobService extends CrudService<ScheduleJobEntity, String> {
 
+    void enable(String id);
+
+    void disable(String id);
 }

+ 12 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-api/src/main/java/org/hswebframework/web/service/schedule/ScheduleTriggerBuilder.java

@@ -0,0 +1,12 @@
+package org.hswebframework.web.service.schedule;
+
+import org.quartz.spi.MutableTrigger;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public interface ScheduleTriggerBuilder {
+    MutableTrigger buildTrigger(String config);
+}

+ 46 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DefaultScriptScheduleJobExecutor.java

@@ -0,0 +1,46 @@
+package org.hswebframework.web.service.schedule.simple;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.hswebframework.expands.script.engine.DynamicScriptEngine;
+import org.hswebframework.expands.script.engine.DynamicScriptEngineFactory;
+import org.hswebframework.web.entity.schedule.ScheduleJobEntity;
+import org.hswebframework.web.service.schedule.ScheduleJobExecutor;
+import org.hswebframework.web.service.schedule.ScheduleJobService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author zhouhao
+ */
+@Service
+public class DefaultScriptScheduleJobExecutor implements ScheduleJobExecutor {
+
+    private ScheduleJobService scheduleJobService;
+
+    @Autowired
+    public void setScheduleJobService(ScheduleJobService scheduleJobService) {
+        this.scheduleJobService = scheduleJobService;
+    }
+
+    @Override
+    public Object doExecuteJob(String jobId, Map<String, Object> parameter) {
+        try {
+            ScheduleJobEntity jobEntity = scheduleJobService.selectByPk(jobId);
+            if (null == jobEntity) {
+                return null;
+            }
+            DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(jobEntity.getLanguage());
+
+            String jobMd5 = DigestUtils.md5Hex(jobEntity.getScript());
+            //脚本发生变化,重新编译执行
+            if (!jobMd5.equals(engine.getContext(jobId).getMd5())) {
+                engine.compile(jobId, jobEntity.getScript());
+            }
+            return engine.execute(jobId, parameter).getIfSuccess();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 19 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DynamicJob.java

@@ -0,0 +1,19 @@
+package org.hswebframework.web.service.schedule.simple;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@DisallowConcurrentExecution
+public class DynamicJob implements Job {
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+
+    }
+}

+ 42 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/DynamicJobFactory.java

@@ -0,0 +1,42 @@
+package org.hswebframework.web.service.schedule.simple;
+
+import org.hswebframework.web.service.schedule.ScheduleJobExecutor;
+import org.quartz.Job;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.spi.JobFactory;
+import org.quartz.spi.TriggerFiredBundle;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Map;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class DynamicJobFactory implements JobFactory {
+
+    public static final String JOB_ID_KEY = "dynamic-job-id:";
+
+    private JobFactory defaultFactory;
+
+    private ScheduleJobExecutor scheduleJobExecutor;
+
+    public DynamicJobFactory(JobFactory defaultFactory) {
+        this.defaultFactory = defaultFactory;
+    }
+
+    @Autowired
+    public void setScheduleJobExecutor(ScheduleJobExecutor scheduleJobExecutor) {
+        this.scheduleJobExecutor = scheduleJobExecutor;
+    }
+
+    @Override
+    public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
+        Map<String, Object> data = bundle.getJobDetail().getJobDataMap();
+        String jobId = (String) data.get(JOB_ID_KEY);
+        if (null == jobId || bundle.getJobDetail().getJobClass() != DynamicJob.class) return defaultFactory.newJob(bundle, scheduler);
+        return  context -> scheduleJobExecutor.doExecuteJob(jobId, data);
+    }
+}

+ 117 - 2
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/SimpleScheduleJobService.java

@@ -1,12 +1,26 @@
 package org.hswebframework.web.service.schedule.simple;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.hswebframework.web.BusinessException;
+import org.hswebframework.web.commons.entity.DataStatus;
 import org.hswebframework.web.dao.schedule.ScheduleJobDao;
 import org.hswebframework.web.entity.schedule.ScheduleJobEntity;
-import org.hswebframework.web.service.GenericEntityService;
 import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.service.GenericEntityService;
 import org.hswebframework.web.service.schedule.ScheduleJobService;
+import org.hswebframework.web.service.schedule.ScheduleTriggerBuilder;
+import org.quartz.*;
+import org.quartz.spi.MutableTrigger;
+import org.quartz.spi.OperableTrigger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * 默认的服务实现
@@ -18,13 +32,114 @@ public class SimpleScheduleJobService extends GenericEntityService<ScheduleJobEn
         implements ScheduleJobService {
     @Autowired
     private ScheduleJobDao scheduleJobDao;
-   @Override
+
+    @Autowired
+    protected Scheduler scheduler;
+
+    @Autowired
+    private ScheduleTriggerBuilder scheduleTriggerBuilder;
+
+    @Override
     protected IDGenerator<String> getIDGenerator() {
         return IDGenerator.MD5;
     }
+
     @Override
     public ScheduleJobDao getDao() {
         return scheduleJobDao;
     }
 
+    public static List<Date> computeFireTimesBetween(OperableTrigger trigger,
+                                                     org.quartz.Calendar cal, Date from, Date to, int num) {
+        List<Date> lst = new LinkedList<>();
+        OperableTrigger t = (OperableTrigger) trigger.clone();
+        if (t.getNextFireTime() == null) {
+            t.setStartTime(from);
+            t.setEndTime(to);
+            t.computeFirstFireTime(cal);
+        }
+        for (int i = 0; i < num; i++) {
+            Date d = t.getNextFireTime();
+            if (d != null) {
+                if (d.before(from)) {
+                    t.triggered(cal);
+                    continue;
+                }
+                if (d.after(to)) {
+                    break;
+                }
+                lst.add(d);
+                t.triggered(cal);
+            } else {
+                break;
+            }
+        }
+        return lst;
+    }
+
+    protected void startJob(ScheduleJobEntity jobEntity) {
+        JobDetail jobDetail = JobBuilder
+                .newJob(DynamicJob.class)
+                .withIdentity(createJobKey(jobEntity))
+                .setJobData(createJobDataMap(jobEntity.getParameters()))
+                .usingJobData(DynamicJobFactory.JOB_ID_KEY, jobEntity.getId())
+                .withDescription(jobEntity.getName() + (jobEntity.getRemark() == null ? "" : jobEntity.getRemark()))
+                .build();
+        MutableTrigger trigger = scheduleTriggerBuilder.buildTrigger(jobEntity.getQuartzConfig());
+        trigger.setKey(createTriggerKey(jobEntity));
+        try {
+            scheduler.scheduleJob(jobDetail, trigger);
+        } catch (SchedulerException e) {
+            throw new BusinessException("启动定时调度失败", e);
+        }
+    }
+
+    protected JobDataMap createJobDataMap(String parameters) {
+        JobDataMap map = new JobDataMap();
+        if (!StringUtils.isEmpty(parameters)) {
+            JSONArray jsonArray = JSON.parseArray(parameters);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                JSONObject o = jsonArray.getJSONObject(i);
+                map.put(o.getString("key"), o.get("value"));
+            }
+        }
+        return map;
+    }
+
+    protected JobKey createJobKey(ScheduleJobEntity jobEntity) {
+        String group = jobEntity.getType() == null ? "hsweb.scheduler" : jobEntity.getType();
+
+        return new JobKey(jobEntity.getId(), group);
+    }
+
+    protected TriggerKey createTriggerKey(ScheduleJobEntity jobEntity) {
+        String group = jobEntity.getType() == null ? "hsweb.scheduler" : jobEntity.getType();
+
+        return new TriggerKey(jobEntity.getId(), group);
+    }
+
+    @Override
+    public void enable(String id) {
+        createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_ENABLED)
+                .where(ScheduleJobEntity.id, id).exec();
+        startJob(selectByPk(id));
+    }
+
+    private void deleteJob(ScheduleJobEntity jobEntity) {
+        JobKey jobKey = createJobKey(jobEntity);
+        try {
+            if (scheduler.checkExists(jobKey)) {
+                scheduler.deleteJob(jobKey);
+            }
+        } catch (SchedulerException e) {
+            throw new BusinessException("更新任务失败", e, 500);
+        }
+    }
+
+    @Override
+    public void disable(String id) {
+        createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_DISABLED)
+                .where(ScheduleJobEntity.id, id).exec();
+        deleteJob(selectByPk(id));
+    }
 }

+ 30 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-service/hsweb-system-schedule-service-simple/src/main/java/org/hswebframework/web/service/schedule/simple/SmartScheduleTriggerBuilder.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.service.schedule.simple;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.hswebframework.web.service.schedule.ScheduleTriggerBuilder;
+import org.quartz.CronScheduleBuilder;
+import org.quartz.spi.MutableTrigger;
+import org.springframework.stereotype.Service;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@Service
+public class SmartScheduleTriggerBuilder implements ScheduleTriggerBuilder {
+    @Override
+    public MutableTrigger buildTrigger(String config) {
+        JSONObject configObj = JSON.parseObject(config);
+        switch (configObj.getString("type")) {
+            case "cron":
+                String cron = configObj.getString("config");
+                return CronScheduleBuilder.cronSchedule(cron)
+                        .build();
+            default:
+                throw new UnsupportedOperationException(config);
+        }
+
+    }
+}

+ 5 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/pom.xml

@@ -40,6 +40,11 @@
             <version>${project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>

+ 51 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/AutoCreateTable.java

@@ -0,0 +1,51 @@
+package org.hswebframework.web.schedule.configuration;
+
+import org.hsweb.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.utils.file.FileUtils;
+import org.hswebframework.web.Sqls;
+import org.hswebframework.web.datasource.DataSourceHolder;
+import org.hswebframework.web.datasource.DatabaseType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.List;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class AutoCreateTable implements CommandLineRunner {
+
+    @Autowired
+    private SqlExecutor sqlExecutor;
+
+    @Override
+    public void run(String... args) throws Exception {
+        if (sqlExecutor.tableExists("QRTZ_LOCKS")) return;
+
+        DatabaseType databaseType = DataSourceHolder.currentDatabaseType();
+        String databaseTypeName = databaseType.name();
+        if (databaseType == DatabaseType.jtds_sqlserver) {
+            databaseTypeName = DatabaseType.sqlserver.name();
+        }
+        String file = "classpath*:/quartz/sql/quartz-" + databaseTypeName + "-create.sql";
+        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(file);
+
+        for (Resource resource : resources) {
+            try (Reader reader = new InputStreamReader(resource.getInputStream())) {
+                String str = FileUtils.reader2String(reader);
+                List<String> sqlList = Sqls.parse(str);
+                for (String sql : sqlList) {
+                    sqlExecutor.exec(sql);
+                }
+            }
+        }
+    }
+}

+ 81 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/ScheduleAutoConfiguration.java

@@ -0,0 +1,81 @@
+package org.hswebframework.web.schedule.configuration;
+
+import org.hswebframework.web.datasource.DataSourceHolder;
+import org.hswebframework.web.datasource.DatabaseType;
+import org.hswebframework.web.service.schedule.simple.DynamicJobFactory;
+import org.quartz.Calendar;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerListener;
+import org.quartz.impl.StdSchedulerFactory;
+import org.quartz.spi.JobFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.quartz.AdaptableJobFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import javax.sql.DataSource;
+import java.util.Map;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@Configuration
+@EnableConfigurationProperties(SchedulerProperties.class)
+@ConditionalOnMissingBean({Scheduler.class, SchedulerFactoryBean.class})
+public class ScheduleAutoConfiguration {
+    @Autowired
+    private SchedulerProperties schedulerProperties;
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Autowired
+    private PlatformTransactionManager platformTransactionManager;
+
+    @Autowired(required = false)
+    private Map<String, Calendar> calendarMap;
+
+    @Autowired(required = false)
+    private SchedulerListener[] schedulerListeners;
+
+    @Bean
+    public JobFactory jobFactory() {
+        return new DynamicJobFactory(new AdaptableJobFactory());
+    }
+
+    @Bean
+    public AutoCreateTable autoCreateTable() {
+        return new AutoCreateTable();
+    }
+
+    @Bean
+    public SchedulerFactoryBean schedulerFactory(JobFactory jobFactory) {
+        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+        schedulerFactoryBean.setApplicationContext(applicationContext);
+        schedulerFactoryBean.setAutoStartup(schedulerProperties.isAutoStartup());
+        schedulerFactoryBean.setDataSource(dataSource);
+        schedulerFactoryBean.setTransactionManager(platformTransactionManager);
+        schedulerFactoryBean.setOverwriteExistingJobs(schedulerProperties.isOverwriteExistingJobs());
+        schedulerFactoryBean.setSchedulerFactoryClass(StdSchedulerFactory.class);
+        schedulerFactoryBean.setBeanName(schedulerProperties.getBeanName());
+        schedulerFactoryBean.setJobFactory(jobFactory);
+        schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(schedulerProperties.isWaitOnShutdown());
+        schedulerFactoryBean.setQuartzProperties(schedulerProperties.getProperties());
+        schedulerFactoryBean.setStartupDelay(schedulerProperties.getStartupDelay());
+        schedulerFactoryBean.setCalendars(calendarMap);
+        schedulerFactoryBean.setSchedulerListeners(schedulerListeners);
+        return schedulerFactoryBean;
+    }
+
+
+}

+ 84 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/java/org/hswebframework/web/schedule/configuration/SchedulerProperties.java

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015-2016 http://hsweb.me
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hswebframework.web.schedule.configuration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.Properties;
+
+@ConfigurationProperties(prefix = "scheduler")
+public class SchedulerProperties {
+    private boolean autoStartup = true;
+
+    private boolean overwriteExistingJobs = true;
+
+    private String beanName = "scheduler";
+
+    private boolean waitOnShutdown = true;
+
+    private int startupDelay = 5;
+
+    private Properties properties = new Properties();
+
+    public boolean isAutoStartup() {
+        return autoStartup;
+    }
+
+    public void setAutoStartup(boolean autoStartup) {
+        this.autoStartup = autoStartup;
+    }
+
+    public boolean isOverwriteExistingJobs() {
+        return overwriteExistingJobs;
+    }
+
+    public void setOverwriteExistingJobs(boolean overwriteExistingJobs) {
+        this.overwriteExistingJobs = overwriteExistingJobs;
+    }
+
+    public String getBeanName() {
+        return beanName;
+    }
+
+    public void setBeanName(String beanName) {
+        this.beanName = beanName;
+    }
+
+    public boolean isWaitOnShutdown() {
+        return waitOnShutdown;
+    }
+
+    public void setWaitOnShutdown(boolean waitOnShutdown) {
+        this.waitOnShutdown = waitOnShutdown;
+    }
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
+
+    public int getStartupDelay() {
+        return startupDelay;
+    }
+
+    public void setStartupDelay(int startupDelay) {
+        this.startupDelay = startupDelay;
+    }
+}

+ 2 - 2
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/hsweb-starter.js

@@ -25,10 +25,10 @@ function install(context) {
         .addColumn().name("u_id").alias("id").comment("ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).primaryKey().commit()
         .addColumn().name("name").alias("name").comment("任务名称").jdbcType(java.sql.JDBCType.VARCHAR).length(128).commit()
         .addColumn().name("remark").alias("remark").comment("备注").jdbcType(java.sql.JDBCType.VARCHAR).length(512).commit()
-        .addColumn().name("quartz_config").alias("quartz_config").comment("定时调度配置").jdbcType(java.sql.JDBCType.CLOB).commit()
+        .addColumn().name("quartz_config").alias("quartzConfig").comment("定时调度配置").jdbcType(java.sql.JDBCType.CLOB).commit()
         .addColumn().name("script").alias("script").comment("执行脚本").jdbcType(java.sql.JDBCType.CLOB).commit()
         .addColumn().name("language").alias("language").comment("脚本语言").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
-        .addColumn().name("enabled").alias("enabled").comment("是否启用").jdbcType(java.sql.JDBCType.DECIMAL).length(4,0).commit()
+        .addColumn().name("status").alias("status").comment("是否启用").jdbcType(java.sql.JDBCType.DECIMAL).length(4,0).commit()
         .addColumn().name("parameters").alias("parameters").comment("启动参数").jdbcType(java.sql.JDBCType.CLOB).commit()
         .addColumn().name("type").alias("type").comment("任务类型").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
         .addColumn().name("tags").alias("tags").comment("标签").jdbcType(java.sql.JDBCType.VARCHAR).length(512).commit()

+ 247 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-h2-create.sql

@@ -0,0 +1,247 @@
+-- Thanks to Amir Kibbar and Peter Rietzler for contributing the schema for H2 database, 
+-- and verifying that it works with Quartz's StdJDBCDelegate
+--
+-- Note, Quartz depends on row-level locking which means you must use the MVCC=TRUE 
+-- setting on your H2 database, or you will experience dead-locks
+--
+--
+-- In your Quartz properties file, you'll need to set 
+-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+
+CREATE TABLE QRTZ_CALENDARS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  CALENDAR_NAME VARCHAR (200)  NOT NULL ,
+  CALENDAR IMAGE NOT NULL
+);
+
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  CRON_EXPRESSION VARCHAR (120)  NOT NULL ,
+  TIME_ZONE_ID VARCHAR (80) 
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  ENTRY_ID VARCHAR (95)  NOT NULL ,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  INSTANCE_NAME VARCHAR (200)  NOT NULL ,
+  FIRED_TIME BIGINT NOT NULL ,
+  SCHED_TIME BIGINT NOT NULL ,
+  PRIORITY INTEGER NOT NULL ,
+  STATE VARCHAR (16)  NOT NULL,
+  JOB_NAME VARCHAR (200)  NULL ,
+  JOB_GROUP VARCHAR (200)  NULL ,
+  IS_NONCONCURRENT BOOLEAN  NULL ,
+  REQUESTS_RECOVERY BOOLEAN  NULL 
+);
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL 
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  INSTANCE_NAME VARCHAR (200)  NOT NULL ,
+  LAST_CHECKIN_TIME BIGINT NOT NULL ,
+  CHECKIN_INTERVAL BIGINT NOT NULL
+);
+
+CREATE TABLE QRTZ_LOCKS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  LOCK_NAME VARCHAR (40)  NOT NULL 
+);
+
+CREATE TABLE QRTZ_JOB_DETAILS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  JOB_NAME VARCHAR (200)  NOT NULL ,
+  JOB_GROUP VARCHAR (200)  NOT NULL ,
+  DESCRIPTION VARCHAR (250) NULL ,
+  JOB_CLASS_NAME VARCHAR (250)  NOT NULL ,
+  IS_DURABLE BOOLEAN  NOT NULL ,
+  IS_NONCONCURRENT BOOLEAN  NOT NULL ,
+  IS_UPDATE_DATA BOOLEAN  NOT NULL ,
+  REQUESTS_RECOVERY BOOLEAN  NOT NULL ,
+  JOB_DATA IMAGE NULL
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  REPEAT_COUNT BIGINT NOT NULL ,
+  REPEAT_INTERVAL BIGINT NOT NULL ,
+  TIMES_TRIGGERED BIGINT NOT NULL
+);
+
+CREATE TABLE qrtz_simprop_triggers
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INTEGER NULL,
+    INT_PROP_2 INTEGER NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 BOOLEAN NULL,
+    BOOL_PROP_2 BOOLEAN NULL,
+);
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  BLOB_DATA IMAGE NULL
+);
+
+CREATE TABLE QRTZ_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  JOB_NAME VARCHAR (200)  NOT NULL ,
+  JOB_GROUP VARCHAR (200)  NOT NULL ,
+  DESCRIPTION VARCHAR (250) NULL ,
+  NEXT_FIRE_TIME BIGINT NULL ,
+  PREV_FIRE_TIME BIGINT NULL ,
+  PRIORITY INTEGER NULL ,
+  TRIGGER_STATE VARCHAR (16)  NOT NULL ,
+  TRIGGER_TYPE VARCHAR (8)  NOT NULL ,
+  START_TIME BIGINT NOT NULL ,
+  END_TIME BIGINT NULL ,
+  CALENDAR_NAME VARCHAR (200)  NULL ,
+  MISFIRE_INSTR SMALLINT NULL ,
+  JOB_DATA IMAGE NULL
+);
+
+ALTER TABLE QRTZ_CALENDARS  ADD
+  CONSTRAINT PK_QRTZ_CALENDARS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    CALENDAR_NAME
+  );
+
+ALTER TABLE QRTZ_CRON_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_CRON_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_FIRED_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_FIRED_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    ENTRY_ID
+  );
+
+ALTER TABLE QRTZ_PAUSED_TRIGGER_GRPS  ADD
+  CONSTRAINT PK_QRTZ_PAUSED_TRIGGER_GRPS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_SCHEDULER_STATE  ADD
+  CONSTRAINT PK_QRTZ_SCHEDULER_STATE PRIMARY KEY  
+  (
+    SCHED_NAME,
+    INSTANCE_NAME
+  );
+
+ALTER TABLE QRTZ_LOCKS  ADD
+  CONSTRAINT PK_QRTZ_LOCKS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    LOCK_NAME
+  );
+
+ALTER TABLE QRTZ_JOB_DETAILS  ADD
+  CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  );
+
+ALTER TABLE QRTZ_SIMPLE_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_SIMPLE_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_SIMPROP_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_SIMPROP_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_CRON_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+
+ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+
+ALTER TABLE QRTZ_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS FOREIGN KEY
+  (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  ) REFERENCES QRTZ_JOB_DETAILS (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  );

+ 143 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-mysql-create.sql

@@ -0,0 +1,143 @@
+CREATE TABLE QRTZ_JOB_DETAILS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL,
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
+    IS_DURABLE VARCHAR(1) NOT NULL,
+    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
+    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL,
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    NEXT_FIRE_TIME BIGINT(13) NULL,
+    PREV_FIRE_TIME BIGINT(13) NULL,
+    PRIORITY INTEGER NULL,
+    TRIGGER_STATE VARCHAR(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR(8) NOT NULL,
+    START_TIME BIGINT(13) NOT NULL,
+    END_TIME BIGINT(13) NULL,
+    CALENDAR_NAME VARCHAR(200) NULL,
+    MISFIRE_INSTR SMALLINT(2) NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    REPEAT_COUNT BIGINT(7) NOT NULL,
+    REPEAT_INTERVAL BIGINT(12) NOT NULL,
+    TIMES_TRIGGERED BIGINT(10) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CRON_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR(200) NOT NULL,
+    TIME_ZONE_ID VARCHAR(80),
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR(1) NULL,
+    BOOL_PROP_2 VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CALENDARS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR(200) NOT NULL,
+    CALENDAR BLOB NOT NULL,
+    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(200) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    ENTRY_ID VARCHAR(95) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    FIRED_TIME BIGINT(13) NOT NULL,
+    SCHED_TIME BIGINT(13) NOT NULL,
+    PRIORITY INTEGER NOT NULL,
+    STATE VARCHAR(16) NOT NULL,
+    JOB_NAME VARCHAR(200) NULL,
+    JOB_GROUP VARCHAR(200) NULL,
+    IS_NONCONCURRENT VARCHAR(1) NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
+    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+
+CREATE TABLE QRTZ_LOCKS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    LOCK_NAME  VARCHAR(40) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);

+ 157 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/main/resources/quartz/sql/quartz-oracle-create.sql

@@ -0,0 +1,157 @@
+CREATE TABLE qrtz_job_details
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL,
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    JOB_CLASS_NAME   VARCHAR2(250) NOT NULL,
+    IS_DURABLE VARCHAR2(1) NOT NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
+    IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+CREATE TABLE qrtz_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL,
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    NEXT_FIRE_TIME NUMBER(13) NULL,
+    PREV_FIRE_TIME NUMBER(13) NULL,
+    PRIORITY NUMBER(13) NULL,
+    TRIGGER_STATE VARCHAR2(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR2(8) NOT NULL,
+    START_TIME NUMBER(13) NOT NULL,
+    END_TIME NUMBER(13) NULL,
+    CALENDAR_NAME VARCHAR2(200) NULL,
+    MISFIRE_INSTR NUMBER(2) NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+      REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+CREATE TABLE qrtz_simple_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    REPEAT_COUNT NUMBER(7) NOT NULL,
+    REPEAT_INTERVAL NUMBER(12) NOT NULL,
+    TIMES_TRIGGERED NUMBER(10) NOT NULL,
+    CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_cron_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR2(120) NOT NULL,
+    TIME_ZONE_ID VARCHAR2(80),
+    CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_simprop_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    STR_PROP_1 VARCHAR2(512) NULL,
+    STR_PROP_2 VARCHAR2(512) NULL,
+    STR_PROP_3 VARCHAR2(512) NULL,
+    INT_PROP_1 NUMBER(10) NULL,
+    INT_PROP_2 NUMBER(10) NULL,
+    LONG_PROP_1 NUMBER(13) NULL,
+    LONG_PROP_2 NUMBER(13) NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR2(1) NULL,
+    BOOL_PROP_2 VARCHAR2(1) NULL,
+    CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_blob_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_calendars
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR2(200) NOT NULL,
+    CALENDAR BLOB NOT NULL,
+    CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR2(200) NOT NULL,
+    CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_fired_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    ENTRY_ID VARCHAR2(95) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    FIRED_TIME NUMBER(13) NOT NULL,
+    SCHED_TIME NUMBER(13) NOT NULL,
+    PRIORITY NUMBER(13) NOT NULL,
+    STATE VARCHAR2(16) NOT NULL,
+    JOB_NAME VARCHAR2(200) NULL,
+    JOB_GROUP VARCHAR2(200) NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NULL,
+    CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+CREATE TABLE qrtz_scheduler_state
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    LAST_CHECKIN_TIME NUMBER(13) NOT NULL,
+    CHECKIN_INTERVAL NUMBER(13) NOT NULL,
+    CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+CREATE TABLE qrtz_locks
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    LOCK_NAME  VARCHAR2(40) NOT NULL,
+    CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+
+create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
+
+create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
+create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
+create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
+create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
+create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
+

+ 39 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/test/java/org/hswebframework/web/schedule/test/DynamicScheduleTests.java

@@ -0,0 +1,39 @@
+package org.hswebframework.web.schedule.test;
+
+import org.hswebframework.web.commons.entity.DataStatus;
+import org.hswebframework.web.entity.schedule.ScheduleJobEntity;
+import org.hswebframework.web.service.schedule.ScheduleJobService;
+import org.hswebframework.web.tests.SimpleWebApplicationTests;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class DynamicScheduleTests extends SimpleWebApplicationTests {
+
+    @Autowired
+    private ScheduleJobService scheduleJobService;
+
+
+    public ScheduleJobEntity createJob() {
+        ScheduleJobEntity entity = scheduleJobService.createEntity();
+        entity.setStatus(DataStatus.STATUS_ENABLED);
+        entity.setType("test");
+        entity.setLanguage("javascript");
+        entity.setScript("java.lang.System.out.println('job running...')");
+        entity.setQuartzConfig("{\"type\":\"cron\",\"config\":\"0/5 * * * * ?\"}");
+        return entity;
+    }
+
+    @Test
+    public void testCreateJob() throws InterruptedException {
+        Thread.sleep(5000);
+        String id = scheduleJobService.insert(createJob());
+        scheduleJobService.enable(id);
+
+        Thread.sleep(40000);
+    }
+}

+ 35 - 0
hsweb-system/hsweb-system-schedule/hsweb-system-schedule-starter/src/test/java/org/hswebframework/web/schedule/test/ScheduleTests.java

@@ -0,0 +1,35 @@
+package org.hswebframework.web.schedule.test;
+
+import org.hswebframework.web.tests.SimpleWebApplicationTests;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@EnableScheduling
+@Configuration
+public class ScheduleTests extends SimpleWebApplicationTests {
+
+    AtomicInteger counter = new AtomicInteger();
+
+    @Scheduled(cron = "0/1 * * * * ?")
+    public void quartzTest() {
+        System.out.println(1234);
+        counter.incrementAndGet();
+    }
+
+    @Test
+    public void test() throws InterruptedException {
+        Thread.sleep(10000);
+        Assert.assertTrue(counter.get() > 0);
+        System.out.println(counter.get());
+    }
+}

+ 9 - 0
hsweb-system/hsweb-system-schedule/pom.xml

@@ -18,4 +18,13 @@
         <module>hsweb-system-schedule-starter</module>
     </modules>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.quartz-scheduler</groupId>
+                <artifactId>quartz</artifactId>
+                <version>2.2.3</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 </project>

+ 3 - 1
hsweb-system/hsweb-system-script/hsweb-system-script-service/hsweb-system-script-service-simple/src/main/java/org/hswebframework/web/service/script/simple/SimpleScriptService.java

@@ -18,10 +18,12 @@ public class SimpleScriptService extends GenericEntityService<ScriptEntity, Stri
         implements ScriptService {
     @Autowired
     private ScriptDao scriptDao;
-   @Override
+
+    @Override
     protected IDGenerator<String> getIDGenerator() {
         return IDGenerator.MD5;
     }
+
     @Override
     public ScriptDao getDao() {
         return scriptDao;