commit 3e21c706e27476e4b55c17db63a3364c158fec5f
Author: fst1996 <2411194573@qq.com>
Date: Wed Sep 27 09:10:06 2023 +0800
初始化
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..05d7c76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+######################################################################
+# Build Tools
+
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+######################################################################
+# IDE
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### JRebel ###
+rebel.xml
+### NetBeans ###
+nbproject/private/
+build/*
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+target/
+
+######################################################################
+# Others
+*.log
+*.xml.versionsBackup
+*.swp
+
+!*/build/*.java
+!*/build/*.html
+!*/build/*.xml
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..b799d63
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+# 基础镜像
+FROM anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/openjdk:17-8.6
+
+#暴露端口位置
+EXPOSE 9203
+
+# 挂载目录
+VOLUME /home/logs/base-job
+
+# 复制jar文件到docker内部
+COPY /target/base-job.jar /home/app.jar
+
+#工作目录 exec -it 进来默认就是这个目录
+WORKDIR /home
+
+# 启动java程序
+ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-jar","/home/app.jar"]
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..97ad941
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,119 @@
+
+
+
+ com.bawei
+ menghang-base
+ 3.6.0
+
+ 4.0.0
+
+ 3.6.0
+ menghang-base-job
+
+
+ base-job定时任务
+
+
+
+
+ menghang-public
+ 梦航-public
+ http://192.168.111.133:8081/repository/maven-public/
+
+
+
+
+
+ menghang-releases
+ 梦航-releases
+ http://192.168.111.133:8081/repository/maven-releases/
+
+
+
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${swagger.fox.version}
+
+
+
+
+ org.quartz-scheduler
+ quartz
+
+
+ com.mchange
+ c3p0
+
+
+
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+
+ com.bawei
+ menghang-common-log
+ 3.6.0
+
+
+
+
+ com.bawei
+ menghang-common-swagger
+ 3.6.0
+
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/bawei/job/BaWeiJobApplication.java b/src/main/java/com/bawei/job/BaWeiJobApplication.java
new file mode 100644
index 0000000..f3a0528
--- /dev/null
+++ b/src/main/java/com/bawei/job/BaWeiJobApplication.java
@@ -0,0 +1,25 @@
+package com.bawei.job;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import com.bawei.common.security.annotation.EnableCustomConfig;
+import com.bawei.common.security.annotation.EnableRyFeignClients;
+import com.bawei.common.swagger.annotation.EnableCustomSwagger2;
+
+/**
+ * 定时任务
+ *
+ * @author bawei
+ */
+@EnableCustomConfig
+@EnableCustomSwagger2
+@EnableRyFeignClients
+@SpringBootApplication
+public class BaWeiJobApplication
+{
+ public static void main(String[] args)
+ {
+ SpringApplication.run(BaWeiJobApplication.class, args);
+ System.out.println("(♥◠‿◠)ノ゙ 定时任务模块启动成功 ლ(´ڡ`ლ)゙ ");
+ }
+}
diff --git a/src/main/java/com/bawei/job/config/ScheduleConfig.java b/src/main/java/com/bawei/job/config/ScheduleConfig.java
new file mode 100644
index 0000000..c4e7ebe
--- /dev/null
+++ b/src/main/java/com/bawei/job/config/ScheduleConfig.java
@@ -0,0 +1,57 @@
+package com.bawei.job.config;
+
+import java.util.Properties;
+import javax.sql.DataSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+
+/**
+ * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效)
+ *
+ * @author bawei
+ */
+@Configuration
+public class ScheduleConfig
+{
+ @Bean
+ public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
+ {
+ SchedulerFactoryBean factory = new SchedulerFactoryBean();
+ factory.setDataSource(dataSource);
+
+ // quartz参数
+ Properties prop = new Properties();
+ prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
+ prop.put("org.quartz.scheduler.instanceId", "AUTO");
+ // 线程池配置
+ prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+ prop.put("org.quartz.threadPool.threadCount", "20");
+ prop.put("org.quartz.threadPool.threadPriority", "5");
+ // JobStore配置
+ prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+ // 集群配置
+ prop.put("org.quartz.jobStore.isClustered", "true");
+ prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+ prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
+ prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
+
+ // sqlserver 启用
+ // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+ prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+ prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+ factory.setQuartzProperties(prop);
+
+ factory.setSchedulerName("RuoyiScheduler");
+ // 延时启动
+ factory.setStartupDelay(1);
+ factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+ // 可选,QuartzScheduler
+ // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
+ factory.setOverwriteExistingJobs(true);
+ // 设置自动启动,默认为true
+ factory.setAutoStartup(true);
+
+ return factory;
+ }
+}
diff --git a/src/main/java/com/bawei/job/controller/SysJobController.java b/src/main/java/com/bawei/job/controller/SysJobController.java
new file mode 100644
index 0000000..5c2bfe4
--- /dev/null
+++ b/src/main/java/com/bawei/job/controller/SysJobController.java
@@ -0,0 +1,186 @@
+package com.bawei.job.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.bawei.common.core.constant.Constants;
+import com.bawei.common.core.exception.job.TaskException;
+import com.bawei.common.core.utils.StringUtils;
+import com.bawei.common.core.utils.poi.ExcelUtil;
+import com.bawei.common.core.web.controller.BaseController;
+import com.bawei.common.core.web.domain.AjaxResult;
+import com.bawei.common.core.web.page.TableDataInfo;
+import com.bawei.common.log.annotation.Log;
+import com.bawei.common.log.enums.BusinessType;
+import com.bawei.common.security.annotation.RequiresPermissions;
+import com.bawei.common.security.utils.SecurityUtils;
+import com.bawei.job.domain.SysJob;
+import com.bawei.job.service.ISysJobService;
+import com.bawei.job.util.CronUtils;
+import com.bawei.job.util.ScheduleUtils;
+
+/**
+ * 调度任务信息操作处理
+ *
+ * @author bawei
+ */
+@RestController
+@RequestMapping("/job")
+public class SysJobController extends BaseController
+{
+ @Autowired
+ private ISysJobService jobService;
+
+ /**
+ * 查询定时任务列表
+ */
+ @RequiresPermissions("monitor:job:list")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJob sysJob)
+ {
+ startPage();
+ List list = jobService.selectJobList(sysJob);
+ return getDataTable(list);
+ }
+
+ /**
+ * 导出定时任务列表
+ */
+ @RequiresPermissions("monitor:job:export")
+ @Log(title = "定时任务", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJob sysJob)
+ {
+ List list = jobService.selectJobList(sysJob);
+ ExcelUtil util = new ExcelUtil(SysJob.class);
+ util.exportExcel(response, list, "定时任务");
+ }
+
+ /**
+ * 获取定时任务详细信息
+ */
+ @RequiresPermissions("monitor:job:query")
+ @GetMapping(value = "/{jobId}")
+ public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
+ {
+ return AjaxResult.success(jobService.selectJobById(jobId));
+ }
+
+ /**
+ * 新增定时任务
+ */
+ @RequiresPermissions("monitor:job:add")
+ @Log(title = "定时任务", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
+ }
+ job.setCreateBy(SecurityUtils.getUsername());
+ return toAjax(jobService.insertJob(job));
+ }
+
+ /**
+ * 修改定时任务
+ */
+ @RequiresPermissions("monitor:job:edit")
+ @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
+ }
+ job.setUpdateBy(SecurityUtils.getUsername());
+ return toAjax(jobService.updateJob(job));
+ }
+
+ /**
+ * 定时任务状态修改
+ */
+ @RequiresPermissions("monitor:job:changeStatus")
+ @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
+ {
+ SysJob newJob = jobService.selectJobById(job.getJobId());
+ newJob.setStatus(job.getStatus());
+ return toAjax(jobService.changeStatus(newJob));
+ }
+
+ /**
+ * 定时任务立即执行一次
+ */
+ @RequiresPermissions("monitor:job:changeStatus")
+ @Log(title = "定时任务", businessType = BusinessType.UPDATE)
+ @PutMapping("/run")
+ public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
+ {
+ boolean result = jobService.run(job);
+ return result ? success() : error("任务不存在或已过期!");
+ }
+
+ /**
+ * 删除定时任务
+ */
+ @RequiresPermissions("monitor:job:remove")
+ @Log(title = "定时任务", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobIds}")
+ public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
+ {
+ jobService.deleteJobByIds(jobIds);
+ return AjaxResult.success();
+ }
+}
diff --git a/src/main/java/com/bawei/job/controller/SysJobLogController.java b/src/main/java/com/bawei/job/controller/SysJobLogController.java
new file mode 100644
index 0000000..5969a76
--- /dev/null
+++ b/src/main/java/com/bawei/job/controller/SysJobLogController.java
@@ -0,0 +1,91 @@
+package com.bawei.job.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.bawei.common.core.utils.poi.ExcelUtil;
+import com.bawei.common.core.web.controller.BaseController;
+import com.bawei.common.core.web.domain.AjaxResult;
+import com.bawei.common.core.web.page.TableDataInfo;
+import com.bawei.common.log.annotation.Log;
+import com.bawei.common.log.enums.BusinessType;
+import com.bawei.common.security.annotation.RequiresPermissions;
+import com.bawei.job.domain.SysJobLog;
+import com.bawei.job.service.ISysJobLogService;
+
+/**
+ * 调度日志操作处理
+ *
+ * @author bawei
+ */
+@RestController
+@RequestMapping("/job/log")
+public class SysJobLogController extends BaseController
+{
+ @Autowired
+ private ISysJobLogService jobLogService;
+
+ /**
+ * 查询定时任务调度日志列表
+ */
+ @RequiresPermissions("monitor:job:list")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJobLog sysJobLog)
+ {
+ startPage();
+ List list = jobLogService.selectJobLogList(sysJobLog);
+ return getDataTable(list);
+ }
+
+ /**
+ * 导出定时任务调度日志列表
+ */
+ @RequiresPermissions("monitor:job:export")
+ @Log(title = "任务调度日志", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJobLog sysJobLog)
+ {
+ List list = jobLogService.selectJobLogList(sysJobLog);
+ ExcelUtil util = new ExcelUtil(SysJobLog.class);
+ util.exportExcel(response, list, "调度日志");
+ }
+
+ /**
+ * 根据调度编号获取详细信息
+ */
+ @RequiresPermissions("monitor:job:query")
+ @GetMapping(value = "/{configId}")
+ public AjaxResult getInfo(@PathVariable Long jobLogId)
+ {
+ return AjaxResult.success(jobLogService.selectJobLogById(jobLogId));
+ }
+
+ /**
+ * 删除定时任务调度日志
+ */
+ @RequiresPermissions("monitor:job:remove")
+ @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobLogIds}")
+ public AjaxResult remove(@PathVariable Long[] jobLogIds)
+ {
+ return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
+ }
+
+ /**
+ * 清空定时任务调度日志
+ */
+ @RequiresPermissions("monitor:job:remove")
+ @Log(title = "调度日志", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ jobLogService.cleanJobLog();
+ return AjaxResult.success();
+ }
+}
diff --git a/src/main/java/com/bawei/job/domain/SysJob.java b/src/main/java/com/bawei/job/domain/SysJob.java
new file mode 100644
index 0000000..221508f
--- /dev/null
+++ b/src/main/java/com/bawei/job/domain/SysJob.java
@@ -0,0 +1,171 @@
+package com.bawei.job.domain;
+
+import java.util.Date;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.bawei.common.core.annotation.Excel;
+import com.bawei.common.core.annotation.Excel.ColumnType;
+import com.bawei.common.core.constant.ScheduleConstants;
+import com.bawei.common.core.utils.StringUtils;
+import com.bawei.common.core.web.domain.BaseEntity;
+import com.bawei.job.util.CronUtils;
+
+/**
+ * 定时任务调度表 sys_job
+ *
+ * @author bawei
+ */
+public class SysJob extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 任务ID */
+ @Excel(name = "任务序号", cellType = ColumnType.NUMERIC)
+ private Long jobId;
+
+ /** 任务名称 */
+ @Excel(name = "任务名称")
+ private String jobName;
+
+ /** 任务组名 */
+ @Excel(name = "任务组名")
+ private String jobGroup;
+
+ /** 调用目标字符串 */
+ @Excel(name = "调用目标字符串")
+ private String invokeTarget;
+
+ /** cron执行表达式 */
+ @Excel(name = "执行表达式 ")
+ private String cronExpression;
+
+ /** cron计划策略 */
+ @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行")
+ private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
+
+ /** 是否并发执行(0允许 1禁止) */
+ @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止")
+ private String concurrent;
+
+ /** 任务状态(0正常 1暂停) */
+ @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停")
+ private String status;
+
+ public Long getJobId()
+ {
+ return jobId;
+ }
+
+ public void setJobId(Long jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ @NotBlank(message = "任务名称不能为空")
+ @Size(min = 0, max = 64, message = "任务名称不能超过64个字符")
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ @NotBlank(message = "调用目标字符串不能为空")
+ @Size(min = 0, max = 500, message = "调用目标字符串长度不能超过500个字符")
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ @NotBlank(message = "Cron执行表达式不能为空")
+ @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符")
+ public String getCronExpression()
+ {
+ return cronExpression;
+ }
+
+ public void setCronExpression(String cronExpression)
+ {
+ this.cronExpression = cronExpression;
+ }
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ public Date getNextValidTime()
+ {
+ if (StringUtils.isNotEmpty(cronExpression))
+ {
+ return CronUtils.getNextExecution(cronExpression);
+ }
+ return null;
+ }
+
+ public String getMisfirePolicy()
+ {
+ return misfirePolicy;
+ }
+
+ public void setMisfirePolicy(String misfirePolicy)
+ {
+ this.misfirePolicy = misfirePolicy;
+ }
+
+ public String getConcurrent()
+ {
+ return concurrent;
+ }
+
+ public void setConcurrent(String concurrent)
+ {
+ this.concurrent = concurrent;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobId", getJobId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("cronExpression", getCronExpression())
+ .append("nextValidTime", getNextValidTime())
+ .append("misfirePolicy", getMisfirePolicy())
+ .append("concurrent", getConcurrent())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/src/main/java/com/bawei/job/domain/SysJobLog.java b/src/main/java/com/bawei/job/domain/SysJobLog.java
new file mode 100644
index 0000000..108498f
--- /dev/null
+++ b/src/main/java/com/bawei/job/domain/SysJobLog.java
@@ -0,0 +1,155 @@
+package com.bawei.job.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.bawei.common.core.annotation.Excel;
+import com.bawei.common.core.web.domain.BaseEntity;
+
+/**
+ * 定时任务调度日志表 sys_job_log
+ *
+ * @author bawei
+ */
+public class SysJobLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** ID */
+ @Excel(name = "日志序号")
+ private Long jobLogId;
+
+ /** 任务名称 */
+ @Excel(name = "任务名称")
+ private String jobName;
+
+ /** 任务组名 */
+ @Excel(name = "任务组名")
+ private String jobGroup;
+
+ /** 调用目标字符串 */
+ @Excel(name = "调用目标字符串")
+ private String invokeTarget;
+
+ /** 日志信息 */
+ @Excel(name = "日志信息")
+ private String jobMessage;
+
+ /** 执行状态(0正常 1失败) */
+ @Excel(name = "执行状态", readConverterExp = "0=正常,1=失败")
+ private String status;
+
+ /** 异常信息 */
+ @Excel(name = "异常信息")
+ private String exceptionInfo;
+
+ /** 开始时间 */
+ private Date startTime;
+
+ /** 停止时间 */
+ private Date stopTime;
+
+ public Long getJobLogId()
+ {
+ return jobLogId;
+ }
+
+ public void setJobLogId(Long jobLogId)
+ {
+ this.jobLogId = jobLogId;
+ }
+
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ public String getJobMessage()
+ {
+ return jobMessage;
+ }
+
+ public void setJobMessage(String jobMessage)
+ {
+ this.jobMessage = jobMessage;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getExceptionInfo()
+ {
+ return exceptionInfo;
+ }
+
+ public void setExceptionInfo(String exceptionInfo)
+ {
+ this.exceptionInfo = exceptionInfo;
+ }
+
+ public Date getStartTime()
+ {
+ return startTime;
+ }
+
+ public void setStartTime(Date startTime)
+ {
+ this.startTime = startTime;
+ }
+
+ public Date getStopTime()
+ {
+ return stopTime;
+ }
+
+ public void setStopTime(Date stopTime)
+ {
+ this.stopTime = stopTime;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobLogId", getJobLogId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("jobMessage", getJobMessage())
+ .append("status", getStatus())
+ .append("exceptionInfo", getExceptionInfo())
+ .append("startTime", getStartTime())
+ .append("stopTime", getStopTime())
+ .toString();
+ }
+}
diff --git a/src/main/java/com/bawei/job/mapper/SysJobLogMapper.java b/src/main/java/com/bawei/job/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..cc7c92e
--- /dev/null
+++ b/src/main/java/com/bawei/job/mapper/SysJobLogMapper.java
@@ -0,0 +1,64 @@
+package com.bawei.job.mapper;
+
+import java.util.List;
+import com.bawei.job.domain.SysJobLog;
+
+/**
+ * 调度任务日志信息 数据层
+ *
+ * @author bawei
+ */
+public interface SysJobLogMapper
+{
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 查询所有调度任务日志
+ *
+ * @return 调度任务日志列表
+ */
+ public List selectJobLogAll();
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobLogId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ * @return 结果
+ */
+ public int insertJobLog(SysJobLog jobLog);
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param logIds 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ * @return 结果
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 清空任务日志
+ */
+ public void cleanJobLog();
+}
diff --git a/src/main/java/com/bawei/job/mapper/SysJobMapper.java b/src/main/java/com/bawei/job/mapper/SysJobMapper.java
new file mode 100644
index 0000000..bbe2bf2
--- /dev/null
+++ b/src/main/java/com/bawei/job/mapper/SysJobMapper.java
@@ -0,0 +1,67 @@
+package com.bawei.job.mapper;
+
+import java.util.List;
+import com.bawei.job.domain.SysJob;
+
+/**
+ * 调度任务信息 数据层
+ *
+ * @author bawei
+ */
+public interface SysJobMapper
+{
+ /**
+ * 查询调度任务日志集合
+ *
+ * @param job 调度信息
+ * @return 操作日志集合
+ */
+ public List selectJobList(SysJob job);
+
+ /**
+ * 查询所有调度任务
+ *
+ * @return 调度任务列表
+ */
+ public List selectJobAll();
+
+ /**
+ * 通过调度ID查询调度任务信息
+ *
+ * @param jobId 调度ID
+ * @return 角色对象信息
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 通过调度ID删除调度任务信息
+ *
+ * @param jobId 调度ID
+ * @return 结果
+ */
+ public int deleteJobById(Long jobId);
+
+ /**
+ * 批量删除调度任务信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteJobByIds(Long[] ids);
+
+ /**
+ * 修改调度任务信息
+ *
+ * @param job 调度任务信息
+ * @return 结果
+ */
+ public int updateJob(SysJob job);
+
+ /**
+ * 新增调度任务信息
+ *
+ * @param job 调度任务信息
+ * @return 结果
+ */
+ public int insertJob(SysJob job);
+}
diff --git a/src/main/java/com/bawei/job/service/ISysJobLogService.java b/src/main/java/com/bawei/job/service/ISysJobLogService.java
new file mode 100644
index 0000000..e3aeb11
--- /dev/null
+++ b/src/main/java/com/bawei/job/service/ISysJobLogService.java
@@ -0,0 +1,56 @@
+package com.bawei.job.service;
+
+import java.util.List;
+import com.bawei.job.domain.SysJobLog;
+
+/**
+ * 定时任务调度日志信息信息 服务层
+ *
+ * @author bawei
+ */
+public interface ISysJobLogService
+{
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobLogId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ */
+ public void addJobLog(SysJobLog jobLog);
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param logIds 需要删除的日志ID
+ * @return 结果
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ * @return 结果
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 清空任务日志
+ */
+ public void cleanJobLog();
+}
diff --git a/src/main/java/com/bawei/job/service/ISysJobService.java b/src/main/java/com/bawei/job/service/ISysJobService.java
new file mode 100644
index 0000000..6f3009e
--- /dev/null
+++ b/src/main/java/com/bawei/job/service/ISysJobService.java
@@ -0,0 +1,102 @@
+package com.bawei.job.service;
+
+import java.util.List;
+import org.quartz.SchedulerException;
+import com.bawei.common.core.exception.job.TaskException;
+import com.bawei.job.domain.SysJob;
+
+/**
+ * 定时任务调度信息信息 服务层
+ *
+ * @author bawei
+ */
+public interface ISysJobService
+{
+ /**
+ * 获取quartz调度器的计划任务
+ *
+ * @param job 调度信息
+ * @return 调度任务集合
+ */
+ public List selectJobList(SysJob job);
+
+ /**
+ * 通过调度任务ID查询调度信息
+ *
+ * @param jobId 调度任务ID
+ * @return 调度任务对象信息
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 暂停任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int pauseJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 恢复任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int resumeJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int deleteJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 批量删除调度信息
+ *
+ * @param jobIds 需要删除的任务ID
+ * @return 结果
+ */
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException;
+
+ /**
+ * 任务调度状态修改
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int changeStatus(SysJob job) throws SchedulerException;
+
+ /**
+ * 立即运行任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public boolean run(SysJob job) throws SchedulerException;
+
+ /**
+ * 新增任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int insertJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 更新任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int updateJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 校验cron表达式是否有效
+ *
+ * @param cronExpression 表达式
+ * @return 结果
+ */
+ public boolean checkCronExpressionIsValid(String cronExpression);
+}
diff --git a/src/main/java/com/bawei/job/service/SysJobLogServiceImpl.java b/src/main/java/com/bawei/job/service/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..cc16402
--- /dev/null
+++ b/src/main/java/com/bawei/job/service/SysJobLogServiceImpl.java
@@ -0,0 +1,86 @@
+package com.bawei.job.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.bawei.job.domain.SysJobLog;
+import com.bawei.job.mapper.SysJobLogMapper;
+
+/**
+ * 定时任务调度日志信息 服务层
+ *
+ * @author bawei
+ */
+@Service
+public class SysJobLogServiceImpl implements ISysJobLogService
+{
+ @Autowired
+ private SysJobLogMapper jobLogMapper;
+
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ @Override
+ public List selectJobLogList(SysJobLog jobLog)
+ {
+ return jobLogMapper.selectJobLogList(jobLog);
+ }
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobLogId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ @Override
+ public SysJobLog selectJobLogById(Long jobLogId)
+ {
+ return jobLogMapper.selectJobLogById(jobLogId);
+ }
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ */
+ @Override
+ public void addJobLog(SysJobLog jobLog)
+ {
+ jobLogMapper.insertJobLog(jobLog);
+ }
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param logIds 需要删除的数据ID
+ * @return 结果
+ */
+ @Override
+ public int deleteJobLogByIds(Long[] logIds)
+ {
+ return jobLogMapper.deleteJobLogByIds(logIds);
+ }
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ */
+ @Override
+ public int deleteJobLogById(Long jobId)
+ {
+ return jobLogMapper.deleteJobLogById(jobId);
+ }
+
+ /**
+ * 清空任务日志
+ */
+ @Override
+ public void cleanJobLog()
+ {
+ jobLogMapper.cleanJobLog();
+ }
+}
diff --git a/src/main/java/com/bawei/job/service/SysJobServiceImpl.java b/src/main/java/com/bawei/job/service/SysJobServiceImpl.java
new file mode 100644
index 0000000..ad27737
--- /dev/null
+++ b/src/main/java/com/bawei/job/service/SysJobServiceImpl.java
@@ -0,0 +1,260 @@
+package com.bawei.job.service;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.bawei.common.core.constant.ScheduleConstants;
+import com.bawei.common.core.exception.job.TaskException;
+import com.bawei.job.domain.SysJob;
+import com.bawei.job.mapper.SysJobMapper;
+import com.bawei.job.util.CronUtils;
+import com.bawei.job.util.ScheduleUtils;
+
+/**
+ * 定时任务调度信息 服务层
+ *
+ * @author bawei
+ */
+@Service
+public class SysJobServiceImpl implements ISysJobService
+{
+ @Autowired
+ private Scheduler scheduler;
+
+ @Autowired
+ private SysJobMapper jobMapper;
+
+ /**
+ * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
+ */
+ @PostConstruct
+ public void init() throws SchedulerException, TaskException
+ {
+ scheduler.clear();
+ List jobList = jobMapper.selectJobAll();
+ for (SysJob job : jobList)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ }
+
+ /**
+ * 获取quartz调度器的计划任务列表
+ *
+ * @param job 调度信息
+ * @return
+ */
+ @Override
+ public List selectJobList(SysJob job)
+ {
+ return jobMapper.selectJobList(job);
+ }
+
+ /**
+ * 通过调度任务ID查询调度信息
+ *
+ * @param jobId 调度任务ID
+ * @return 调度任务对象信息
+ */
+ @Override
+ public SysJob selectJobById(Long jobId)
+ {
+ return jobMapper.selectJobById(jobId);
+ }
+
+ /**
+ * 暂停任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int pauseJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 恢复任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int resumeJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deleteJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ int rows = jobMapper.deleteJobById(jobId);
+ if (rows > 0)
+ {
+ scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 批量删除调度信息
+ *
+ * @param jobIds 需要删除的任务ID
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException
+ {
+ for (Long jobId : jobIds)
+ {
+ SysJob job = jobMapper.selectJobById(jobId);
+ deleteJob(job);
+ }
+ }
+
+ /**
+ * 任务调度状态修改
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int changeStatus(SysJob job) throws SchedulerException
+ {
+ int rows = 0;
+ String status = job.getStatus();
+ if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
+ {
+ rows = resumeJob(job);
+ }
+ else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
+ {
+ rows = pauseJob(job);
+ }
+ return rows;
+ }
+
+ /**
+ * 立即运行任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean run(SysJob job) throws SchedulerException
+ {
+ boolean result = false;
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ SysJob properties = selectJobById(job.getJobId());
+ // 参数
+ JobDataMap dataMap = new JobDataMap();
+ dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ result = true;
+ scheduler.triggerJob(jobKey, dataMap);
+ }
+ return result;
+ }
+
+ /**
+ * 新增任务
+ *
+ * @param job 调度信息 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int insertJob(SysJob job) throws SchedulerException, TaskException
+ {
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.insertJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 更新任务的时间表达式
+ *
+ * @param job 调度信息
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int updateJob(SysJob job) throws SchedulerException, TaskException
+ {
+ SysJob properties = selectJobById(job.getJobId());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ updateSchedulerJob(job, properties.getJobGroup());
+ }
+ return rows;
+ }
+
+ /**
+ * 更新任务
+ *
+ * @param job 任务对象
+ * @param jobGroup 任务组名
+ */
+ public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException
+ {
+ Long jobId = job.getJobId();
+ // 判断是否存在
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ // 防止创建时存在数据问题 先移除,然后在执行创建操作
+ scheduler.deleteJob(jobKey);
+ }
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+
+ /**
+ * 校验cron表达式是否有效
+ *
+ * @param cronExpression 表达式
+ * @return 结果
+ */
+ @Override
+ public boolean checkCronExpressionIsValid(String cronExpression)
+ {
+ return CronUtils.isValid(cronExpression);
+ }
+}
diff --git a/src/main/java/com/bawei/job/task/RyTask.java b/src/main/java/com/bawei/job/task/RyTask.java
new file mode 100644
index 0000000..ce11f0c
--- /dev/null
+++ b/src/main/java/com/bawei/job/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.bawei.job.task;
+
+import org.springframework.stereotype.Component;
+import com.bawei.common.core.utils.StringUtils;
+
+/**
+ * 定时任务调度测试
+ *
+ * @author bawei
+ */
+@Component("ryTask")
+public class RyTask
+{
+ public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
+ {
+ System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i));
+ }
+
+ public void ryParams(String params)
+ {
+ System.out.println("执行有参方法:" + params);
+ }
+
+ public void ryNoParams()
+ {
+ System.out.println("执行无参方法");
+ }
+}
diff --git a/src/main/java/com/bawei/job/util/AbstractQuartzJob.java b/src/main/java/com/bawei/job/util/AbstractQuartzJob.java
new file mode 100644
index 0000000..a57add0
--- /dev/null
+++ b/src/main/java/com/bawei/job/util/AbstractQuartzJob.java
@@ -0,0 +1,106 @@
+package com.bawei.job.util;
+
+import java.util.Date;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.bawei.common.core.constant.ScheduleConstants;
+import com.bawei.common.core.utils.ExceptionUtil;
+import com.bawei.common.core.utils.SpringUtils;
+import com.bawei.common.core.utils.StringUtils;
+import com.bawei.common.core.utils.bean.BeanUtils;
+import com.bawei.job.domain.SysJob;
+import com.bawei.job.domain.SysJobLog;
+import com.bawei.job.service.ISysJobLogService;
+
+/**
+ * 抽象quartz调用
+ *
+ * @author bawei
+ */
+public abstract class AbstractQuartzJob implements Job
+{
+ private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
+
+ /**
+ * 线程本地变量
+ */
+ private static ThreadLocal threadLocal = new ThreadLocal<>();
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException
+ {
+ SysJob sysJob = new SysJob();
+ BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
+ try
+ {
+ before(context, sysJob);
+ if (sysJob != null)
+ {
+ doExecute(context, sysJob);
+ }
+ after(context, sysJob, null);
+ }
+ catch (Exception e)
+ {
+ log.error("任务执行异常 - :", e);
+ after(context, sysJob, e);
+ }
+ }
+
+ /**
+ * 执行前
+ *
+ * @param context 工作执行上下文对象
+ * @param sysJob 系统计划任务
+ */
+ protected void before(JobExecutionContext context, SysJob sysJob)
+ {
+ threadLocal.set(new Date());
+ }
+
+ /**
+ * 执行后
+ *
+ * @param context 工作执行上下文对象
+ * @param sysJob 系统计划任务
+ */
+ protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
+ {
+ Date startTime = threadLocal.get();
+ threadLocal.remove();
+
+ final SysJobLog sysJobLog = new SysJobLog();
+ sysJobLog.setJobName(sysJob.getJobName());
+ sysJobLog.setJobGroup(sysJob.getJobGroup());
+ sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
+ sysJobLog.setStartTime(startTime);
+ sysJobLog.setStopTime(new Date());
+ long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
+ sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
+ if (e != null)
+ {
+ sysJobLog.setStatus("1");
+ String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
+ sysJobLog.setExceptionInfo(errorMsg);
+ }
+ else
+ {
+ sysJobLog.setStatus("0");
+ }
+
+ // 写入数据库当中
+ SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
+ }
+
+ /**
+ * 执行方法,由子类重载
+ *
+ * @param context 工作执行上下文对象
+ * @param sysJob 系统计划任务
+ * @throws Exception 执行过程中的异常
+ */
+ protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
+}
diff --git a/src/main/java/com/bawei/job/util/CronUtils.java b/src/main/java/com/bawei/job/util/CronUtils.java
new file mode 100644
index 0000000..cef4616
--- /dev/null
+++ b/src/main/java/com/bawei/job/util/CronUtils.java
@@ -0,0 +1,63 @@
+package com.bawei.job.util;
+
+import java.text.ParseException;
+import java.util.Date;
+import org.quartz.CronExpression;
+
+/**
+ * cron表达式工具类
+ *
+ * @author bawei
+ *
+ */
+public class CronUtils
+{
+ /**
+ * 返回一个布尔值代表一个给定的Cron表达式的有效性
+ *
+ * @param cronExpression Cron表达式
+ * @return boolean 表达式是否有效
+ */
+ public static boolean isValid(String cronExpression)
+ {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 返回一个字符串值,表示该消息无效Cron表达式给出有效性
+ *
+ * @param cronExpression Cron表达式
+ * @return String 无效时返回表达式错误描述,如果有效返回null
+ */
+ public static String getInvalidMessage(String cronExpression)
+ {
+ try
+ {
+ new CronExpression(cronExpression);
+ return null;
+ }
+ catch (ParseException pe)
+ {
+ return pe.getMessage();
+ }
+ }
+
+ /**
+ * 返回下一个执行时间根据给定的Cron表达式
+ *
+ * @param cronExpression Cron表达式
+ * @return Date 下次Cron表达式执行时间
+ */
+ public static Date getNextExecution(String cronExpression)
+ {
+ try
+ {
+ CronExpression cron = new CronExpression(cronExpression);
+ return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/bawei/job/util/JobInvokeUtil.java b/src/main/java/com/bawei/job/util/JobInvokeUtil.java
new file mode 100644
index 0000000..a253bdd
--- /dev/null
+++ b/src/main/java/com/bawei/job/util/JobInvokeUtil.java
@@ -0,0 +1,182 @@
+package com.bawei.job.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import com.bawei.common.core.utils.SpringUtils;
+import com.bawei.common.core.utils.StringUtils;
+import com.bawei.job.domain.SysJob;
+
+/**
+ * 任务执行工具
+ *
+ * @author bawei
+ */
+public class JobInvokeUtil
+{
+ /**
+ * 执行方法
+ *
+ * @param sysJob 系统任务
+ */
+ public static void invokeMethod(SysJob sysJob) throws Exception
+ {
+ String invokeTarget = sysJob.getInvokeTarget();
+ String beanName = getBeanName(invokeTarget);
+ String methodName = getMethodName(invokeTarget);
+ List