Quartz简单使用

Quartz有两种,编程式的和声明式的,编程式的是直接在类中写代码的,声明式的是集成Spring在xml中配置。

一、编程式

例子都是基于Quartz 2.2.1

package com.test.quartz;

import static org.quartz.DateBuilder.newDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.GregorianCalendar;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;

public class QuartzTest {

    public static void main(String[] args) {
        try {
            //创建scheduler
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            //定义一个Trigger
            Trigger trigger = newTrigger().withIdentity("trigger1", "group1") //定义name/group
                .startNow()//一旦加入scheduler,立即生效
                .withSchedule(simpleSchedule() //使用SimpleTrigger
                    .withIntervalInSeconds(1) //每隔一秒执行一次
                    .repeatForever()) //一直执行,奔腾到老不停歇
                .build();

            //定义一个JobDetail
            JobDetail job = newJob(HelloQuartz.class) //定义Job类为HelloQuartz类,这是真正的执行逻辑所在
                .withIdentity("job1", "group1") //定义name/group
                .usingJobData("name", "quartz") //定义属性
                .build();

            //加入这个调度
            scheduler.scheduleJob(job, trigger);

            //启动之
            scheduler.start();

            //运行一段时间后关闭
            Thread.sleep(10000);
            scheduler.shutdown(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.test.quartz;

import java.util.Date;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloQuartz implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail detail = context.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("say hello to " + name + " at " + new Date());
    }
}

这个例子很好的覆盖了Quartz最重要的3个基本要素:

  • Scheduler:调度器。所有的调度都是由它控制。
  • Trigger: 定义触发的条件。例子中,它的类型是SimpleTrigger,每隔1秒中执行一次(什么是SimpleTrigger下面会有详述)。
  • JobDetail & Job: JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中,例子中是HelloQuartz。 为什么设计成JobDetail + Job,不直接使用Job?这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

二、声明式

先导入jar

<dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.3</version>
        </dependency>

配置XML文件,记得一定要加载这个xml,我的xml取名叫做spring-context-quartz.xml,是在web.xml中通过通配符形式匹配加载的

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:/spring-context*.xml</param-value>
	</context-param>

在Spring中使用Quartz有两种方式实现:第一种是任务类继承QuartzJobBean(可传参),第二种则是在配置文件里定义任务类和要执行的方法(不可传参),类和方法仍然是普通类,下面没有注释的是第二种,有注释的是第一种

	<!--默认扫描的包路径 -->
	<context:component-scan base-package="net.nengmao.backend.vendor.common.utils.quartz" />


	<bean id="simpleJobDetail"
		  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="myBean" />
        <!-- 任务类中需要执行的方法 -->
		<property name="targetMethod" value="printMessage" />
        <!-- 上一次未执行完成的,要等待有再执行。 -->
        <property name="concurrent" value="false"></property>
	</bean>

<!--	<bean id="firstComplexJobDetail"
		  class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass"
				  value="net.nengmao.backend.vendor.common.utils.quartz.FirstScheduledJob" />
		<property name="jobDataMap">
			<map>
				<entry key="anotherBean" value-ref="anotherBean" />
			</map>
		</property>
		<property name="Durability" value="true"/>
	</bean>-->
	<!-- 距离当前时间一分钟之后执行,之后每隔五分钟执行一次 -->
	<bean id="mySimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
		<property name="jobDetail"  ref="simpleJobDetail"/>
		<property name="startDelay"  value="120000"/>
		<property name="repeatInterval"  value="300000"/>
	</bean>

	<!-- 每隔5秒钟执行一次 -->
<!--	<bean id="myCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail"  ref="firstComplexJobDetail"/>
		<property name="cronExpression"  value="0/5 * * ? * *"/>
	</bean>-->

	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobFactory">
			<bean class="net.nengmao.backend.vendor.common.utils.quartz.MyJobFactory"/>
		</property>
		<property name="jobDetails">
			<list>
				<ref bean="simpleJobDetail"/>
			<!--	<ref bean="firstComplexJobDetail"/>-->
			</list>
		</property>
		<property name="triggers">
			<list>
				<ref bean="mySimpleTrigger"/>
				<!--<ref bean="myCronTrigger"/>-->
			</list>
		</property>
	</bean>
</beans>


第一种的任务类

/**
 * 	 2018-5-18
 * Quartz工具类(能传参)
 */
@Component
public class FirstScheduledJob extends QuartzJobBean{
     private AnotherBean anotherBean;
     
     public void setAnotherBean(AnotherBean anotherBean){
    	 this.anotherBean = anotherBean;
     }
	@Override
	protected synchronized void executeInternal(JobExecutionContext arg0)
			throws JobExecutionException {  
            System.out.println("暂无需要修改的图片");
	}
}

辅助传参的类

/**
 * 	 2018-5-18
 * Quartz工具类
 */
@Component("anotherBean")
public class AnotherBean {
	public void printAnotherMessage() {
		System.out.println("AnotherMessage");
	}
}

注意:第一种存在Spring quartz定时任务service注入问题,具体原因可以百度,有很多解释,我这里直接给出方案

写一个辅助类,然后在Quartz配置文件中引入这个配置类,就是上面配置文件的红色部分


/**
 * 	 2018-5-18
 * 	 by_will
 * Quartz解决Spring注入失败辅助类
 */
public class MyJobFactory extends AdaptableJobFactory{
    //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

然后还得把他引入到Spring中去,这样就可以解决Spring quartz定时任务service注入问题了

<bean id="jobFactory" class="net.nengmao.backend.vendor.common.utils.quartz.MyJobFactory"></bean>


第二种的任务类

/**
 * 	 2018-5-18
 * Quartz不能传参的
 */
@Component("myBean")
public class MyBean {
	protected static Logger logger = LoggerFactory.getLogger(MyBean.class);
	@Autowired
	private ProductImgService productImgService;
	@Autowired
	private ProductImgDao productImgDao;
	//int i=0;
	public void printMessage() {
		
        System.out.println("定时器开始检测是否有符合要求的图片");
	}
}


编程式可以看看这个博客,挺好的:https://www.cnblogs.com/dupang/p/6063734.html


个人觉得学一个东西,最基本的就是要会用,用熟悉了自然会去研究实现原理,以上有问题欢迎各位大牛斧正,感谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值