首次写博,如有不对(妥)之处,欢迎指正!
quartz定时插件,对于新入职员工,没有真实开发经验的新人很有可能并没有接触过,网上的博客呢又看不太懂,因此记录一些自己学习并对quartz进行基础使用的过程。
当然我就是呢。
然而在实际项目开发中Web应用是不可缺少的。 定时任务的场景可以说非常广泛,比如某些视频网站,购买会员后,每天会给会员送成长值,每月会给会员送一些电影券;
比如在保证最终一致性的场景中,往往利用定时任务调度进行一些比对工作;比如一些定时需要生成的报表、邮件;比如一些需要定时清理数据的任务等。所以我们提供方便友好的web界面,实现动态管理任务,可以达到动态控制定时任务启动、暂停、重启、删除、添加、修改等操作,极大地方便了开发过程。
一:对于传统springMVC项目(maven管理):
1.导入相关依赖:
1 <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz --> 2 <!--quartz核心包--> 3 <dependency> 4 <groupId>org.quartz-scheduler</groupId> 5 <artifactId>quartz</artifactId> 6 <version>2.3.1</version> 7 </dependency> 8 <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs --> 9 <!--quartz中对job的一些工具,处理方法等--><!--二者同步更新--> 10 <dependency> 11 <groupId>org.quartz-scheduler</groupId> 12 <artifactId>quartz-jobs</artifactId> 13 <version>2.3.1</version> 14 </dependency>
2.写一个自己的job类
1 public class MyJob { 2 public void run() { 3 SimpleDateFormat format = new SimpleDateFormat("yyyy- MM-dd hh:mm:ss"); 4 System.out.print(format.format(new Date().getTime())); 5 } 6 }
3.配置文件: 如果是多个任务,这些配置除了任务调度者都需要写多个
1 <!--注入job对象(自己写的类的全路径)--> 2 <bean id="myjob" class="com.yzy.MyJob"></bean> 3 <!--配置任务详情相关--> 4 <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 5 <!--刚刚注入的MyJob类--> 6 <property name="targetObject" ref="myjob"></property> 7 <!--配置任务详情对象:也就是指明MyJob类中自己写的具体的某个方法,这里就是run()了--> 8 <property name="targetMethod" value="run"></property> 9 </bean> 10 <!--配置任务的执行条件;(触发器)--> 11 <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> 12 <!--上边刚配好的任务详情对象--> 13 <property name="jobDetail" ref="jobDetail"></property> 14 <!--配置任务执行方式:这里用 cron 表达式的方式,其他方式因为不好用,想了解的可以自己了解嘛哈哈--> 15 <property name="cronExpression" value="1/2 * * * * ?"></property> 16 </bean> 17 <!--配置任务的执行者(调度者)--> 18 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 19 <!--上边刚配好的任务详情对象--> 20 <property name="triggers"> 21 <!--可以配置多个任务触发--> 22 <list> 23 <ref bean="trigger1"/> 24 </list> 25 </property> 26 <!--配置任务执行方式:这里用 cron 表达式的方式,其他方式因为不好用,想了解的可以自己了解嘛哈哈--> 27 <property name="cronExpression" value="1/2 * * * * ?"></property> 28 </bean>
4.使用
1 //①: 2 public static void main(String[] args) { 3 new ClassPathXmlApplicationContext("classpath:application.xml");//加载写好的配置文件 4 } 5 6 //或者使用②:在web.xml中: 7 <context-param> 8 <param-name>contextConfigLocation</param-name> 9 <param-value>classpath:application.xml</param-value> 10 </context-param> 11 <listener> 12 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 13 </listener> 14 //两种方式
5.然后:然后就自动执行了呗:启动一秒后每隔两秒执行一次 => 1/2 * * * * ?
二:对于springboot项目:
1.导入依赖
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-quartz</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.quartz-scheduler</groupId> 7 <artifactId>quartz-jobs</artifactId> 8 <version>2.3.1</version> 9 </dependency>
2.写个自己的job类(MyJob.class),此类必须实现quartz自带的Job接口,此接口只有一个方法需要实现,里边是的方法实现内容是自定义的
1 @Configuration //此注解一定要加不然报错: Job instantiation failed 2 public class MyJob implements Job { 3 @Override 4 public void execute(JobExecutionContext context) throws JobExecutionException { 5 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 6 System.out.print(format.format(new Date().getTime())); 7 } 8 }
3. 编程式配置
1 @Configuration //声明配置文件,声明之后spring才会把它当作配置文件去加载,否则不会加载 2 public class QuzrtzConfig { 3 //配置任务详情 4 @Bean 5 public JobDetail jobDetail(){ 6 return JobBuilder.newJob(MyJob.class).withIdentity("beifenKJob","group1")//配置详情名称,以及所在详情组名(与下边的触发器组名没有关系),(方便点调度者Scheduler对其进行相关操作) 7 .storeDurably().build(); 8 } 9 //配置触发器,并将所要加载的任务详情给他; 10 @Bean 11 public Trigger triggerDetail(JobDetail jobDetail){ 12 return TriggerBuilder.newTrigger().forJob(jobDetail) 13 .withIdentity("beifenKT","group1")//配置触发器名称,以及所在触发器组名,(方便点调度者对其进行相关操作)上边xml的方式也可以,但是我没写配值不过是继续添加<property>节点而已; 14 .withSchedule(cronSchedule("2/2 * * * * ?")) 15 .build(); 16 } 17 }
4.boot项目入口直接启动。
三:
1.下边springboot拓展一点,刚开始我不知道如何去控制job,启动的时候不让job去执行,而是让前台,也就是使用者去控制是否开启或者停止该作业;
因为一但启动项目就自动执行了,想要让他在启动项目的时候为关闭状态,使用者去在前端操作是否执行。
2.这点在网上找了好久都没有找到解决办法(反正我是没找到,放低要求去找停止任务的方法,百度都没有);网上的都是让调度器shutdown()掉,多作业job的增删改查之类的,
但是与我所描述的目的完全不同。
3.后来琦哥也就是我的社会上第一个直接领导者,给了我一个别人做好的完整的项目,我在这项目中找到了让停止作业和开始作业的方法(其实是自己没好好看调度器Scheduler的源码,都是英语,看起来异常不舒服也就没仔细看)。但我想不通的是网上为啥没有,还是我有点蠢没找到?那首先这一点我给排除了,因为不蠢嘛。
4.下面分享停止作业与打开的作业的方法:scheduler.resumeJob(key);调度器开始作业的方法 ; scheduler.pauseJob(key);调度器停止作业的方法
这里有必要说明一下,scheduler.start(),scheduler.shutdown(),scheduler.unscheduleJob(triggerKey),scheduler.standby()这些方法是
唤醒调度器,药晕调度器,删除作业(你都删除了,下次调用呢?再敲代码吗?还是再重新注入,应该是注入),停止所有作业,等等还有一些添加,修改。大哥我要的是暂停,暂停懂否?
这就是网上告诉我的答案,和我描述的两回事嘛,他们都在干什么,的确有部分人标题党?写的开启和暂停你给我看这些。
5.我的代码:首先这个代码拓展性不高,只能开始和停止特定的作业(也就是特定的配置类实例),高的话需要传参作业key,因为作业比较少就没这样做(偷个懒)。
而且还没有做验证,后期会加上,验证嘛没什么新鲜的。先这样,主要是功能嘛。
1 @Controller 2 @RequestMapping("/admin/db") 3 public class DBController { 4 @Autowired 5 public Scheduler scheduler;//装载调度者
@Autowired
6 QuartzConfig scheduleJob;//配置类实例,就是上边 “3. 编程式配置 ” 7 8 /** 9 * 开始数据库备份, 10 * */ 11 @RequestMapping("/startDb") 12 @ResponseBody 13 public boolean startDb(String cron) {//需要传入cron表达式,这里没有写死。 14 //crudJob.deleteJob(); 15 boolean s = false; 16 try{ 17 JobKey key = scheduleJob.jobDetail().getKey(); 18 scheduler.resumeJob(key); 19 s = true; 20 }catch (Exception e){ 21 e.printStackTrace(); 22 } 23 return s; 24 } 25 26 /** 27 * 停止数据库备份, 28 * */ 29 @RequestMapping("/stopDb") 30 @ResponseBody 31 public boolean stopDb(){ 32 boolean s = false; 33 try { 34 JobKey key = scheduleJob.jobDetail().getKey(); 35 scheduler.pauseJob(key);//核心方法:调度器类中自带的方法 36 s = true; 37 }catch (Exception e){ 38 e.printStackTrace(); 39 } 40 return s; 41 } 42 }
6.然后呢,是可以停止与开始了,但是启动后依然会自动执行,于是我想到了让程序启动的时候去执行一次停止的方法。以下是我的代码
1 @Component//一定要有,否则不会执行 2 @Order(value = 1)//配置执行顺序,如果有多个需要在项目启动时执行的类的话,可以理解为权重,这里是value越小,越先执行 3 public class StopBei implements ApplicationRunner {//这个类也必须继承ApplicationRunner,如果不清楚:那就是springboot你没有学。 4 5 @Autowired 6 public Scheduler scheduler; 7 8 BaseDataU bs = new BaseDataU(); 9 QuzrtzConfig scheduleJob = new QuzrtzConfig(); 10 11 @Override 12 public void run(ApplicationArguments args) throws Exception { 13 JobKey key = scheduleJob.jobDetail().getKey(); 14 scheduler.pauseJob(key);//guanbi 15 System.out.print("===========================已经停止"+args.getClass()+"============================================"); 16 } 17 }
很显然大功告成,总感觉这个方式不是很好,感觉quartz应该有一个作业的管理,就是项目启动时是否执行作业的方法一个trueOrfalse,什么的,无奈没有找到,
如果哪位帅哥或者美眉有这样直接的方法可以留言给我,谢谢。萌新们,我们一起加油!!!。