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 jobClass = (Class) 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 @@