diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/AbstractException.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/AbstractException.java
new file mode 100644
index 00000000..e2a78371
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/AbstractException.java
@@ -0,0 +1,28 @@
+package group.idealworld.dew.errorInfo;
+
+/**
+ * 自定义全局异常.
+ * @author nipeixuan
+ */
+public abstract class AbstractException extends RuntimeException implements ErrorInfo {
+
+ public AbstractException() {
+ super();
+ }
+
+ public AbstractException(String message) {
+ super(message);
+ }
+
+ public AbstractException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AbstractException(Throwable cause) {
+ super(cause);
+ }
+
+ protected AbstractException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
\ No newline at end of file
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientErrorCodeMark.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientErrorCodeMark.java
new file mode 100644
index 00000000..27df984f
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientErrorCodeMark.java
@@ -0,0 +1,56 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.Getter;
+
+/**
+ * 客户端异常标记接口。
+ * 用于标记{@link ClientException}对象的错误码参数类型,防止错误码串用.
+ * @author nipeixuan
+ */
+public interface ClientErrorCodeMark extends ErrorInfo {
+
+ @Getter
+ enum Code implements ClientErrorCodeMark {
+
+ PARAMETER_ERROR("errorCode 1", "parameter error"),
+
+ FREQUENTLY("errorCode 2", "the operation is too frequent. Please try again later"),
+ ;
+
+ Code(String errorCode) {
+ this.errorCode = errorCode;
+ }
+ Code(String errorCode, String errorDesc) {
+ this.errorCode = errorCode;
+ this.errorDesc = errorDesc;
+ }
+
+ /**
+ * 错误码.
+ */
+ private String errorCode;
+ /**
+ * 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.
+ */
+ private String errorDesc;
+ }
+
+ /**
+ * 快速构建一个自定义错误描述错误信息对象.
+ */
+ default ClientErrorCodeMark as(String desc) {
+ ErrorInfo errorInfo = this;
+ return new ClientErrorCodeMark() {
+ @Override
+ public String getErrorCode() {
+ return errorInfo.getErrorCode();
+ }
+
+ @Override
+ public String getErrorDesc() {
+ return desc;
+ }
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientException.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientException.java
new file mode 100644
index 00000000..39681cc4
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ClientException.java
@@ -0,0 +1,59 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author nipeixuan
+ */
+public class ClientException extends AbstractException {
+
+ private ErrorInfo errorCode;
+ /**
+ * 本地错误描述信息,其优先级高于{@link ErrorInfo}中的errorDesc,即如果该值不为空,则以该值为准
+ */
+ @Setter
+ private String errorDesc;
+
+ public ClientException(ClientErrorCodeMark errorCode) {
+ super();
+ this.errorCode = errorCode;
+ }
+
+ public ClientException(ClientErrorCodeMark errorCode, String message) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ public ClientException(ClientErrorCodeMark errorCode, Throwable cause) {
+ super(cause);
+ this.errorCode = errorCode;
+ }
+
+ public ClientException(ClientErrorCodeMark errorCode, String message, Throwable cause) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ @Override
+ public String getErrorCode() {
+ return errorCode.getErrorCode();
+ }
+
+ @Override
+ public String getErrorDesc() {
+ if (!StringUtils.isEmpty(errorDesc)) {
+ return errorDesc;
+ }
+ return errorCode.getErrorDesc();
+ }
+
+ @Override
+ public String getMessage() {
+ String message = super.getMessage();
+ if (StringUtils.isEmpty(message)) {
+ message = this.getErrorDesc();
+ }
+ return message;
+ }
+}
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ErrorInfo.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ErrorInfo.java
new file mode 100644
index 00000000..be06d9d5
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ErrorInfo.java
@@ -0,0 +1,16 @@
+package group.idealworld.dew.errorInfo;
+
+/**
+ * 公共接口,能获取错误描述和错误码.
+ *
+ * @author nipeixuan
+ */
+public interface ErrorInfo {
+
+
+ String getErrorCode();
+
+
+ String getErrorDesc();
+
+}
\ No newline at end of file
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleErrorCodeMark.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleErrorCodeMark.java
new file mode 100644
index 00000000..36d33d17
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleErrorCodeMark.java
@@ -0,0 +1,61 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.Getter;
+
+public interface ModuleErrorCodeMark extends ErrorInfo{
+
+ @Getter
+ enum Code implements ModuleErrorCodeMark {
+
+ HAZELCAST_ERROR("errorCode8", "hazelcast error"),
+
+ MQTT_ERROR("errorCode9", "mqtt error"),
+
+ RABBIT_ERROR("errorCode10", "rabbit error"),
+
+ RADIS_ERROR("errorCode11", "redis error"),
+
+ ROCKET_ERROR("errorCode12", "rocket error"),
+
+ DBUTILS_ERROR("errorCode13", "dbutils error"),
+
+ HBASE_ERROR("errorCode13", "hbase error"),
+
+ ;
+
+ Code(String errorCode) {
+ this.errorCode = errorCode;
+ }
+ Code(String errorCode, String errorDesc) {
+ this.errorCode = errorCode;
+ this.errorDesc = errorDesc;
+ }
+
+ /**
+ * 错误码.
+ */
+ private String errorCode;
+ /**
+ * 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.
+ */
+ private String errorDesc;
+ }
+
+ /**
+ * 快速构建一个自定义错误描述错误信息对象.
+ */
+ default ModuleErrorCodeMark as(String desc) {
+ ErrorInfo errorInfo = this;
+ return new ModuleErrorCodeMark() {
+ @Override
+ public String getErrorCode() {
+ return errorInfo.getErrorCode();
+ }
+ @Override
+ public String getErrorDesc() {
+ return desc;
+ }
+ };
+ }
+
+}
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleException.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleException.java
new file mode 100644
index 00000000..063e3bc2
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/ModuleException.java
@@ -0,0 +1,56 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+public class ModuleException extends AbstractException{
+
+ private ErrorInfo errorCode;
+ /**
+ * 本地错误描述信息,其优先级高于{@link ErrorInfo}中的errorDesc,即如果该值不为空,则以该值为准
+ */
+ @Setter
+ private String errorDesc;
+
+ public ModuleException(ClientErrorCodeMark errorCode) {
+ super();
+ this.errorCode = errorCode;
+ }
+
+ public ModuleException(ClientErrorCodeMark errorCode, String message) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ public ModuleException(ClientErrorCodeMark errorCode, Throwable cause) {
+ super(cause);
+ this.errorCode = errorCode;
+ }
+
+ public ModuleException(ClientErrorCodeMark errorCode, String message, Throwable cause) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ @Override
+ public String getErrorCode() {
+ return errorCode.getErrorCode();
+ }
+
+ @Override
+ public String getErrorDesc() {
+ if (!StringUtils.isEmpty(errorDesc)) {
+ return errorDesc;
+ }
+ return errorCode.getErrorDesc();
+ }
+
+ @Override
+ public String getMessage() {
+ String message = super.getMessage();
+ if (StringUtils.isEmpty(message)) {
+ message = this.getErrorDesc();
+ }
+ return message;
+ }
+}
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemErrorCodeMark.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemErrorCodeMark.java
new file mode 100644
index 00000000..1d56fb4c
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemErrorCodeMark.java
@@ -0,0 +1,77 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 标记接口.
+ * 用于标记{@link SystemException}对象的错误码参数类型,防止错误码串用.
+ * @author nipeixuan
+ */
+public interface SystemErrorCodeMark extends ErrorInfo {
+
+ /**
+ * 我方系统异常错误码枚举
+ */
+ @Getter
+ @AllArgsConstructor
+ enum Code implements SystemErrorCodeMark {
+
+ /**
+ * 系统错误(本系统).
+ */
+ SYSTEM_ERROR_LOCAL("error Code3", "system error"),
+ /**
+ * 系统内部错误(其他服务引起的错误,如通道异常)
+ */
+ SYSTEM_ERROR_OTHER("error Code4", "system busy"),
+
+ // -----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * 系统内部错误
+ */
+ SYS_0001("error code5"),
+ /**
+ * API不存在
+ */
+ SYSTEM_NOT_API("error code6" , "API not exists"),
+ /**
+ * API不存在
+ */
+ HTTP_NOT_SUPPORTED("error code7" , "the request method is not supported"),
+ ;
+
+ Code(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * 错误码.
+ */
+ private String errorCode;
+ /**
+ * 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.
+ */
+ private String errorDesc;
+ }
+
+ /**
+ * 快速构建一个自定义错误描述错误信息对象.
+ */
+ default SystemErrorCodeMark as(String desc) {
+ ErrorInfo errorInfo = this;
+ return new SystemErrorCodeMark() {
+ @Override
+ public String getErrorCode() {
+ return errorInfo.getErrorCode();
+ }
+
+ @Override
+ public String getErrorDesc() {
+ return desc;
+ }
+ };
+ }
+
+}
diff --git a/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemException.java b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemException.java
new file mode 100644
index 00000000..cb162778
--- /dev/null
+++ b/framework/modules/boot-starter/src/main/java/group/idealworld/dew/errorInfo/SystemException.java
@@ -0,0 +1,65 @@
+package group.idealworld.dew.errorInfo;
+
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ *
+ * @author nipeixuan
+ */
+public class SystemException extends AbstractException {
+
+ private ErrorInfo errorCode;
+ /**
+ * 本地错误描述信息,其优先级高于{@link ErrorInfo}中的errorDesc,即如果该值不为空,则以该值为准
+ */
+ @Setter
+ private String errorDesc;
+
+
+ public SystemException(SystemErrorCodeMark errorCode) {
+ super();
+ this.errorCode = errorCode;
+ }
+
+ public SystemException(SystemErrorCodeMark errorCode, String message) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * @param errorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.
+ */
+ public SystemException(SystemErrorCodeMark errorCode, Throwable cause) {
+ super(cause);
+ this.errorCode = errorCode;
+ }
+
+
+ public SystemException(SystemErrorCodeMark errorCode, String message, Throwable cause) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ @Override
+ public String getErrorCode() {
+ return errorCode.getErrorCode();
+ }
+
+ @Override
+ public String getErrorDesc() {
+ if (!StringUtils.isEmpty(errorDesc)) {
+ return errorDesc;
+ }
+ return errorCode.getErrorDesc();
+ }
+
+ @Override
+ public String getMessage() {
+ String message = super.getMessage();
+ if (StringUtils.isEmpty(message)) {
+ message = this.getErrorDesc();
+ }
+ return message;
+ }
+}
diff --git a/framework/modules/dbutils-starter/pom.xml b/framework/modules/dbutils-starter/pom.xml
index e03fb618..a6d89f80 100644
--- a/framework/modules/dbutils-starter/pom.xml
+++ b/framework/modules/dbutils-starter/pom.xml
@@ -1,6 +1,10 @@
+ 11
+ 11
+ UTF-8
+ ${project.build.sourceEncoding}
+ ${project.build.sourceEncoding}
+ ${java.version}
+ ${java.version}
+ ${java.version}
+ 1.7
+ 1.1.23
+ 8.0.21
+ 42.2.14
+
1.4.200
+ 1.26
+ 1.18.12
+ 4.13
+ 1.7.30
diff --git a/framework/modules/quartz-starter/pom.xml b/framework/modules/quartz-starter/pom.xml
new file mode 100644
index 00000000..fa75804f
--- /dev/null
+++ b/framework/modules/quartz-starter/pom.xml
@@ -0,0 +1,61 @@
+
+
+
+
+ 4.0.0
+
+ group.idealworld.dew
+ parent-starter
+ 3.0.0-Beta3
+ ../parent-starter
+
+
+ quartz-starter
+ 1.1.4 Dew quartz-
+ Dew 集群 quartz调度
+ jar
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ mysql
+ mysql-connector-java
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
+
+ group.idealworld.dew
+ test-starter
+
+
+
+
diff --git a/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfig.java b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfig.java
new file mode 100644
index 00000000..73e0fe39
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfig.java
@@ -0,0 +1,28 @@
+package group.idealworld.dew.core.quartz;
+
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+
+import java.io.IOException;
+
+@Configuration
+public class QuartzConfig {
+
+
+ @Bean
+ public QuartzTemplate quartzTemplate(Scheduler scheduler){
+ return new QuartzTemplate(scheduler);
+ }
+
+ @Bean
+ public SimpleSchedulerListener simpleSchedulerListener(){
+ return new SimpleSchedulerListener();
+ }
+
+
+}
\ No newline at end of file
diff --git a/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfigDTO.java b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfigDTO.java
new file mode 100644
index 00000000..1df82f01
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzConfigDTO.java
@@ -0,0 +1,80 @@
+package group.idealworld.dew.core.quartz;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class QuartzConfigDTO implements Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务名称
+ */
+ private String jobName;
+
+ /**
+ * 任务所属组
+ */
+ private String groupName;
+
+ /**
+ * 任务执行类
+ */
+ private String jobClass;
+
+ /**
+ * 任务调度时间表达式
+ */
+ private String cronExpression;
+
+ /**
+ * 附加参数
+ */
+ private Map param;
+
+
+ public String getJobName() {
+ return jobName;
+ }
+
+ public QuartzConfigDTO setJobName(String jobName) {
+ this.jobName = jobName;
+ return this;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public QuartzConfigDTO setGroupName(String groupName) {
+ this.groupName = groupName;
+ return this;
+ }
+
+ public String getJobClass() {
+ return jobClass;
+ }
+
+ public QuartzConfigDTO setJobClass(String jobClass) {
+ this.jobClass = jobClass;
+ return this;
+ }
+
+ public String getCronExpression() {
+ return cronExpression;
+ }
+
+ public QuartzConfigDTO setCronExpression(String cronExpression) {
+ this.cronExpression = cronExpression;
+ return this;
+ }
+
+ public Map getParam() {
+ return param;
+ }
+
+ public QuartzConfigDTO setParam(Map param) {
+ this.param = param;
+ return this;
+ }
+}
diff --git a/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzOperation.java b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzOperation.java
new file mode 100644
index 00000000..cc5ca617
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzOperation.java
@@ -0,0 +1,77 @@
+package group.idealworld.dew.core.quartz;
+
+import org.quartz.SchedulerException;
+
+import java.util.Map;
+
+public interface QuartzOperation {
+ /**
+ * 添加任务可以传参数
+ *
+ * @param clazzName
+ * @param jobKey
+ * @param cronExp
+ * @param param
+ */
+ void addJob(String clazzName, String jobKey, String cronExp, Map param);
+
+ /**
+ * 暂停任务
+ *
+ * @param jobKey
+ */
+ void pauseJob(String jobKey);
+
+ /**
+ * 恢复任务
+ *
+ * @param jobKey
+ */
+ void resumeJob(String jobKey);
+
+ /**
+ * 立即运行一次定时任务
+ *
+ * @param jobKey
+ */
+ void runOnce(String jobKey);
+
+ /**
+ * 更新任务
+ *
+ * @param jobKey
+ * @param cronExp
+ * @param param
+ */
+ void updateJob(String jobKey, String cronExp, Map param);
+
+ /**
+ * 删除任务
+ *
+ * @param jobKey
+ */
+ void deleteJob(String jobKey);
+
+ /**
+ * 启动所有任务
+ */
+ void startAllJobs();
+
+ /**
+ * 暂停所有任务
+ */
+ void pauseAllJobs();
+
+ /**
+ * 恢复所有任务
+ */
+ void resumeAllJobs();
+
+ /**
+ * 关闭所有任务
+ */
+ void shutdownAllJobs();
+
+ boolean checkJob(String jobKey) throws SchedulerException;
+
+}
diff --git a/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzTemplate.java b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzTemplate.java
new file mode 100644
index 00000000..87f89a9a
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/QuartzTemplate.java
@@ -0,0 +1,150 @@
+package group.idealworld.dew.core.quartz;
+
+import org.quartz.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+public class QuartzTemplate implements QuartzOperation {
+
+ private static final Logger log = LoggerFactory.getLogger(QuartzTemplate.class);
+
+ private Scheduler scheduler;
+
+ public QuartzTemplate(Scheduler scheduler){
+ this.scheduler = scheduler;
+ }
+
+ @Override
+ public void addJob(String clazzName, String jobkey, String cronExp, Map param) {
+ try {
+// scheduler.start();
+ //构建job信息
+ Class extends Job> jobClass = (Class extends Job>) Class.forName(clazzName);
+ JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobkey).build();
+ //表达式调度构建器(即任务执行的时间)
+ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
+ //按新的cronExpression表达式构建一个新的trigger
+ CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobkey).withSchedule(scheduleBuilder).build();
+ //获得JobDataMap,写入数据
+ if (param != null) {
+ trigger.getJobDataMap().putAll(param);
+ }
+ scheduler.scheduleJob(jobDetail, trigger);
+ } catch (Exception e) {
+ log.error("创建任务失败", e);
+ }
+ }
+
+ @Override
+ public void pauseJob(String jobKey) {
+ try {
+ scheduler.pauseJob(JobKey.jobKey(jobKey));
+ } catch (SchedulerException e) {
+ log.error("暂停任务失败", e);
+ }
+ }
+
+ @Override
+ public void resumeJob(String jobKey) {
+ try {
+ scheduler.resumeJob(JobKey.jobKey(jobKey));
+ } catch (SchedulerException e) {
+ log.error("恢复任务失败", e);
+ }
+ }
+
+ @Override
+ public void runOnce(String jobKey) {
+ try {
+ scheduler.triggerJob(JobKey.jobKey(jobKey));
+ } catch (SchedulerException e) {
+ log.error("立即运行一次定时任务失败", e);
+ }
+ }
+
+ @Override
+ public void updateJob(String jobKey, String cronExp, Map param) {
+ try {
+ TriggerKey triggerKey = TriggerKey.triggerKey(jobKey);
+ CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
+ if (cronExp != null) {
+ // 表达式调度构建器
+ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
+ // 按新的cronExpression表达式重新构建trigger
+ trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
+ }
+ //修改map
+ if (param != null) {
+ trigger.getJobDataMap().putAll(param);
+ }
+ // 按新的trigger重新设置job执行
+ scheduler.rescheduleJob(triggerKey, trigger);
+ } catch (Exception e) {
+ log.error("更新任务失败", e);
+ }
+ }
+
+ @Override
+ public void deleteJob(String jobKey) {
+ try {
+ //暂停、移除、删除
+ scheduler.pauseTrigger(TriggerKey.triggerKey(jobKey));
+ scheduler.unscheduleJob(TriggerKey.triggerKey(jobKey));
+ scheduler.deleteJob(JobKey.jobKey(jobKey));
+ } catch (Exception e) {
+ log.error("删除任务失败", e);
+ }
+ }
+
+ @Override
+ public void startAllJobs() {
+ try {
+ scheduler.start();
+ } catch (Exception e) {
+ log.error("开启所有的任务失败", e);
+ }
+ }
+
+ @Override
+ public void pauseAllJobs() {
+ try {
+ scheduler.pauseAll();
+ } catch (Exception e) {
+ log.error("暂停所有任务失败", e);
+ }
+ }
+
+ @Override
+ public void resumeAllJobs() {
+ try {
+ scheduler.resumeAll();
+ } catch (Exception e) {
+ log.error("恢复所有任务失败", e);
+ }
+ }
+
+ @Override
+ public void shutdownAllJobs() {
+ try {
+
+ if (!scheduler.isShutdown()) {
+ scheduler.shutdown(true);
+ }
+ } catch (Exception e) {
+ log.error("关闭所有的任务失败", e);
+ }
+ }
+
+ @Override
+ public boolean checkJob(String jobKey) throws SchedulerException {
+ return scheduler.checkExists(new JobKey(jobKey));
+ }
+
+ public String getJobState(String jobKey) throws SchedulerException {
+ return scheduler.getTriggerState(TriggerKey.triggerKey(jobKey)).toString();
+ }
+
+
+}
diff --git a/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/SimpleSchedulerListener.java b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/SimpleSchedulerListener.java
new file mode 100644
index 00000000..fbd622d8
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/java/group/idealworld/dew/core/quartz/SimpleSchedulerListener.java
@@ -0,0 +1,99 @@
+package group.idealworld.dew.core.quartz;
+
+import org.quartz.*;
+import org.quartz.listeners.SchedulerListenerSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SimpleSchedulerListener extends SchedulerListenerSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(SimpleSchedulerListener.class);
+
+ @Override
+ public void jobScheduled(Trigger trigger) {
+ log.info("create job" + trigger.getJobKey());
+ }
+
+ @Override
+ public void jobUnscheduled(TriggerKey triggerKey) {
+ }
+
+ @Override
+ public void triggerFinalized(Trigger trigger) {
+ }
+
+ @Override
+ public void triggerPaused(TriggerKey triggerKey) {
+ }
+
+ @Override
+ public void triggersPaused(String triggerGroup) {
+ }
+
+ @Override
+ public void triggerResumed(TriggerKey triggerKey) {
+ }
+
+ @Override
+ public void triggersResumed(String triggerGroup) {
+ }
+
+ @Override
+ public void jobAdded(JobDetail jobDetail) {
+ log.info("job add: " + jobDetail.getJobClass());
+ }
+
+ @Override
+ public void jobDeleted(JobKey jobKey) {
+ log.info("delete job: " + jobKey);
+ }
+
+ @Override
+ public void jobPaused(JobKey jobKey) {
+ log.info("job paused: " + jobKey);
+ }
+
+ @Override
+ public void jobsPaused(String jobGroup) {
+ log.info("jobGroup paused: " + jobGroup);
+ }
+
+ @Override
+ public void jobResumed(JobKey jobKey) {
+ log.info("job resumed: " + jobKey);
+ }
+
+ @Override
+ public void jobsResumed(String jobGroup) {
+ log.info("jobGroup resumed: " + jobGroup);
+ }
+
+ @Override
+ public void schedulerError(String msg, SchedulerException cause) {
+ cause.printStackTrace();
+ }
+
+ @Override
+ public void schedulerInStandbyMode() {
+ }
+
+ @Override
+ public void schedulerStarted() {
+ }
+
+ @Override
+ public void schedulerStarting() {
+ }
+
+ @Override
+ public void schedulerShutdown() {
+ }
+
+ @Override
+ public void schedulerShuttingdown() {
+ }
+
+ @Override
+ public void schedulingDataCleared() {
+ }
+}
diff --git a/framework/modules/quartz-starter/src/main/resources/META-INF/spring.factories b/framework/modules/quartz-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..7f3c95b4
--- /dev/null
+++ b/framework/modules/quartz-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ group.idealworld.dew.core.quartz.QuartzConfig
diff --git a/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/ClusterTest.java b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/ClusterTest.java
new file mode 100644
index 00000000..ff95bc78
--- /dev/null
+++ b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/ClusterTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021. the original author or authors.
+ *
+ * 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 group.idealworld.dew.core.quartz;
+
+import group.idealworld.dew.test.MySqlExtension;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+/**
+ * Cluster test.
+ *
+ * @author nipeixuan
+ */
+@ExtendWith({SpringExtension.class, MySqlExtension.class})
+@ContextConfiguration(initializers = MySqlExtension.Initializer.class)
+@SpringBootApplication
+@SpringBootTest
+@Testcontainers
+public class ClusterTest {
+
+ @Autowired
+ private QuartzTemplate quartzTemplate;
+
+ /**
+ * Test mq.
+ *
+ * @throws InterruptedException the interrupted exception
+ */
+ @Test
+ public void testMQ() throws InterruptedException, SchedulerException {
+ new QuartzTest().testQuartz(quartzTemplate);
+ }
+
+}
diff --git a/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/QuartzTest.java b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/QuartzTest.java
new file mode 100644
index 00000000..70bcbb10
--- /dev/null
+++ b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/QuartzTest.java
@@ -0,0 +1,50 @@
+package group.idealworld.dew.core.quartz;
+
+
+import org.junit.Assert;
+import org.quartz.SchedulerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class QuartzTest {
+
+ private static final Logger log = LoggerFactory.getLogger(QuartzTest.class);
+
+
+ public void test(QuartzTemplate template) throws InterruptedException, SchedulerException {
+ testQuartz(template);
+ testRunOnce(template);
+ startAllJob(template);
+ deleteJob(template);
+ }
+
+
+ public void testQuartz(QuartzTemplate template) throws InterruptedException, SchedulerException {
+ template.addJob("group.idealworld.dew.core.quartz.TfCommandJob", "myJob", "0/1 * * * * ?", null);
+ Assert.assertTrue(template.checkJob("myJob"));
+ template.pauseJob("myJob");
+ Assert.assertEquals("PAUSED",template.getJobState("myJob"));
+ template.resumeJob("myJob");
+ Assert.assertEquals("NORMAL",template.getJobState("myJob"));
+ }
+
+
+ public void testRunOnce(QuartzTemplate template) throws InterruptedException, SchedulerException {
+ template.runOnce("myJob");
+ Assert.assertEquals("NORMAL",template.getJobState("myJob"));
+ }
+
+
+ public void startAllJob(QuartzTemplate template) throws InterruptedException, SchedulerException {
+ template.startAllJobs();
+ Thread.sleep(1000);
+ Assert.assertEquals("NORMAL",template.getJobState("myJob"));
+ }
+
+
+ public void deleteJob(QuartzTemplate template) throws SchedulerException {
+ template.deleteJob("myJob");
+ Assert.assertFalse(template.checkJob("myJob"));
+ }
+
+}
diff --git a/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/TfCommandJob.java b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/TfCommandJob.java
new file mode 100644
index 00000000..256ddae4
--- /dev/null
+++ b/framework/modules/quartz-starter/src/test/java/group/idealworld/dew/core/quartz/TfCommandJob.java
@@ -0,0 +1,25 @@
+package group.idealworld.dew.core.quartz;
+
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.SchedulerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class TfCommandJob implements Job {
+
+ private static final Logger log = LoggerFactory.getLogger(TfCommandJob.class);
+
+ @Override
+ public void execute(JobExecutionContext context) {
+ try {
+ Thread.sleep(3000);
+ log.info(context.getScheduler().getSchedulerInstanceId() + "--" + new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date()));
+ } catch (Exception e) {
+ log.error("任务执行失败",e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/modules/test-starter/src/main/java/group/idealworld/dew/test/MySqlExtension.java b/framework/modules/test-starter/src/main/java/group/idealworld/dew/test/MySqlExtension.java
index 938db235..12e55051 100644
--- a/framework/modules/test-starter/src/main/java/group/idealworld/dew/test/MySqlExtension.java
+++ b/framework/modules/test-starter/src/main/java/group/idealworld/dew/test/MySqlExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022. the original author or authors
+ * Copyright 2021. the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,13 +33,16 @@ public class MySqlExtension implements BeforeAllCallback {
private static final Logger logger = LoggerFactory.getLogger(MySqlExtension.class);
- private static final JdbcDatabaseContainer mysqlContainer = new MySQLContainer(DockerImageName.parse("8").asCompatibleSubstituteFor("mysql"));
+// private static JdbcDatabaseContainer mysqlContainer = new MySQLContainer(DockerImageName.parse("8").asCompatibleSubstituteFor("mysql"));
+
+ private static MySQLContainer mysqlContainer = (MySQLContainer) new MySQLContainer("mysql:8.0.11").withDatabaseName("test")
+ .withUsername("test").withPassword("test").withEnv("MYSQL_ROOT_HOST", "%");
@Override
public void beforeAll(ExtensionContext extensionContext) {
var scriptPath = ClassLoader.getSystemResource("").getPath() + "/sql/init.sql";
if (new File(scriptPath).exists()) {
- mysqlContainer.withInitScript("sql/init.sql");
+ mysqlContainer.withInitScript("init.sql");
}
mysqlContainer.withCommand("--max_allowed_packet=10M");
mysqlContainer.start();
@@ -51,9 +54,10 @@ public static class Initializer
implements ApplicationContextInitializer {
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
TestPropertyValues.of(
- "spring.datasource.url=" + mysqlContainer.getJdbcUrl(),
+ "spring.datasource.url=jdbc:mysql://127.0.0.1:" + mysqlContainer.getFirstMappedPort() + "/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true",
"spring.datasource.username=" + mysqlContainer.getUsername(),
- "spring.datasource.password=" + mysqlContainer.getPassword()
+ "spring.datasource.password=" + mysqlContainer.getPassword(),
+ "spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver"
).applyTo(configurableApplicationContext.getEnvironment());
}
}
diff --git a/framework/modules/test-starter/src/main/resources/broker.conf b/framework/modules/test-starter/src/main/resources/broker.conf
new file mode 100644
index 00000000..29fca1b2
--- /dev/null
+++ b/framework/modules/test-starter/src/main/resources/broker.conf
@@ -0,0 +1,8 @@
+brokerClusterName = DefaultCluster
+brokerName = broker-a
+brokerId = 0
+deleteWhen = 04
+fileReservedTime = 48
+brokerRole = ASYNC_MASTER
+flushDiskType = ASYNC_FLUSH
+brokerIP1 = 127.0.0.1
\ No newline at end of file
diff --git a/framework/pom.xml b/framework/pom.xml
index eb323cda..1367d493 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -1,6 +1,6 @@