【Quatz】Quatz实践

前言

定时任务是经常遇到的,主要有单机定时和分布式定时。今天简单总结一下写的几个小例子。之后再总结quatz的原理,源码,其他的定时调度器等。

核心组件

  • scheduler调度器
  • job 任务
  • trigger 触发器
    【Quatz】Quatz实践_第1张图片

【Quatz】Quatz实践_第2张图片

使用单纯的quatz包

  • pom
  
        <dependency>
            <groupId>org.quartz-schedulergroupId>
            <artifactId>quartzartifactId>
            <version>2.2.1version>
        dependency>
        <dependency>
            <groupId>org.quartz-schedulergroupId>
            <artifactId>quartz-jobsartifactId>
            <version>2.2.1version>
        dependency>
  • job类
public class HelloJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Hello Time " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE)));
    }

}
  • 主要类
public class LessonTwo {
    public void run() throws  Exception{
        //创建调度器
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        //创建job
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job2","group2").build();
        //创建trigger
//        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger2","group2").startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.MINUTE)).build();
        SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity("trigger2","group2").startAt(DateBuilder.nextGivenSecondDate(null,1)).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).withRepeatCount(3)).build();

        //组装调度器
        scheduler.scheduleJob(jobDetail,trigger);
        //打印
        System.out.println("schduler says " + jobDetail.getKey() + " will run at" + trigger.getStartTime() + "interval " + trigger.getRepeatInterval()+ "repeatCount : "+ trigger.getRepeatCount());
        //调度器开始
        scheduler.start();
        //调度器关闭
        scheduler.shutdown();
    }
}

trigger中可以定义什么时候触发,隔多长时间触发一次,一共触发几次。

使用quatz和spring继承的jar包

  • pom
 
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>

单机版

  • 配置文件
 
    
    <bean id="quartzJob1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.hlp.myProject.job.quartzSimple.QuartzJob1"/>
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="0"/>
            map>
        property>
    bean>
    
    <bean id="cronTrigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="quartzJob1"/>
        <property name="cronExpression" value="0 0/1 * * * ? *"/>
    bean>
    
    <bean id="quartzJob2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject">
            <bean class="com.hlp.myProject.job.quartzSimple.QuartzJob2"/>
        property>
        <property name="targetMethod" value="run"/>
        <property name="concurrent" value="false"/>
    bean>
    <bean id="cronTrigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="quartzJob2"/>
        <property name="cronExpression" value="0 0/1 * * * ? *"/>
    bean>

    
    <bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger1"/>
                <ref bean="cronTrigger2"/>
            list>
        property>
    bean>

配置文件一般是定义好一个组件1,在定义另一组件2时会引用组件1,从而绑定关系。一般这种引用用的是而不是。
- job1

/**
 * 基于基类的单机版定时任务
 * Created by Summer on 2018-06-30.
 */
public class QuartzJob1 extends QuartzJobBean {
    private Integer timeout;
    public void setTimeout(Integer timeout){
        this.timeout = timeout;
    }

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        LocalDateTime localDateTime = LocalDateTime.now();
        String s = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE));
        System.out.println(s + "基于基类QuartzJobBean的任务类开始执行了");
    }
}
  • job2
/**
 * 没有基类的单机版定时任务
 * Created by Summer on 2018-06-30.
 */
public class QuartzJob2 {
    public void run(){
        LocalDateTime local = LocalDateTime.now();
        String s = local.format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE));
        System.out.println(s + "没有基类的单机版定时任务开始执行");
    }

}

集群版

  • 配置文件
 
        <bean id="dataSourceQuartz" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="url" value="${db.url_quartz}"/>
            <property name="username" value="${db.username}"/>
            <property name="driverClassName" value="${db.driver}"/>
            <property name="password" value="${db.password}"/>
            <property name="maxActive" value="${db.maxActive}"/>
            <property name="initialSize" value="${db.initialSize}"/>
            <property name="maxWait" value="${db.maxWait}"/>
            <property name="minIdle" value="${db.minIdle}"/>
            <property name="timeBetweenConnectErrorMillis" value="${db.timeBetweenEvictionRunsMillis}"/>
            <property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"/>
            <property name="validationQuery" value="${db.validationQuery}"/>
            <property name="testWhileIdle" value="${db.testWhileIdle}"/>
            <property name="testOnBorrow" value="${db.testOnBorrow}"/>
            <property name="testOnReturn" value="${db.testOnReturn}"/>
            <property name="poolPreparedStatements" value="${db.poolPreparedStatements}"/>
            <property name="maxOpenPreparedStatements" value="${db.maxOpenPreparedStatements}"/>
            <property name="filters" value="stat,config"/>
            <property name="defaultAutoCommit" value="false"/>
        bean>

        
        <bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <property name="corePoolSize" value="10"/>
            <property name="maxPoolSize" value="100"/>
            <property name="queueCapacity" value="500"/>
        bean>

        
        <bean id="quartzJob1" class="com.hlp.myProject.job.quartzSimple.QuartzJob1" />

        <bean id="testMethod2" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <property name="durability" value="true"/>
            <property name="requestsRecovery" value="true"/>
            <property name="jobClass" value="com.hlp.myProject.job.quartzCluster.MyDetailQuartzJobBean"/>
            <property name="jobDataAsMap">
                <map>
                    <entry key="targetObject" value="quartzJob1"/>
                    <entry key="targetMethod" value="executeInternal"/>
                map>
            property>
        bean>

        
        <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="testMethod2"/>
            <property name="cronExpression" value="0/5 * * * * ? *"/>
        bean>

        
        <bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="dataSource" ref="dataSourceQuartz"/>
            
            <property name="startupDelay" value="30"/>
            <property name="applicationContextSchedulerContextKey" value="applicationKey"/>
            <property name="configLocation" value="classpath:conf/quartz.properties"/>
            <property name="overwriteExistingJobs" value="true"/>
            <property name="autoStartup" value="true"/>
            <property name="triggers">
                <list>
                    <ref bean="trigger1"/>
                list>
            property>
        bean>
  • quatz.properties
org.quartz.scheduler.instanceName=TestScheduler1
db.driver=com.mysql.cj.jdbc.Driver
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered=true 
org.quartz.jobStore.clusterCheckinInterval=20000
#org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL = jdbc:mysql://192.168.22.141:3306/dmsd_quartz?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
#org.quartz.dataSource.myDS.user = root
#org.quartz.dataSource.myDS.password = root
#org.quartz.dataSource.myDS.maxConnections = 30
#org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
  • job

/**
 * quartz分布式集群 工厂类
 * Created by Summer on 2018-06-30.
 */
/*
@PersistJobDataAfterExecution  添加到 Job 类后,表示 Quartz 将会在成功执行 execute() 方法后(没有抛出异常)更新 JobDetail 的 JobDataMap,下一次执行相同的任务(JobDetail)将会得到更新后的值,而不是原始的值。就像@DisallowConcurrentExecution 一样,这个注释基于 JobDetail 而不是 Job 类的实例。
@DisallowConcurrentExecution   不允许并发执行
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class MyDetailQuartzJobBean extends QuartzJobBean implements ApplicationContextAware{
    private static final Logger logger = LoggerFactory.getLogger(MyDetailQuartzJobBean.class);


    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }

    private String targetObject;
    private String targetMethod;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try{
            Object object = ctx.getBean(targetObject);
            Method m = object.getClass().getMethod(targetMethod);
            m.invoke(object);


        }catch (Exception e){
            e.printStackTrace();
            logger.error("定时器异常",e);

        }
    }

    public  void setTargetObject(String targetMethod){
        this.targetObject = targetObject;

    }

    public  void setTargetMethod(String targetMethod){
        this.targetMethod = targetMethod;
    }


}

quatz与spring整合的特点是应用了配置文件,三大组件及关系都配置在了配置文件中。类中需要写的就是一个job.

运行的时候直接点击上面的运行就可以了,因为会执行配置文件中的逻辑。之前还一直疑惑没有main方法从哪里运行呢。

小结

先定义一个任务,在定义一个触发器并把任务绑定到触发器上,然后再定义一个总的调度器,把触发器,任务都绑上去。这就是简单流程了。

你可能感兴趣的:(中间件)