parent
bd6fac2394
commit
c9c2296d60
14 changed files with 908 additions and 79 deletions
@ -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; |
//package org.jeecg.modules.cms.webmagic.task;
|
||||||
|
//
|
||||||
import lombok.extern.slf4j.Slf4j; |
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor; |
//import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
|
||||||
import org.jeecg.modules.cms.webmagic.service.NewsPipeline; |
//import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.Scheduled; |
//import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component; |
//import org.springframework.stereotype.Component;
|
||||||
import us.codecraft.webmagic.Spider; |
//import us.codecraft.webmagic.Spider;
|
||||||
|
//
|
||||||
@Slf4j |
//@Slf4j
|
||||||
@Component |
//@Component
|
||||||
public class NewsWebMagicTask { |
//public class NewsWebMagicTask {
|
||||||
|
//
|
||||||
@Autowired |
// @Autowired
|
||||||
private NewsPipeline pipeline; |
// private NewsPipeline pipeline;
|
||||||
|
//
|
||||||
@Autowired |
// @Autowired
|
||||||
private NewsPageProcessor pageProcessor; |
// private NewsPageProcessor pageProcessor;
|
||||||
|
//
|
||||||
// 每天23点执行一次
|
// // 每天23点执行一次
|
||||||
@Scheduled(cron = "0 0 23 * * ?") |
//// @Scheduled(cron = "0 0 23 * * ?")
|
||||||
//@Scheduled(cron = "0 40 15 * * ?")
|
// //@Scheduled(cron = "0 40 15 * * ?")
|
||||||
// 每隔1分钟执行一次
|
// // 每隔1分钟执行一次
|
||||||
// @Scheduled(cron = "0 */3 * * * ?")
|
//// @Scheduled(cron = "0 */3 * * * ?")
|
||||||
public void crawl() { |
// public void crawl() {
|
||||||
//第1页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml
|
// //第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
|
// //第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
|
// //第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
|
// //第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 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 urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
|
||||||
String url = ""; |
// String url = "";
|
||||||
try { |
// try {
|
||||||
Spider.create(pageProcessor) |
// Spider.create(pageProcessor)
|
||||||
.addUrl(urlPage1) |
// .addUrl(urlPage1)
|
||||||
// 抓取到的数据存数据库
|
// // 抓取到的数据存数据库
|
||||||
.addPipeline(pipeline) |
// .addPipeline(pipeline)
|
||||||
// 开启2个线程抓取
|
// // 开启2个线程抓取
|
||||||
.thread(3) |
// .thread(1)
|
||||||
// 异步启动爬虫
|
// // 异步启动爬虫
|
||||||
.start(); |
// .start();
|
||||||
} catch (Exception ex) { |
// } catch (Exception ex) {
|
||||||
log.error("数据抓取异常:", ex.getMessage()); |
// log.error("数据抓取异常:", ex.getMessage());
|
||||||
log.error("定时抓取数据线程执行异常", ex); |
// 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);
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
} |
//// 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…
Reference in new issue