栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

springBoot2 结合 Quartz

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springBoot2 结合 Quartz

为什么使用Quartz

定时任务是框架不可缺少的一部分,spring自带的定时任务工具,已经可以满足使用,但无法满足分布式的情况(实际也可以用分布式锁来实现),所以使用Quartz来实现框架的定时器功能

1.Quartz的一般使用

一般框架下怎么使用
1.1 引入jar


    org.quartz-scheduler
    quartz
    2.3.0

1.2 定义一个Job,具体执行任务的类

@DisallowConcurrentExecution
public class HelloJob implements Job{
	
	private static Logger log = LogManager.getLogger();

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		log.info(" HelloJob ");
	}
}

1.3 定义jobDetail,trigger,Scheduler
job与jobDetail绑定,形成任务
trigger定义了任务的执行时间
Scheduler 执行一对任务与触发器

public class HelloScheduler {
	public static void main(String[] args) throws SchedulerException, ParseException {
		// jobdetail 和 job实例绑定
		JobDetail helloJobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "helloGroup").build();
		
		// 触发器 simpleTrigger(SimpleScheduleBuilder)  CronTrigger	
		// 每5秒运行一次	
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("helloTrigger", "helloGroup")
				.withSchedule(CronScheduleBuilder.cronSchedule("/5 * * * * ? *"))
				.build();
		
		// 调度器
		SchedulerFactory schedulerFactory = new StdSchedulerFactory();
		Scheduler scheduler = schedulerFactory.getScheduler();
		scheduler.start();
		//执行任务
		scheduler.scheduleJob(helloJobDetail, trigger);
	}
}
2. springBoot2 结合 Quartz

2.1 jar引入


    org.springframework.boot
    spring-boot-starter-quartz

2.2 QuartzConfiguration

public class QuartzJobVo {
	
	//任务信息
	private String jobName;
	private String jobGroupName;
	
	//触发器信息
	private String triggerName;
	private String triggerGroupName;
	
	private String cron;

	//具体任务类
	private Class jobClass;
	//需要被删除
	private boolean needDelete = false;

	
	public QuartzJobVo() {
		super();
	}

	public QuartzJobVo(String jobName, String jobGroupName, String triggerName, String triggerGroupName, 
			Class jobClass, String cron) {
		super();
		this.jobName = jobName;
		this.jobGroupName = jobGroupName;
		this.triggerName = triggerName;
		this.triggerGroupName = triggerGroupName;
		this.cron = cron;
		this.jobClass = jobClass;
	}

	public QuartzJobVo(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
			Class jobClass, String cron, boolean needDelete) {
		super();
		this.jobName = jobName;
		this.jobGroupName = jobGroupName;
		this.triggerName = triggerName;
		this.triggerGroupName = triggerGroupName;
		this.cron = cron;
		this.jobClass = jobClass;
		this.needDelete = needDelete;
	}
...................
	}
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
public class HelloJob extends QuartzJobBean{
	
	private static Logger log = LogManager.getLogger();

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		// 任务具体执行的地方
		log.info("Hello world!:" + context.getJobDetail().getKey());
	}
}
@Configuration
public class QuartzConfiguration {
	
	@Autowired
    private DataSource dataSource;
	
	private static Logger log = LogManager.getLogger();
	
	//任务集合
	private final QuartzJobVo[] Jobs = {
		new QuartzJobVo("hello2", "hello2", "hello2", "hello2", HelloJob.class, "/5 * * * * ? *"),
		new QuartzJobVo("hello", "hello", "hello", "hello", HelloJob.class, "4,14 * * * * ? *", true)
	};
	
	@Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
 SchedulerFactoryBean factory = new SchedulerFactoryBean();
 factory.setDataSource(dataSource);

 //quartz参数
 Properties prop = new Properties();
 prop.put("org.quartz.scheduler.instanceName", "WIFIScheduler");
 prop.put("org.quartz.scheduler.instanceId", "AUTO");
 prop.put("org.quartz.scheduler.skipUpdateCheck", true);
 //线程池配置
 prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
 prop.put("org.quartz.threadPool.threadCount", "10");
 prop.put("org.quartz.threadPool.threadPriority", "5");
 //JobStore配置
 prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
 prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
 //集群配置
 prop.put("org.quartz.jobStore.isClustered", "true");
 //#设置此实例“检入”*与群集的其他实例的频率(以毫秒为单位)。影响检测失败实例的速度。
 prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
 prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
 // #在被认为“失火”之前,调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)
 prop.put("org.quartz.jobStore.misfireThreshold", "12000");
 prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
 prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERe LOCK_NAME = ?");

 //PostgreSQL数据库,需要打开此注释
 //prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");

 factory.setQuartzProperties(prop);

 factory.setSchedulerName("WIFIScheduler");
 //延时启动
 factory.setStartupDelay(30);
 factory.setApplicationContextSchedulerContextKey("applicationContextKey");
 //设置自动启动,默认为true
 factory.setAutoStartup(true);
 //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
 //实际运用中,要把jobDetail,trigger 全都交给spring管理,这个属性才起作用
 factory.setOverwriteExistingJobs(true);
		
 JobDetail[] jobDetails = new JobDetail[Jobs.length];
 Trigger[] triggers = new Trigger[Jobs.length];
 
 int size = 0;
		for (QuartzJobVo vo : Jobs) {
		  
			//job定义: // 任务名,任务组,任务执行类 
			JobDetail jobDetail = JobBuilder.newJob(vo.getJobClass()) 
									.withIdentity(vo.getJobName(), vo.getJobGroupName()) 
									.storeDurably() 
									.build();
			jobDetails[size] = jobDetail;
		  
			//触发器构建 
			Trigger trigger = TriggerBuilder.newTrigger()
								.withIdentity(vo.getTriggerName(), vo.getTriggerGroupName())
								.withSchedule(CronScheduleBuilder.cronSchedule(vo.getCron()))
								.forJob(jobDetail) 
								.build();
			triggers[size] = trigger;
		  
			log.info("增加了定时任务 vo={}", JSON.toJSonString(vo)); 
			size++;
		}
		
		factory.setJobDetails(jobDetails);
		factory.setTriggers(triggers);
		
 return factory;
    }
	
    @Bean
    public void deleteJob() {
    	
    	Scheduler scheduler = schedulerFactoryBean().getScheduler();
    	
    	for (QuartzJobVo vo : Jobs) {
    		
    		if(vo.isNeedDelete()) {
    			//需要被删除
    			JobKey jobKey = JobKey.jobKey(vo.getJobName(), vo.getJobGroupName()); 
    			
    			if(jobKey !=null) {
    				try {
    					scheduler.deleteJob(jobKey); 
    					log.info("定时任务删除成功  vo={}", JSON.toJSonString(vo));
    				} catch (Exception e) {
    					log.error("定时任务删除出错  vo={}", JSON.toJSonString(vo), e);
    					
    					try {
    						scheduler.pauseJob(jobKey);
						} catch (Exception e2) {
							log.error("定时任务暂停出错  vo={}", JSON.toJSonString(vo), e);
						}
    				}
    			}else {
    				log.info("定时任务已经不存在quartz表中 vo={}", JSON.toJSonString(vo));
    			}
    		}
    	}
    }
}
3. 注意

3.1 @DisallowConcurrentExecution,将该注解加到job类上,告诉Quartz不要并发地执行同一个job定义(这里指特定的job类)的多个实例,即同一个job,即是时间到了,只要上一个还在运行,新的就等待,spring的定时默认有这个机制
3.2 @PersistJobDataAfterExecution,将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该job(即JobDetail)在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据
3.3 线程池,org.quartz.threadPool.threadCount,默认10个,每一个在运行的job会占用一个线程,线程池被用完,新的任务只能排队

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/234385.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号