
SpringBoot整合Quartz计划任务-基于Ruoyi的代码
拷贝ruoyi job和joblog对应的Mapper。拷贝ruoyi里面的Util和Service。创建job和joblog数据库。Controller类。
·
使用的Pom文件
<!--quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
</dependency>
<!--定时任务需要依赖context模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
创建job和joblog数据库
拷贝ruoyi job和joblog对应的Mapper
拷贝ruoyi里面的Util和Service
按格式写任务类
Controller类
package com.java.core.web.contrller.job;
import com.java.core.com.annotation.Log;
import com.java.core.com.constant.Constants;
import com.java.core.com.enums.BusinessType;
import com.java.core.com.exception.job.TaskException;
import com.java.core.com.page.TableDataInfo;
import com.java.core.com.utils.StringUtils;
import com.java.core.com.vo.HttpResult;
import com.java.core.entity.master.SysJob;
import com.java.core.quartz.util.CronUtils;
import com.java.core.quartz.util.ScheduleUtils;
import com.java.core.quartz.service.SysJobService;
import com.java.core.web.contrller.common.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.quartz.SchedulerException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 调度任务信息操作处理
*
*/
@Api(tags = {"调度任务"})
@RestController
@RequestMapping("job")
public class SysJobController extends BaseController {
@Resource
private SysJobService jobService;
@ApiOperation(value = "获取任务列表")
@Log(title = "调度任务", businessType = BusinessType.GET)
@PreAuthorize("hasAuthority('sys:job:get')")
@GetMapping(value = "/getList")
public HttpResult getList(@RequestBody SysJob job){
this.startPage();
List<SysJob> list = jobService.selectJobList(job);
TableDataInfo dataInfo = this.getDataTable(list);
return HttpResult.ok(dataInfo.getRows(),dataInfo.getTotal());
}
@ApiOperation(value = "批量删除")
@Log(title = "调度任务", businessType = BusinessType.DELETE)
@PreAuthorize("hasAuthority('sys:job:delete')")
@PostMapping(value = "/del")
public HttpResult del(String ids) throws SchedulerException {
jobService.deleteJobByIds(ids);
return HttpResult.ok("删除成功");
}
@ApiOperation(value = "任务调度状态修改")
@Log(title = "调度任务", businessType = BusinessType.UPDATE)
@PreAuthorize("hasAuthority('sys:job:update')")
@PostMapping(value = "/changeStatus")
public HttpResult changeStatus(@RequestBody SysJob job) throws SchedulerException {
SysJob newJob = jobService.selectJobById(job.getJobId());
newJob.setStatus(job.getStatus());
jobService.changeStatus(newJob);
return HttpResult.ok("修改成功");
}
@ApiOperation(value = "任务调度立即执行一次")
@Log(title = "调度任务", businessType = BusinessType.UPDATE)
@PreAuthorize("hasAuthority('sys:job:update')")
@PostMapping(value = "/run")
public HttpResult run(@RequestBody SysJob job) throws SchedulerException {
jobService.run(job);
return HttpResult.ok("执行成功");
}
@ApiOperation(value = "新增保存调度")
@Log(title = "调度任务", businessType = BusinessType.INSERT)
@PreAuthorize("hasAuthority('sys:job:insert')")
@PostMapping(value = "/insert")
public HttpResult insert(@RequestBody SysJob job) throws TaskException, SchedulerException {
if (!CronUtils.isValid(job.getCronExpression()))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规");
}
else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
{
return HttpResult.error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
}
job.setCreate_by((getUserId()));
jobService.insertJob(job);
return HttpResult.ok("操作成功");
}
@ApiOperation(value = "修改保存调度")
@Log(title = "调度任务", businessType = BusinessType.UPDATE)
@PreAuthorize("hasAuthority('sys:job:update')")
@PostMapping(value = "/edit")
public HttpResult edit(@RequestBody SysJob job) throws TaskException, SchedulerException {
if (!CronUtils.isValid(job.getCronExpression()))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规");
}
else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
{
return HttpResult.error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
}
jobService.updateJob(job);
return HttpResult.ok("操作成功");
}
@ApiOperation(value = "查询cron表达式近5次的执行时间")
@Log(title = "调度任务", businessType = BusinessType.GET)
@PreAuthorize("hasAuthority('sys:job:get')")
@GetMapping(value = "/queryCronExpression")
public HttpResult queryCronExpression(String cronExpression){
if (jobService.checkCronExpressionIsValid(cronExpression))
{
List<String> dateList = CronUtils.getRecentTriggerTime(cronExpression);
return HttpResult.ok(dateList);
}
else
{
return HttpResult.error("表达式无效");
}
}
}
项目启动后,内存版本就行可以运行了
Job日志记录类捕捉的地方
配置一个任务可以并发和不并发的类
/**
* 定时任务处理(禁止并发执行)
*
*
*/
@DisallowConcurrentExecution
public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
{
JobInvokeUtil.invokeMethod(sysJob);
}
}
/**
* 定时任务处理(允许并发执行)
*
*
*/
public class QuartzJobExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
{
JobInvokeUtil.invokeMethod(sysJob);
}
}
在创建任务的时候,动态创建这个任务是可并发任务还是不可并发任务
/**
* 得到quartz任务类
*
* @param sysJob 执行计划
* @return 具体执行任务类
*/
private static Class<? extends Job> getQuartzJobClass(SysJob sysJob)
{
boolean isConcurrent = "0".equals(sysJob.getConcurrent());
return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
}
如果想把JOB存在数据数据库,则写个下面的类
package com.java.core.quartz.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
* 定时任务配置(单机部署建议默认走内存,如需集群需要创建qrtz数据库表/打开类注释)
*
*/
@Configuration
public class ScheduleConfig
{
@Bean
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("masterXADataSource") DataSource dataSource)
{
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "DefaultQuartzScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
// 存储方式使用JobStoreTX,也就是数据库
prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
// 集群配置
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
// sqlserver 启用
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
factory.setQuartzProperties(prop);
factory.setSchedulerName("QuartzScheduler");
// 延时启动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选,QuartzScheduler
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
// 设置自动启动,默认为true
factory.setAutoStartup(true);
return factory;
}
}
masterXADataSource 的配置
更多推荐
所有评论(0)