diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/AppRun.java b/nladmin-system/nlsso-server/src/main/java/org/nl/AppRun.java index 230144d..4add80b 100644 --- a/nladmin-system/nlsso-server/src/main/java/org/nl/AppRun.java +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/AppRun.java @@ -35,11 +35,6 @@ import org.springframework.web.bind.annotation.RestController; @EnableTransactionManagement @EnableMethodCache(basePackages = "org.nl") @EnableCreateCacheAnnotation -@ComponentScan( - excludeFilters = { - @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.nl.modules.quartz.*"), - @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.github.loki4j.*")} -) public class AppRun { public static void main(String[] args) { diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/JobRunner.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/JobRunner.java new file mode 100644 index 0000000..06483c9 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/JobRunner.java @@ -0,0 +1,45 @@ +package org.nl.modules.quartz.config; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import netscape.javascript.JSObject; +import org.nl.modules.quartz.utils.QuartzManage; +import org.nl.modules.wql.core.bean.WQLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.function.Consumer; + +/** + * @author: lyd + * @description: + * @Date: 2022/12/5 + */ +@Component +@RequiredArgsConstructor +@Order(100) +public class JobRunner implements ApplicationRunner { + private static final Logger log = LoggerFactory.getLogger(JobRunner.class); +// private final QuartzJobRepository quartzJobRepository; + private final QuartzManage quartzManage; + + /** + * 项目启动时重新激活启用的定时任务 + * + * @param applicationArguments / + */ + @Override + public void run(ApplicationArguments applicationArguments) { + log.info("--------------------注入定时任务---------------------"); + WQLObject jobTab = WQLObject.getWQLObject("sys_quartz_job"); + JSONArray quartzJobs = jobTab.query("is_pause = '0'").getResultJSONArray(0); + quartzJobs.forEach( job -> quartzManage.addJob((JSONObject) job)); + log.info("--------------------定时任务注入完成---------------------"); + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/QuartzConfig.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/QuartzConfig.java new file mode 100644 index 0000000..f0743ff --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/config/QuartzConfig.java @@ -0,0 +1,57 @@ +package org.nl.modules.quartz.config; + +import org.quartz.Scheduler; +import org.quartz.spi.TriggerFiredBundle; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.AdaptableJobFactory; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.stereotype.Component; + +/** + * @author: lyd + * @description: 定时任务配置 + * @Date: 2022/12/5 + */ +@Configuration +public class QuartzConfig { + + /** + * 解决Job中注入Spring Bean为null的问题 + */ + @Component("quartzJobFactory") + public static class QuartzJobFactory extends AdaptableJobFactory { + + private final AutowireCapableBeanFactory capableBeanFactory; + + public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) { + this.capableBeanFactory = capableBeanFactory; + } + + @Override + protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { + + //调用父类的方法 + Object jobInstance = super.createJobInstance(bundle); + capableBeanFactory.autowireBean(jobInstance); + return jobInstance; + } + } + + /** + * 注入scheduler到spring + * @param quartzJobFactory / + * @return Scheduler + * @throws Exception / + */ + @Bean(name = "scheduler") + public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception { + SchedulerFactoryBean factoryBean=new SchedulerFactoryBean(); + factoryBean.setJobFactory(quartzJobFactory); + factoryBean.afterPropertiesSet(); + Scheduler scheduler=factoryBean.getScheduler(); + scheduler.start(); + return scheduler; + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/rest/QuartzJobController.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/rest/QuartzJobController.java new file mode 100644 index 0000000..260eb49 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/rest/QuartzJobController.java @@ -0,0 +1,92 @@ +package org.nl.modules.quartz.rest; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.alibaba.fastjson.JSONObject; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.logging.annotation.Log; +import org.nl.modules.quartz.service.QuartzJobService; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.Set; + +/** + * @author: lyd + * @description: + * @Date: 2022/12/5 + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/jobs") +@Api(tags = "系统:定时任务管理") +public class QuartzJobController { + private final QuartzJobService quartzJobService; + + @GetMapping + @Log("查询点位") + @ApiOperation("查询点位") + //@SaCheckPermission("timing:list") + public ResponseEntity query(@RequestParam Map whereJson, Pageable page) { + return new ResponseEntity<>(quartzJobService.queryAll(whereJson, page), HttpStatus.OK); + } + + @ApiOperation("查询任务执行日志") + @GetMapping(value = "/logs") + @SaCheckPermission("timing:list") + public ResponseEntity queryJobLog(@RequestParam Map criteria, Pageable pageable) { + return new ResponseEntity<>(quartzJobService.queryAllLog(criteria, pageable), HttpStatus.OK); + } + + @Log("新增定时任务") + @ApiOperation("新增定时任务") + @PostMapping +// @SaCheckPermission("timing:add") + public ResponseEntity create(@RequestBody JSONObject resources) { + quartzJobService.create(resources); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改定时任务") + @ApiOperation("修改定时任务") + @PutMapping +// @SaCheckPermission("timing:edit") + public ResponseEntity update(@RequestBody JSONObject resources) { + quartzJobService.update(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("更改定时任务状态") + @ApiOperation("更改定时任务状态") + @PutMapping(value = "/{id}") +// @SaCheckPermission("timing:edit") + public ResponseEntity update(@PathVariable Long id) { + quartzJobService.updateIsPause(quartzJobService.findById(id)); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("执行定时任务") + @ApiOperation("执行定时任务") + @PutMapping(value = "/exec/{id}") +// @SaCheckPermission("timing:edit") + public ResponseEntity execution(@PathVariable Long id) { + quartzJobService.execution(quartzJobService.findById(id)); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除定时任务") + @ApiOperation("删除定时任务") + @DeleteMapping +// @SaCheckPermission("timing:del") + public ResponseEntity delete(@RequestBody Set ids) { + quartzJobService.delete(ids); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/QuartzJobService.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/QuartzJobService.java new file mode 100644 index 0000000..abf9d40 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/QuartzJobService.java @@ -0,0 +1,79 @@ +package org.nl.modules.quartz.service; + +import com.alibaba.fastjson.JSONObject; +import org.springframework.data.domain.Pageable; + +import java.util.Map; +import java.util.Set; + +/** + * @author: lyd + * @description: + * @Date: 2022/12/5 + */ +public interface QuartzJobService { + + /** + * 分页查询 + * @param whereJson + * @param page + * @return + */ + Object queryAll(Map whereJson, Pageable page); + + /** + * 添加 + * @param resources + */ + void create(JSONObject resources); + + /** + * 日志查询 + * @param criteria + * @param pageable + * @return + */ + Object queryAllLog(Map criteria, Pageable pageable); + + /** + * 修改任务 + * @param resources + */ + void update(JSONObject resources); + + /** + * 根据ID查询 + * + * @param id ID + * @return / + */ + JSONObject findById(Long id); + + /** + * 立即执行定时任务 + * + * @param quartzJob / + */ + void execution(JSONObject quartzJob); + + /** + * 更改定时任务状态 + * + * @param job / + */ + void updateIsPause(JSONObject job); + + /** + * 执行子任务 + * + * @param tasks / + * @throws InterruptedException / + */ + void executionSubJob(String[] tasks) throws InterruptedException; + + /** + * 批量删除 + * @param ids + */ + void delete(Set ids); +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/impl/QuartzJobServiceImpl.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/impl/QuartzJobServiceImpl.java new file mode 100644 index 0000000..30745d6 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/service/impl/QuartzJobServiceImpl.java @@ -0,0 +1,219 @@ +package org.nl.modules.quartz.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.common.utils.RedisUtils; +import org.nl.modules.common.utils.SecurityUtils; +import org.nl.modules.quartz.service.QuartzJobService; +import org.nl.modules.quartz.utils.QuartzManage; +import org.nl.modules.wql.core.bean.ResultBean; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.WqlUtil; +import org.quartz.CronExpression; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author: lyd + * @description: + * @Date: 2022/12/5 + */ +@RequiredArgsConstructor +@Service(value = "quartzJobService") +public class QuartzJobServiceImpl implements QuartzJobService { + + private final RedisUtils redisUtils; + private final QuartzManage quartzManage; + + @Override + public Object queryAll(Map whereJson, Pageable page) { + WQLObject quartzTab = WQLObject.getWQLObject("sys_quartz_job"); + String param = "1 = 1"; + if (ObjectUtil.isNotEmpty(whereJson.get("job_name"))) { + String job_name = whereJson.get("job_name").toString(); + param = param + " AND job_name like '%" + job_name + "%'"; + } + ResultBean rb = quartzTab.pagequery(WqlUtil.getHttpContext(page), param, "update_time desc"); + final JSONObject json = rb.pageResult(); + return json; + } + + /** + * 添加 + * + * @param resources + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void create(JSONObject resources) { + if (!CronExpression.isValidExpression(resources.getString("cron_expression"))) { + throw new BadRequestException("cron表达式格式错误"); + } + WQLObject quartzTab = WQLObject.getWQLObject("sys_quartz_job"); + Long userId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + resources.put("job_id", IdUtil.getSnowflake(1,1).nextId()); + resources.put("create_id", userId); + resources.put("create_name", nickName); + resources.put("create_time", now); + resources.put("update_optid", userId); + resources.put("update_optname", nickName); + resources.put("update_time", now); + quartzTab.insert(resources); + // 添加任务 + quartzManage.addJob(resources); + } + + /** + * 日志查询 + * + * @param criteria + * @param pageable + * @return + */ + @Override + public Object queryAllLog(Map criteria, Pageable pageable) { + WQLObject logTab = WQLObject.getWQLObject("sys_quartz_log"); + String param = "1=1"; + if (ObjectUtil.isNotEmpty(criteria.get("job_name"))) { + param = param + " AND job_name = '" + criteria.get("job_name").toString() + "'"; + } + if (ObjectUtil.isNotEmpty(criteria.get("is_success"))) { + param = param + " AND is_success = '" + criteria.get("is_success").toString() + "'"; + } + if (ObjectUtil.isNotEmpty(criteria.get("createTime"))) { + param = param + " AND create_time >= " + criteria.get("begin_time") + " AND" + + " create_time <= " + criteria.get("end_time"); + } + ResultBean rb = logTab.pagequery(WqlUtil.getHttpContext(pageable), param, "create_time desc"); + final JSONObject json = rb.pageResult(); + return json; + } + + /** + * 修改任务 + * + * @param resources + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void update(JSONObject resources) { + WQLObject jobTab = WQLObject.getWQLObject("sys_quartz_job"); + JSONObject entity = this.findById(resources.getLong("job_id")); + if (entity == null) { + throw new BadRequestException("被删除或无权限,操作失败!"); + } + if (!CronExpression.isValidExpression(resources.getString("cron_expression"))) { + throw new BadRequestException("cron表达式格式错误"); + } + if (StrUtil.isNotEmpty(resources.getString("sub_task"))) { + List tasks = Arrays.asList(resources.getString("sub_task").split("[,,]")); + if (tasks.contains(resources.getString("job_id"))) { + throw new BadRequestException("子任务中不能添加当前任务ID"); + } + } + resources.put("update_optid", SecurityUtils.getCurrentUserId()); + resources.put("update_optname", SecurityUtils.getCurrentNickName()); + resources.put("update_time", DateUtil.now()); + jobTab.update(resources); + quartzManage.updateJobCron(resources); + } + + /** + * 根据ID查询 + * + * @param id ID + * @return / + */ + @Override + public JSONObject findById(Long id) { + WQLObject jobTab = WQLObject.getWQLObject("sys_quartz_job"); + JSONObject entity = jobTab.query("job_id = '" + id + "'").uniqueResult(0); + return entity; + } + + /** + * 立即执行定时任务 + * + * @param quartzJob / + */ + @Override + public void execution(JSONObject quartzJob) { + quartzManage.runJobNow(quartzJob); + } + + /** + * 更改定时任务状态 + * + * @param quartzJob / + */ + @Override + public void updateIsPause(JSONObject quartzJob) { + WQLObject jobTab = WQLObject.getWQLObject("sys_quartz_job"); + if (quartzJob.getString("is_pause").equals("1")) { + quartzManage.resumeJob(quartzJob); + quartzJob.put("is_pause", "0"); + } else { + quartzManage.pauseJob(quartzJob); + quartzJob.put("is_pause", "1"); + } + jobTab.update(quartzJob); + } + + /** + * 执行子任务 + * + * @param tasks / + * @throws InterruptedException / + */ + @Override + public void executionSubJob(String[] tasks) throws InterruptedException { + for (String id : tasks) { + JSONObject quartzJob = findById(Long.parseLong(id)); + // 执行任务 + String uuid = IdUtil.simpleUUID(); + quartzJob.put("job_id", uuid); + // 执行任务 + execution(quartzJob); + // 获取执行状态,如果执行失败则停止后面的子任务执行 + Boolean result = (Boolean) redisUtils.get(uuid); + while (result == null) { + // 休眠5秒,再次获取子任务执行情况 + Thread.sleep(5000); + result = (Boolean) redisUtils.get(uuid); + } + if (!result) { + redisUtils.del(uuid); + break; + } + } + } + + /** + * 批量删除 + * + * @param ids + */ + @Override + public void delete(Set ids) { + WQLObject jobTab = WQLObject.getWQLObject("sys_quartz_job"); + WQLObject logTab = WQLObject.getWQLObject("sys_quartz_log"); + for (Long id : ids) { + JSONObject quartzJob = findById(id); + quartzManage.deleteJob(quartzJob); + jobTab.delete(quartzJob); + } + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/task/TestTask.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/task/TestTask.java new file mode 100644 index 0000000..49a0114 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/task/TestTask.java @@ -0,0 +1,26 @@ +package org.nl.modules.quartz.task; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author: lyd + * @description: 测试任务 + * @Date: 2022/12/5 + */ +@Slf4j +@Component +public class TestTask { + + public void run(){ + log.info("run 执行成功"); + } + + public void run1(String str){ + log.info("run1 执行成功,参数为: {}" + str); + } + + public void run2(){ + log.info("run2 执行成功"); + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/ExecutionJob.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/ExecutionJob.java new file mode 100644 index 0000000..b334d3f --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/ExecutionJob.java @@ -0,0 +1,102 @@ +package org.nl.modules.quartz.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.config.thread.ThreadPoolExecutorUtil; +import org.nl.modules.common.utils.RedisUtils; +import org.nl.modules.common.utils.ThrowableUtil; +import org.nl.modules.quartz.service.QuartzJobService; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.SpringContextHolder; +import org.quartz.JobExecutionContext; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * @author: lyd + * @description: + * @Date: 2022/12/5 + */ +@Async +@SuppressWarnings({"unchecked", "all"}) +@Slf4j +public class ExecutionJob extends QuartzJobBean { + + /** + * 该处仅供参考 + */ + private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll(); + + @Override + public void executeInternal(JobExecutionContext context) { + JSONObject quartzJob = (JSONObject) context.getMergedJobDataMap().get(QuartzManage.JOB_KEY); + // 获取spring bean + QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class); + RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class); + WQLObject logTab = WQLObject.getWQLObject("sys_quartz_log"); + + String uuid = quartzJob.getString("job_id"); + + JSONObject logDto = new JSONObject(); + logDto.put("log_id", IdUtil.getSnowflake(1,1).nextId()); + logDto.put("create_time", DateUtil.now()); // ???? + logDto.put("job_name", quartzJob.getString("job_name")); + logDto.put("bean_name", quartzJob.getString("bean_name")); + logDto.put("method_name", quartzJob.getString("method_name")); + logDto.put("params", quartzJob.getString("params")); + long startTime = System.currentTimeMillis(); + logDto.put("cron_expression", quartzJob.getString("cron_expression")); + try { + // 执行任务 + System.out.println("--------------------------------------------------------------"); + System.out.println("任务开始执行,任务名称:" + quartzJob.getString("bean_name")); + QuartzRunnable task = new QuartzRunnable(quartzJob.getString("bean_name"), quartzJob.getString("method_name"), + quartzJob.getString("params")); + Future future = EXECUTOR.submit(task); + future.get(); + long times = System.currentTimeMillis() - startTime; + logDto.put("time", times); + if (StrUtil.isNotEmpty(uuid)) { + redisUtils.set(uuid, true); + } + // 任务状态 + logDto.put("is_success", "1"); + System.out.println("任务执行完毕,任务名称:" + quartzJob.getString("job_name") + ", 执行时间:" + times + "毫秒"); + System.out.println("--------------------------------------------------------------"); + // 判断是否存在子任务 + if (StrUtil.isNotEmpty(quartzJob.getString("sub_task"))) { + String[] tasks = quartzJob.getString("sub_task").split("[,,]"); + // 执行子任务 + quartzJobService.executionSubJob(tasks); + } + } catch (Exception e) { + if (StrUtil.isNotEmpty(uuid)) { + redisUtils.set(uuid, false); + } + System.out.println("任务执行失败,任务名称:" + quartzJob.getString("job_name")); + System.out.println("--------------------------------------------------------------"); + long times = System.currentTimeMillis() - startTime; + logDto.put("time", times); + // 任务状态 0:成功 1:失败 + logDto.put("is_success", "0"); + logDto.put("exception_detail", ThrowableUtil.getStackTrace(e)); + // 任务如果失败了则暂停 + if (quartzJob.getString("pause_after_failure") != null && quartzJob.getString("pause_after_failure").equals("1")) { + quartzJob.put("is_pause", "0"); + //更新状态 + quartzJobService.updateIsPause(quartzJob); + } + //异常时候打印日志 + log.info(logDto.toString()); + logTab.insert(logDto); + } finally { + } + } + +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzManage.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzManage.java new file mode 100644 index 0000000..3fff0f8 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzManage.java @@ -0,0 +1,156 @@ +package org.nl.modules.quartz.utils; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.common.exception.BadRequestException; +import org.quartz.*; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; + +import static org.quartz.TriggerBuilder.newTrigger; + +/** + * @author: lyd + * @description: 任务管理 + * @Date: 2022/12/5 + */ +@Slf4j +@Component +public class QuartzManage { + private static final String JOB_NAME = "TASK_"; + public static final String JOB_KEY = "JOB_KEY"; + + @Resource(name = "scheduler") + private Scheduler scheduler; + + public void addJob(JSONObject quartzJob){ + try { + // 构建job信息 + JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class). + withIdentity(JOB_NAME + quartzJob.getString("job_id")).build(); + + //通过触发器名和cron 表达式创建 Trigger + Trigger cronTrigger = newTrigger() + .withIdentity(JOB_NAME + quartzJob.getString("job_id")) + .startNow() + .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getString("cron_expression"))) + .build(); + + cronTrigger.getJobDataMap().put(QuartzManage.JOB_KEY, quartzJob); + + //重置启动时间 + ((CronTriggerImpl)cronTrigger).setStartTime(new Date()); + + //执行定时任务 + scheduler.scheduleJob(jobDetail,cronTrigger); + + // 暂停任务 + if (quartzJob.getString("is_pause").equals("1")) { + pauseJob(quartzJob); + } + } catch (Exception e){ + log.error("创建定时任务失败", e); + throw new BadRequestException("创建定时任务失败"); + } + } + + /** + * 执行任务 + * @param quartzJob + */ + public void runJobNow(JSONObject quartzJob) { + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getString("job_id")); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null) { + addJob(quartzJob); + } + JobDataMap dataMap = new JobDataMap(); + dataMap.put(QuartzManage.JOB_KEY, quartzJob); + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getString("job_id")); + scheduler.triggerJob(jobKey,dataMap); + } catch (Exception e){ + log.error("定时任务执行失败", e); + throw new BadRequestException("定时任务执行失败"); + } + } + + /** + * 暂停一个job + * @param quartzJob / + */ + public void pauseJob(JSONObject quartzJob){ + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getString("job_id")); + scheduler.pauseJob(jobKey); + } catch (Exception e){ + log.error("定时任务暂停失败", e); + throw new BadRequestException("定时任务暂停失败"); + } + } + + /** + * 更新job cron表达式 + * @param quartzJob / + */ + public void updateJobCron(JSONObject quartzJob) { + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getString("job_id")); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null){ + addJob(quartzJob); + trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + } + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getString("cron_expression")); + trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + //重置启动时间 + ((CronTriggerImpl)trigger).setStartTime(new Date()); + trigger.getJobDataMap().put(QuartzManage.JOB_KEY, quartzJob); + + scheduler.rescheduleJob(triggerKey, trigger); + // 暂停任务 + if (quartzJob.getString("is_pause").equals("1")) { + pauseJob(quartzJob); + } + } catch (Exception e){ + log.error("更新定时任务失败", e); + throw new BadRequestException("更新定时任务失败"); + } + } + + /** + * 恢复一个job + * @param quartzJob / + */ + public void resumeJob(JSONObject quartzJob) { + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getString("job_id")); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null) { + addJob(quartzJob); + } + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getString("job_id")); + scheduler.resumeJob(jobKey); + } catch (Exception e){ + log.error("恢复定时任务失败", e); + throw new BadRequestException("恢复定时任务失败"); + } + } + + public void deleteJob(JSONObject quartzJob) { + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getString("job_id")); + scheduler.pauseJob(jobKey); + scheduler.deleteJob(jobKey); + } catch (Exception e){ + log.error("删除定时任务失败", e); + throw new BadRequestException("删除定时任务失败"); + } + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzRunnable.java b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzRunnable.java new file mode 100644 index 0000000..da1b4d7 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/quartz/utils/QuartzRunnable.java @@ -0,0 +1,45 @@ +package org.nl.modules.quartz.utils; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.wql.util.SpringContextHolder; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +/** + * @author: lyd + * @description: 执行定时任务 + * @Date: 2022/12/5 + */ +@Slf4j +public class QuartzRunnable implements Callable { + + private final Object target; + private final Method method; + private final String params; + + QuartzRunnable(String beanName, String methodName, String params) + throws NoSuchMethodException, SecurityException { + this.target = SpringContextHolder.getBean(beanName); + this.params = params; + + if (StrUtil.isNotEmpty(params)) { + this.method = target.getClass().getDeclaredMethod(methodName, String.class); + } else { + this.method = target.getClass().getDeclaredMethod(methodName); + } + } + + @Override + public Object call() throws Exception { + ReflectionUtils.makeAccessible(method); + if (StrUtil.isNotEmpty(params)) { + method.invoke(target, params); + } else { + method.invoke(target); + } + return null; + } +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/system/wql/sys.xls b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/system/wql/sys.xls index 9c7e6d3..b30935b 100644 Binary files a/nladmin-system/nlsso-server/src/main/java/org/nl/modules/system/wql/sys.xls and b/nladmin-system/nlsso-server/src/main/java/org/nl/modules/system/wql/sys.xls differ diff --git a/nladmin-ui/src/views/system/timing/index.vue b/nladmin-ui/src/views/system/timing/index.vue index ca1474c..6317f79 100644 --- a/nladmin-ui/src/views/system/timing/index.vue +++ b/nladmin-ui/src/views/system/timing/index.vue @@ -4,7 +4,7 @@
- +
@@ -23,21 +23,21 @@ - - + + - - + + - - + + - + - +