'调度修改'

master
zhc077 2 years ago
parent bd6fac2394
commit c9c2296d60
  1. 29
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/controller/NewsWebMagicController.java
  2. 2
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPageProcessor.java
  3. 53
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsAsyncJob.java
  4. 140
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsWebMagicTask.java
  5. 22
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/SampleJobTest.java
  6. 283
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/controller/QuartzJobController.java
  7. 84
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/entity/QuartzJob.java
  8. 35
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/job/AsyncJob.java
  9. 23
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/job/SampleJob.java
  10. 32
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/job/SampleParamJob.java
  11. 25
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/mapper/QuartzJobMapper.java
  12. 9
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/mapper/xml/QuartzJobMapper.xml
  13. 67
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/service/IQuartzJobService.java
  14. 183
      jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/quartz/service/impl/QuartzJobServiceImpl.java

@ -29,13 +29,26 @@ public class NewsWebMagicController {
String page1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
String pageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
String url = "";
for (int i = 60; i <= 65; i++) {
if (i == 1) {
url = page1;
} else {
url = pageOther + (i + 1) + ".html";
}
log.info("the page {} url:{}", i, url);
try {
Spider.create(pageProcessor)
.addUrl(page1)
// 抓取到的数据存数据库
.addPipeline(pipeline)
// 开启2个线程抓取
.thread(1)
// 异步启动爬虫
.start();
} catch (Exception ex) {
log.error("数据抓取异常:", ex.getMessage());
log.error("定时抓取数据线程执行异常", ex);
}
// for (int i = 60; i <= 65; i++) {
// if (i == 1) {
// url = page1;
// } else {
// url = pageOther + (i + 1) + ".html";
// }
// log.info("the page {} url:{}", i, url);
// try {
// Spider.create(pageProcessor)
// .addUrl(url)
@ -49,6 +62,6 @@ public class NewsWebMagicController {
// log.error("第[{}]页数据抓取异常:", i, ex.getMessage());
// log.error("定时抓取数据线程执行异常", ex);
// }
}
// }
}
}

@ -24,7 +24,7 @@ public class NewsPageProcessor implements PageProcessor {
@Override
public void process(Page page) {
// log.info("page.url = " + page.getUrl());
log.info("the page.url ****** = " + page.getUrl());
// log.info("page= " + page.getHtml().toString());
/**

@ -0,0 +1,53 @@
package org.jeecg.modules.cms.webmagic.task;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import us.codecraft.webmagic.Spider;
/**
* @Description: 同步定时任务
* <p>
* 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时
* 会等待第一个任务执行完成才会走第二个任务
* @author: taoyan
* @date: 2020年06月19日
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class NewsAsyncJob implements Job {
@Autowired
private NewsPipeline pipeline;
@Autowired
private NewsPageProcessor pageProcessor;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" NewsAsyncJob Execution key:" + jobExecutionContext.getJobDetail().getKey());
log.info(String.format("NewsAsyncJob-开始时间:" + DateUtils.getTimestamp()));
String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
// String url = "";
try {
Spider.create(pageProcessor)
.addUrl(urlPage1)
// 抓取到的数据存数据库
.addPipeline(pipeline)
// 开启2个线程抓取
.thread(1)
// 异步启动爬虫
.start();
} catch (Exception ex) {
log.error("数据抓取异常:", ex.getMessage());
log.error("定时抓取数据线程执行异常", ex);
}
}
}

@ -1,71 +1,71 @@
package org.jeecg.modules.cms.webmagic.task;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;
@Slf4j
@Component
public class NewsWebMagicTask {
@Autowired
private NewsPipeline pipeline;
@Autowired
private NewsPageProcessor pageProcessor;
// 每天23点执行一次
@Scheduled(cron = "0 0 23 * * ?")
//@Scheduled(cron = "0 40 15 * * ?")
// 每隔1分钟执行一次
// @Scheduled(cron = "0 */3 * * * ?")
public void crawl() {
//第1页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml
//第2页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-2.html
//第3页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-3.html
// ......
//第65页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-65.html
String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
String url = "";
try {
Spider.create(pageProcessor)
.addUrl(urlPage1)
// 抓取到的数据存数据库
.addPipeline(pipeline)
// 开启2个线程抓取
.thread(3)
// 异步启动爬虫
.start();
} catch (Exception ex) {
log.error("数据抓取异常:", ex.getMessage());
log.error("定时抓取数据线程执行异常", ex);
}
// for (int i = 1; i <= 9; i++) {
// if (i == 1) {
// url = urlPage1;
// } else {
// url = urlPageOther + (i + 1) + ".html";
// }
// log.info("the page {} url:{}", i, url);
// try {
// Spider.create(pageProcessor)
// .addUrl(url)
// // 抓取到的数据存数据库
// .addPipeline(pipeline)
// // 开启2个线程抓取
// .thread(3)
// // 异步启动爬虫
// .start();
// } catch (Exception ex) {
// log.error("第[{}]页数据抓取异常:", i, ex.getMessage());
// log.error("定时抓取数据线程执行异常", ex);
// }
//package org.jeecg.modules.cms.webmagic.task;
//
//import lombok.extern.slf4j.Slf4j;
//import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
//import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//import us.codecraft.webmagic.Spider;
//
//@Slf4j
//@Component
//public class NewsWebMagicTask {
//
// @Autowired
// private NewsPipeline pipeline;
//
// @Autowired
// private NewsPageProcessor pageProcessor;
//
// // 每天23点执行一次
//// @Scheduled(cron = "0 0 23 * * ?")
// //@Scheduled(cron = "0 40 15 * * ?")
// // 每隔1分钟执行一次
//// @Scheduled(cron = "0 */3 * * * ?")
// public void crawl() {
// //第1页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml
// //第2页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-2.html
// //第3页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-3.html
// // ......
// //第65页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-65.html
//
// String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
// String url = "";
// try {
// Spider.create(pageProcessor)
// .addUrl(urlPage1)
// // 抓取到的数据存数据库
// .addPipeline(pipeline)
// // 开启2个线程抓取
// .thread(1)
// // 异步启动爬虫
// .start();
// } catch (Exception ex) {
// log.error("数据抓取异常:", ex.getMessage());
// log.error("定时抓取数据线程执行异常", ex);
// }
}
}
//// for (int i = 1; i <= 9; i++) {
//// if (i == 1) {
//// url = urlPage1;
//// } else {
//// url = urlPageOther + (i + 1) + ".html";
//// }
//// log.info("the page {} url:{}", i, url);
//// try {
//// Spider.create(pageProcessor)
//// .addUrl(url)
//// // 抓取到的数据存数据库
//// .addPipeline(pipeline)
//// // 开启2个线程抓取
//// .thread(3)
//// // 异步启动爬虫
//// .start();
//// } catch (Exception ex) {
//// log.error("第[{}]页数据抓取异常:", i, ex.getMessage());
//// log.error("定时抓取数据线程执行异常", ex);
//// }
//// }
// }
//}

@ -0,0 +1,22 @@
package org.jeecg.modules.cms.webmagic.task;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 示例不带参定时任务
*
* @Author Scott
*/
@Slf4j
public class SampleJobTest implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" >>>>>>>>SampleJobTest Execution key:"+jobExecutionContext.getJobDetail().getKey());
log.info(String.format(" 普通定时任务 SampleJobTest,时间:" + DateUtils.getTimestamp()));
}
}

@ -0,0 +1,283 @@
package org.jeecg.modules.quartz.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.service.IQuartzJobService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Description: 定时任务在线管理
* @Author: jeecg-boot
* @Date: 2019-01-02
* @Version:V1.0
*/
@RestController
@RequestMapping("/sys/quartzJob")
@Slf4j
@Api(tags = "定时任务接口")
public class QuartzJobController {
@Autowired
private IQuartzJobService quartzJobService;
@Autowired
private Scheduler scheduler;
/**
* 分页列表查询
*
* @param quartzJob
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<?> queryPageList(QuartzJob quartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, req.getParameterMap());
Page<QuartzJob> page = new Page<QuartzJob>(pageNo, pageSize);
IPage<QuartzJob> pageList = quartzJobService.page(page, queryWrapper);
return Result.ok(pageList);
}
/**
* 添加定时任务
*
* @param quartzJob
* @return
*/
//@RequiresRoles("admin")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<?> add(@RequestBody QuartzJob quartzJob) {
quartzJobService.saveAndScheduleJob(quartzJob);
return Result.ok("创建定时任务成功");
}
/**
* 更新定时任务
*
* @param quartzJob
* @return
*/
//@RequiresRoles("admin")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
try {
quartzJobService.editAndScheduleJob(quartzJob);
} catch (SchedulerException e) {
log.error(e.getMessage(), e);
return Result.error("更新定时任务失败!");
}
return Result.ok("更新定时任务成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
//@RequiresRoles("admin")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (quartzJob == null) {
return Result.error("未找到对应实体");
}
quartzJobService.deleteAndStopJob(quartzJob);
return Result.ok("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
//@RequiresRoles("admin")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
if (ids == null || "".equals(ids.trim())) {
return Result.error("参数不识别!");
}
for (String id : Arrays.asList(ids.split(","))) {
QuartzJob job = quartzJobService.getById(id);
quartzJobService.deleteAndStopJob(job);
}
return Result.ok("删除定时任务成功!");
}
/**
* 暂停定时任务
*
* @param id
* @return
*/
//@RequiresRoles("admin")
@GetMapping(value = "/pause")
@ApiOperation(value = "停止定时任务")
public Result<Object> pauseJob(@RequestParam(name = "id") String id) {
QuartzJob job = quartzJobService.getById(id);
if (job == null) {
return Result.error("定时任务不存在!");
}
quartzJobService.pause(job);
return Result.ok("停止定时任务成功");
}
/**
* 启动定时任务
*
* @param id
* @return
*/
//@RequiresRoles("admin")
@GetMapping(value = "/resume")
@ApiOperation(value = "启动定时任务")
public Result<Object> resumeJob(@RequestParam(name = "id") String id) {
QuartzJob job = quartzJobService.getById(id);
if (job == null) {
return Result.error("定时任务不存在!");
}
quartzJobService.resumeJob(job);
//scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));
return Result.ok("启动定时任务成功");
}
/**
* 通过id查询
*
* @param id
* @return
*/
@RequestMapping(value = "/queryById", method = RequestMethod.GET)
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
return Result.ok(quartzJob);
}
/**
* 导出excel
*
* @param request
* @param quartzJob
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {
// Step.1 组装查询条件
QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
// Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
List<QuartzJob> pageList = quartzJobService.list(queryWrapper);
// 导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "定时任务列表");
mv.addObject(NormalExcelConstants.CLASS, QuartzJob.class);
//获取当前登录用户
//update-begin---author:wangshuai ---date:20211227 for:[JTC-116]导出人写死了------------
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("定时任务列表数据", "导出人:" + user.getRealname(), "导出信息"));
//update-end---author:wangshuai ---date:20211227 for:[JTC-116]导出人写死了------------
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
// 错误信息
List<String> errorMessage = new ArrayList<>();
int successLines = 0, errorLines = 0;
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// 获取上传文件对象
MultipartFile file = entity.getValue();
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<Object> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);
//add-begin-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
// for(QuartzJob job: listQuartzJobs){
// job.setStatus(CommonConstant.STATUS_DISABLE);
// }
List<String> list = ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage, CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);
//add-end-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
errorLines += list.size();
successLines += (listQuartzJobs.size() - errorLines);
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("文件导入失败!");
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
}
/**
* 立即执行
*
* @param id
* @return
*/
//@RequiresRoles("admin")
@GetMapping("/execute")
public Result<?> execute(@RequestParam(name = "id", required = true) String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (quartzJob == null) {
return Result.error("未找到对应实体");
}
try {
quartzJobService.execute(quartzJob);
} catch (Exception e) {
//e.printStackTrace();
log.info("定时任务 立即执行失败>>" + e.getMessage());
return Result.error("执行失败!");
}
return Result.ok("执行成功!");
}
}

@ -0,0 +1,84 @@
package org.jeecg.modules.quartz.entity;
import java.io.Serializable;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
/**
* @Description: 定时任务在线管理
* @Author: jeecg-boot
* @Date: 2019-01-02
* @Version: V1.0
*/
@Data
@TableName("sys_quartz_job")
public class QuartzJob implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private java.util.Date createTime;
/**
* 删除状态
*/
private Integer delFlag;
/**
* 修改人
*/
private String updateBy;
/**
* 修改时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private java.util.Date updateTime;
/**
* 任务类名
*/
@Excel(name = "任务类名", width = 40)
private String jobClassName;
/**
* cron表达式
*/
@Excel(name = "cron表达式", width = 30)
private String cronExpression;
/**
* 参数
*/
@Excel(name = "参数", width = 15)
private String parameter;
/**
* 描述
*/
@Excel(name = "描述", width = 40)
private String description;
/**
* 状态 0正常 -1停止
*/
@Excel(name = "状态", width = 15, dicCode = "quartz_status")
@Dict(dicCode = "quartz_status")
private Integer status;
}

@ -0,0 +1,35 @@
package org.jeecg.modules.quartz.job;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.quartz.*;
/**
* @Description: 同步定时任务测试
*
* 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时
* 会等待第一个任务执行完成才会走第二个任务
*
*
* @author: taoyan
* @date: 2020年06月19日
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class AsyncJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" --- 同步任务调度开始 --- ");
try {
//此处模拟任务执行时间 5秒 任务表达式配置为每秒执行一次:0/1 * * * * ? *
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//测试发现 每5秒执行一次
log.info(" --- 执行完毕,时间:"+DateUtils.now()+"---");
}
}

@ -0,0 +1,23 @@
package org.jeecg.modules.quartz.job;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import lombok.extern.slf4j.Slf4j;
/**
* 示例不带参定时任务
*
* @Author Scott
*/
@Slf4j
public class SampleJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
log.info(String.format(" Jeecg-Boot 普通定时任务 SampleJob ! 时间:" + DateUtils.getTimestamp()));
}
}

@ -0,0 +1,32 @@
package org.jeecg.modules.quartz.job;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import lombok.extern.slf4j.Slf4j;
/**
* 示例带参定时任务
*
* @Author Scott
*/
@Slf4j
public class SampleParamJob implements Job {
/**
* 若参数变量名修改 QuartzJobController中也需对应修改
*/
private String parameter;
public void setParameter(String parameter) {
this.parameter = parameter;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
log.info( String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now(), this.parameter));
}
}

@ -0,0 +1,25 @@
package org.jeecg.modules.quartz.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.quartz.entity.QuartzJob;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: 定时任务在线管理
* @Author: jeecg-boot
* @Date: 2019-01-02
* @Version: V1.0
*/
public interface QuartzJobMapper extends BaseMapper<QuartzJob> {
/**
* 根据jobClassName查询
* @param jobClassName 任务类名
* @return
*/
public List<QuartzJob> findByJobClassName(@Param("jobClassName") String jobClassName);
}

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.quartz.mapper.QuartzJobMapper">
<!-- 根据jobClassName查询 -->
<select id="findByJobClassName" resultType="org.jeecg.modules.quartz.entity.QuartzJob">
select * from sys_quartz_job where job_class_name = #{jobClassName}
</select>
</mapper>

@ -0,0 +1,67 @@
package org.jeecg.modules.quartz.service;
import java.util.List;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.quartz.SchedulerException;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: 定时任务在线管理
* @Author: jeecg-boot
* @Date: 2019-04-28
* @Version: V1.1
*/
public interface IQuartzJobService extends IService<QuartzJob> {
/**
* 通过类名寻找定时任务
* @param jobClassName 类名
* @return List<QuartzJob>
*/
List<QuartzJob> findByJobClassName(String jobClassName);
/**
* 保存定时任务
* @param quartzJob
* @return boolean
*/
boolean saveAndScheduleJob(QuartzJob quartzJob);
/**
* 编辑定时任务
* @param quartzJob
* @return boolean
* @throws SchedulerException
*/
boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;
/**
* 删除定时任务
* @param quartzJob
* @return boolean
*/
boolean deleteAndStopJob(QuartzJob quartzJob);
/**
* 恢复定时任务
* @param quartzJob
* @return
*/
boolean resumeJob(QuartzJob quartzJob);
/**
* 执行定时任务
* @param quartzJob
* @throws Exception
*/
void execute(QuartzJob quartzJob) throws Exception;
/**
* 暂停任务
* @param quartzJob
* @throws SchedulerException
*/
void pause(QuartzJob quartzJob);
}

@ -0,0 +1,183 @@
package org.jeecg.modules.quartz.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.mapper.QuartzJobMapper;
import org.jeecg.modules.quartz.service.IQuartzJobService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @Description: 定时任务在线管理
* @Author: jeecg-boot
* @Date: 2019-04-28
* @Version: V1.1
*/
@Slf4j
@Service
public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {
@Autowired
private QuartzJobMapper quartzJobMapper;
@Autowired
private Scheduler scheduler;
/**
* 立即执行的任务分组
*/
private static final String JOB_TEST_GROUP = "test_group";
@Override
public List<QuartzJob> findByJobClassName(String jobClassName) {
return quartzJobMapper.findByJobClassName(jobClassName);
}
/**
* 保存&启动定时任务
*/
@Override
@Transactional(rollbackFor = JeecgBootException.class)
public boolean saveAndScheduleJob(QuartzJob quartzJob) {
// DB设置修改
quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
boolean success = this.save(quartzJob);
if (success) {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
// 定时器添加
this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
}
}
return success;
}
/**
* 恢复定时任务
*/
@Override
@Transactional(rollbackFor = JeecgBootException.class)
public boolean resumeJob(QuartzJob quartzJob) {
schedulerDelete(quartzJob.getId());
schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
return this.updateById(quartzJob);
}
/**
* 编辑&启停定时任务
* @throws SchedulerException
*/
@Override
@Transactional(rollbackFor = JeecgBootException.class)
public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
schedulerDelete(quartzJob.getId());
schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
}else{
scheduler.pauseJob(JobKey.jobKey(quartzJob.getId()));
}
return this.updateById(quartzJob);
}
/**
* 删除&停止删除定时任务
*/
@Override
@Transactional(rollbackFor = JeecgBootException.class)
public boolean deleteAndStopJob(QuartzJob job) {
schedulerDelete(job.getId());
boolean ok = this.removeById(job.getId());
return ok;
}
@Override
public void execute(QuartzJob quartzJob) throws Exception {
String jobName = quartzJob.getJobClassName().trim();
Date startDate = new Date();
String ymd = DateUtils.date2Str(startDate,DateUtils.yyyymmddhhmmss.get());
String identity = jobName + ymd;
//3秒后执行 只执行一次
// update-begin--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------
startDate.setTime(startDate.getTime() + 100L);
// update-end--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------
// 定义一个Trigger
SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger()
.withIdentity(identity, JOB_TEST_GROUP)
.startAt(startDate)
.build();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();
// 将trigger和 jobDetail 加入这个调度
scheduler.scheduleJob(jobDetail, trigger);
// 启动scheduler
scheduler.start();
}
@Override
@Transactional(rollbackFor = JeecgBootException.class)
public void pause(QuartzJob quartzJob){
schedulerDelete(quartzJob.getId());
quartzJob.setStatus(CommonConstant.STATUS_DISABLE);
this.updateById(quartzJob);
}
/**
* 添加定时任务
*
* @param jobClassName
* @param cronExpression
* @param parameter
*/
private void schedulerAdd(String id, String jobClassName, String cronExpression, String parameter) {
try {
// 启动调度器
scheduler.start();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new JeecgBootException("创建定时任务失败", e);
} catch (RuntimeException e) {
throw new JeecgBootException(e.getMessage(), e);
}catch (Exception e) {
throw new JeecgBootException("后台找不到该类名:" + jobClassName, e);
}
}
/**
* 删除定时任务
*
* @param id
*/
private void schedulerDelete(String id) {
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(id));
scheduler.unscheduleJob(TriggerKey.triggerKey(id));
scheduler.deleteJob(JobKey.jobKey(id));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new JeecgBootException("删除定时任务失败");
}
}
private static Job getClass(String classname) throws Exception {
Class<?> class1 = Class.forName(classname);
return (Job) class1.newInstance();
}
}
Loading…
Cancel
Save