定时任务_定时任务Quartz入门

前言

53fa9ac1d770701146425215e0fa06f6.png

Quartz是一个定时任务框架,即可以在程序运行期间,定时定期的做出些什么事情,比如发邮件,重启机器,清除缓存等等。

java.util.Timer也可以做到这些功能,但是Quartz框架毕竟是框架,比java自带的定时工具要强大很多。初次体验对于具体细节还不太清楚,目前主要先学会使用,更深入的要等有具体场景具体需求了再深入了解。

bf58666b9437714c9ad42e91dd913e29.png

使用java.util.Timer

53fa9ac1d770701146425215e0fa06f6.png

因为对定时任务不熟悉,所以我先使用了一下 Timer 这个java自带的定时任务工具。

import java.util.Date;import java.util.Timer;import java.util.TimerTask;/** * @author 拽小白 * @create 2020-07-18-53 */public class TimerTest {    // 一个简单的demo,每2秒就打印一行 123    public static void main(String[] args) {        Timer timer = new Timer();        timer.scheduleAtFixedRate(new TimerTask() {            @Override            public void run() {                System.out.println("123");            }        }, new Date(), 2000);    }}

‍从这个简单的demo中可以看出来使用Timer只需要创建一个Timer对象,然后使用Timer的scheduleAtFixedRate()方法,放入一个TimeTask匿名内部类并实现里面的run方法和想要间隔的时间就可以完成这个定时任务了。

当然也可以以其他的形式完成所需的形式的定时任务,只要改变所使用的Timer构造方法和启动定时的方法就可以了,具体参考jdk的api文档。 bf58666b9437714c9ad42e91dd913e29.png

使用Quartz

53fa9ac1d770701146425215e0fa06f6.png

使用了java自带的定时工具Timer之后,我对定时任务有了个大概的了解,于是开始上手Quartz,在csdn上找到了一个入门小demo。

import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Random;/** * @author 拽小白 * @create 2020-07-18-07 */public class PrintWordsJob implements Job {    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {        //System.out.println(jobExecutionContext.getJobDetail().getJobDataMap().get("msg"));        //System.out.println(jobExecutionContext.getTrigger().getJobDataMap().get("trigger1"));        String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());        System.out.println("PrintWordsJob start at: " + printTime + ", prints: Hello Job-" + new Random().nextInt(100));        System.out.println("==================================================");    }}
import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import java.util.concurrent.TimeUnit;/** * @author 拽小白 * @create 2020-07-18-10 */public class MyScheduler {    public static void main(String[] args) throws SchedulerException, InterruptedException {        SchedulerFactory schedulerFactory = new StdSchedulerFactory();        Scheduler scheduler = schedulerFactory.getScheduler();        JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class).withIdentity("job1", "group1").usingJobData("msg", "这是一个测试job").build();        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")                .usingJobData("trigger1", "这是一个测试trigger")                .startNow() //立即生效                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())                .build();        scheduler.scheduleJob(jobDetail, trigger);        System.out.println("-----------scheduler start!!------------");        scheduler.start();        //主线程睡眠1分钟        TimeUnit.MINUTES.sleep(1);        scheduler.shutdown();        System.out.println("-----------scheduler shutdown!!------------");    }}
从这个小demo中可以大致看出来一个Quartz启动需要 SchedulerJobTrigger 。第一段代码很明显是用来描述定时任务的即 Job,它实现了 org.quartz.Job 接口,这个接口里只有一个 public void execute(JobExecutionContext jobExecutionContext) 方法,所要完成的任务的内容就是在这里面写。参数 jobExecutionContext 根据字面意思可以得知这是一个job执行的上下文,包含了Quartz运行时的环境以及Job本身的详细数据信息,所以:
System.out.println(jobExecutionContext.getJobDetail().getJobDataMap().get("msg"));System.out.println(jobExecutionContext.getTrigger().getJobDataMap().get("trigger1"));JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class).usingJobData("msg", "这是一个测试job").build();SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")                .usingJobData("trigger1", "这是一个测试trigger")

这两行代码就是对应第二段代码的usingJobDataJobDataMap实现了JDK的Map接口,所以可以以Key-Value的形式存储数据。

第二段代码就是Scheduler调度触发器Trigger触发Job的过程,这个demo使用的是SimpleTrigger,还有一种CronTrigger,SimpleTrigger只能定间隔时间,但是CronTrigger可以定启动时间、关闭时间、时间间隔等,功能要比SimpleTrigger强大

CronTrigger是基于Cron表达式的。Cron表达式由7个子表达式组成字符串,格式如下:

[秒][分][小时][日][月][周][年]

举个栗子:* 30 10 ?* 1/5 *   [指定年份] 的 [周一到周五][不指定日][上午10时][30分][指定秒]   00 00 00 ?* 10,11,12 1#5 2018   表示   2018年的10、11、12月的第一周的星期五这一天的0时0分0秒去执行任务。Cron表达式太复杂,所以可以通过在线生成Cron表达式的工具来生成自己想要的表达式:http://cron.qqe2.com/

bf58666b9437714c9ad42e91dd913e29.png

在spring里使用Quartz

53fa9ac1d770701146425215e0fa06f6.png

通过简单的使用Quartz,我知道了Quartz主要是三个部分:Scheduler、Trigger、Job,但是在项目中一般都会与spring框架进行整合,所以我又去找了一些关于spring整合Quartz的博客进行了学习。

spring整合Quartz非常简单,只要导入相关jar包然后加上一些配置就好了。毕竟最主要的代码是Job的实现。

关于Job的实现,有两种,一种是继承 org.springframework.scheduling.quartz.QuartzJobBean 然后实现 protected void executeInternal(JobExecutionContext jobExecutionContext) 方法,与之前单独使用Quartz的时候实现 org.quartz.Job 接口一样。还有一种是直接编写类和方法。

示例Demo 第一步导入所需jar包或添加依赖。
<dependency>    <groupId>org.quartz-schedulergroupId>    <artifactId>quartzartifactId>    <version>2.3.0version>dependency><dependency>    <groupId>org.quartz-schedulergroupId>    <artifactId>quartz-jobsartifactId>    <version>2.3.0version>dependency><dependency>    <groupId>org.springframeworkgroupId>    <artifactId>spring-context-supportartifactId>    <version>5.2.5.RELEASEversion>dependency><dependency>    <groupId>org.springframeworkgroupId>    <artifactId>spring-txartifactId>    <version>5.2.5.RELEASEversion>dependency>
第二步使用上述第二种方法编写Job,即被调度的类和方法。
/** * @author 拽小白 * @create 2020-07-18-48 */public class QuartzJob {    public void doSimpleBusiness() {        System.out.println("---------quartz + 固定时长---------");    }    public void doCronBusiness() {        System.out.println("---------quartz + cron表达式----------");    }}
第三步配置spring的相关配置文件,这里配置了两种JobDetail和Trigger,为的是体现两种方式的Trigger。
<bean id="quartzJob" class="com.study.quartz.QuartzJob"/><bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">    <property name="targetObject" ref="quartzJob"/>    <property name="targetMethod" value="doSimpleBusiness"/>bean><bean id="trigger1" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">    <property name="jobDetail" ref="jobDetail1"/>    <-- 每一秒执行一次 -->    <property name="repeatInterval" value="1000"/>bean><bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">    <property name="targetObject" ref="quartzJob"/>    <property name="targetMethod" value="doCronBusiness"/>bean><bean id="trigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">    <property name="jobDetail" ref="jobDetail2"/>    <-- 这里的cron表达式是指每5秒执行一次 -->    <property name="cronExpression" value="*/5 * * * * ?"/>bean><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">    <property name="triggers">        <list>            <ref bean="trigger1"/>            <ref bean="trigger2"/>        list>    property>bean>
第四步查看启动结果。
---------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + cron表达式-------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + 固定时长------------------quartz + cron表达式----------
bf58666b9437714c9ad42e91dd913e29.png

使用Spring+Quartz完成定时发邮件的功能

53fa9ac1d770701146425215e0fa06f6.png

定时发邮件的功能无非就是将Job里的内容变成发邮件,而发邮件我使用的是java里的Mail模块,与spring整合一下就好了,就是一些配置的事情。

第一步添加依赖。

<dependency>    <groupId>javax.mailgroupId>    <artifactId>mailartifactId>    <version>1.4.7version>dependency>

第二步在spring里配置好邮件的相关配置。

// properties文件protocol=smtp   // 发邮件所用协议host=smtp.qq.com   // 这里使用的是qq邮箱的服务,要去qq邮箱里开启这个服务,具体操作百度一下mailUsername=*********  // 这里填写你的邮箱,即开通了smtp服务的邮箱mailPassword=*********  // 这里填写密码,即开通smtp服务时会告知一个使用该服务的密码
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">    <property name="protocol" value="${protocol}"/>    <property name="username" value="${mailUsername}"/>    <property name="password" value="${mailPassword}"/>    <property name="host" value="${host}"/>    <property name="javaMailProperties">        <props>            <prop key="mail.smtp.auth">trueprop>        props>    property>bean>

第三步编写Job类和方法,这里我是把发邮件的部分和被调度的方法分开了。

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.PropertySource;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.mail.javamail.MimeMessageHelper;import org.springframework.stereotype.Component;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import java.text.SimpleDateFormat;import java.util.Date;/** * @author 拽小白 * @create 2020-07-18-20 */@Component@PropertySource("classpath:spring.properties")public class MailUtil {    @Autowired    private JavaMailSender javaMailSender;    @Value("${mailUsername}")    private String username;    public void sendMail() {        try {            MimeMessage mimeMessage = javaMailSender.createMimeMessage();            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);            helper.setTo("发送到哪里的具体邮箱");            helper.setSubject("邮件的主题");            helper.setText("邮件的内容");            helper.setFrom(new InternetAddress(username, "署名", "UTF-8"));            javaMailSender.send(mimeMessage);            String now = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());            System.out.println("邮件已发送成功!! 现在是:" + now);        } catch (Exception e) {            e.printStackTrace();        }    }}
import com.study.utils.MailUtil;import org.springframework.beans.factory.annotation.Autowired;/** * @author 拽小白 * @create 2020-07-18-55 */public class SendMailJob {    @Autowired    private MailUtil mailUtil;    public void sentMail() {        mailUtil.sendMail();    }}

第四步配置tigger和scheduler。

<bean id="mailJob" class="com.study.quartz.SendMailJob"/><bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">    <property name="targetObject" ref="mailJob"/>    <property name="targetMethod" value="sentMail"/>bean><bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">    <property name="jobDetail" ref="jobDetail"/>    <property name="repeatInterval" value="10000"/>bean><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">    <property name="triggers">        <list>            <ref bean="trigger"/>        list>    property>bean> 

第五步查看结果。

c2708442b34f5f5caabf96de0d35a5cd.png

bf58666b9437714c9ad42e91dd913e29.png 喜欢就点个在看再走吧 f9d3baaaf524224ef9381218d7ae1072.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值