`
frank-liu
  • 浏览: 1682623 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring quartz学习总结: 基本任务结构和定义

 
阅读更多

简介

    最近在工作中一些地方要用到quartz做定时任务,于是结合一些示例和自己的理解整理了几个示例。通过对这些基本概念的分析希望能够加深一点对它们的理解。

 

Quartz

    Quartz是一个开源的定时任务框架,在一些日常的任务中,我们经常有一些这样的需要,比如我们需要隔多少分钟去扫描或者检查一下某些文件,或者在指定的时间点内去处理一些文件。这些定时的任务更多的是一种批处理任务。在一些常用的实现里我们会使用shell脚本来完成这份工作。使用shell脚本来完成的这些任务相对来说是特定于某个任务的,不具备通用性,而且根据问题性质的复杂程度,有时候我们需要提高定时任务的可靠性和性能,这个时候单纯的用一些脚本来处理就显得非常困难和复杂了 。于是quartz这个框架就能帮我们不少忙。

 

第一个示例

    quartz本身的概念并不复杂,我们可以通过一个示例来结合着过一遍。首先我们建一个maven的工程,设置其archetype为quickstart。其中的pom.xml文件内容如下:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.yunzero</groupId>
  <artifactId>SpringQuartzSample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>SpringQuartzSample</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
  	<dependency>
		<groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz</artifactId>
		<version>2.2.1</version>
	</dependency>
	<dependency>
		<groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz-jobs</artifactId>
		<version>2.2.1</version>
	</dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

    这里的内容很简单,主要是添加了对quartz的依赖。

    配置好引用之后,我们创建一个类HelloJob:

package com.yunzero;

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


public class HelloJob implements Job {

	public void execute(JobExecutionContext context) throws JobExecutionException {
		System.out.println("job started...");
	}
}

     在quartz里,我们具体要执行的任务就是通过实现接口Job来定义的。在这里的实现仅仅是打印一个字符串。

    定义好需要执行的任务之后,我们需要的是来定义任务执行的细节了。既然quartz是用来实现计划任务的功能,那么很多执行计划任务需要考虑到的东西就应该在这里定义了。比如说既然这个任务定义好了,它什么时候开始执行呢?需要执行一次还是多少次呢?每次执行的周期是多久呢?于是我们调用执行这个任务的代码实现如下:

package com.yunzero;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class App 
{
    public static void main( String[] args ) throws Exception
    {
        // Define scheduler
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        // Define job
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        		.withIdentity("job1", "group1")
        		.build();

        // Define trigger strategy
        Trigger trigger = TriggerBuilder.newTrigger()
        		.withIdentity("trigger1", "group1")
        		.withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?"))
        		.build();
        sched.scheduleJob(job, trigger);
        // Start the job
        sched.start();
        Thread.sleep(90L * 1000L);
        sched.shutdown(true);
    }
}

     上述的代码其实可以定义成4个部分,第1部分是创建一个Scheduler对象,它用来真正调度和执行job。然后第2部分是注册我们定义的job,这里引用了我们前面定义的HelloJob.class。第3部分则定义触发这些任务的细节。这里的CronScheduleBuilder定义了该任务每20秒执行一次。第4部分则是通过scheduler启动job。sched.scheduleJob()方法里有两个参数,分别引用了job对象和trigger对象。在实际中我们可以实现一个很好的job和trigger的分离,将需要的job和对应的trigger绑定起来。

     就这么几个简单的步骤,我们定义的一个计划任务就完成了。它会每20秒打印一段字符串。然后主线程sleep 90秒之后再退出quartz。如果我们执行上述的代码,其运行结果如下:

 

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
job started...

     结合前面的代码和执行结果,我们可以发现最常用的quartz的过程主要就是scheduler, job, trigger它们三个之间来处理的。因此,只要把握好这个就可以实现一个理想的定时调度任务。

 

结合spring

    上面的这个示例只是用java调用的原生quartz api实现的。如果使用spring的话,这个框架本身对集成quartz有更好的支持。再来看看结合spring实现定时任务的示例。

     我们再创建一个maven的工程,其类型依然是archetype-quickstart。唯一不同的地方在于我们引入更多spring的库,其pom.xml文件内容如下:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.yunzero.spring</groupId>
  <artifactId>SpringQuartzIntegrationExample</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>
  <name>SpringQuartzIntegrationExample</name>

	<properties>
		<springframework.version>4.0.6.RELEASE</springframework.version>
		<quartz.version>2.2.1</quartz.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<!-- Transaction dependency is required with Quartz integration -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		
		<!-- Quartz framework -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>${quartz.version}</version>
		</dependency>

	</dependencies>
</project>

     这里除了引用了几个spring相关的库以外和前面的示例没太大差别。

    我们再来看job的定义。在spring里,定义quartz job的方式稍微有点不一样,它是需要继承类QuartzJobBean,我们这里的一个实现如下:

 

package com.yunzero.spring.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.websystique.spring.scheduling.AnotherBean;

public class ScheduledJob extends QuartzJobBean{

	private AnotherBean anotherBean; 
	
	@Override
	protected void executeInternal(JobExecutionContext arg0)
			throws JobExecutionException {
		anotherBean.printAnotherMessage();
	}

	public void setAnotherBean(AnotherBean anotherBean) {
		this.anotherBean = anotherBean;
	}
}

    这部分代码就是一个典型的spring注入,实际上调用了anotherBean的方法。具体job的执行是在executeInternal方法里。而AnotherBean的实现也很简单:

package com.yunzero.spring.scheduling;

import org.springframework.stereotype.Component;

@Component("anotherBean")
public class AnotherBean {
	
	public void printAnotherMessage(){
		System.out.println("I am called by Quartz jobBean using CronTriggerFactoryBean");
	}
	
}

    因为是要将这些任务通过spring的配置文件来拼接到一起,我们来看看具体的配置文件该怎么设置。

    在spring里,如果我们要执行一个计划任务,需要定义一个JobDetail,用它来封装我们具体执行的任务。结合前面纯quartz的示例,我们发现它们其实本质上是一样的。这里的定义如下:

<!-- For times when you just need to invoke a method on a specific object -->
	<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="myBean" />
		<property name="targetMethod" value="printMessage" />
	</bean>

   spring默认提供了一个叫MethodInvokingJobDetailFactoryBean,我们需要将定义好的对象和需要调用的方法传给它。这里对应的是一种类型的jobDetail定义。对应的myBean定义如下:

package com.yunzero.spring.scheduling;

import org.springframework.stereotype.Component;

@Component("myBean")
public class MyBean {

	public void printMessage() {
		System.out.println("I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean");
	}
	
}

     这种封装的方式很简单,就是我定义了一个对象和它对应的方法。如果我们需要将它们封装成一个job了,只要把类的名字和对应的方法传进去就可以了。

    除了上述的JobDetail构造方式,还要一种更复杂一些,它的定义如下:

<!-- For times when you need more complex processing, passing data to the scheduled job -->
	<bean name="complexJobDetail" 	class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="com.yunzero.spring.quartz.ScheduledJob" />
		<property name="jobDataMap">
			<map>
				<entry key="anotherBean" value-ref="anotherBean" />
			</map>
		</property>
		<property name="durability" value="true" />
	</bean>

     这里因为要用到一些对象的引用,对这些对象或者参数的传递可以通过jobDataMap来处理。

    和纯手工写的步骤一样,定义好了jobDetail之后就需要定义trigger了。

 

Trigger定义

    在spring里也有两种常见的trigger定义,一种为simpleTrigger,其定义如下:

<!-- Run the job every 2 seconds with initial delay of 1 second -->
	<bean id="simpleTrigger"  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
		<property name="jobDetail" ref="simpleJobDetail" />
		<property name="startDelay" value="1000" />
		<property name="repeatInterval" value="2000" />
	</bean>

   这里表示对应前面那个simpleDetail的任务,它首先延迟1秒钟然后启动,每2秒钟执行一次这个任务。

   还有一种trigger的定义是cronjob的方式定义的,它的一个配置示例如下:

<!-- Run the job every 5 seconds only on weekends -->
	<bean id="cronTrigger"  class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="complexJobDetail" />
		<property name="cronExpression" value="0/5 * * ? * SAT-SUN" />
	</bean>

    在这个示例里,我们用这个trigger来驱动前面那个复杂的jobDetail。如果定义cronTrigger,需要设置cronExpression。比如这里设定该任务只在周末执行,且每5秒钟执行一次。

    按照我们理解的套路,要让这些定义好的job能够跑起来,我们还需要有一个scheduler,在spring里,这些也是准备好了的。针对前面的两个jobDetail和trigger,它的典型配置如下:

 

<!-- Scheduler factory bean to glue together jobDetails and triggers to Configure Quartz Scheduler -->
	<bean  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobDetails">
			<list>
				<ref bean="simpleJobDetail" />
				<ref bean="complexJobDetail" />
			</list>
		</property>

		<property name="triggers">
			<list>
				<ref bean="simpleTrigger" />
				<ref bean="cronTrigger" />
			</list>
		</property>
	</bean>

   这样,到这里所有的配置就完成了。而启动整个任务的过程和使用spring的普通应用一样:

 

package com.yunzero.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppMain {
	public static void main(String args[]){
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartz-context.xml");
	}

}

 

 执行这个应用程序,会得到结果如下:

 

Dec 21, 2014 10:03:11 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4f9f6e39: startup date [Sun Dec 21 22:03:11 CST 2014]; root of context hierarchy
Dec 21, 2014 10:03:11 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [quartz-context.xml]
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Dec 21, 2014 10:03:12 PM org.springframework.context.support.DefaultLifecycleProcessor start
INFO: Starting beans in phase 2147483647
Dec 21, 2014 10:03:12 PM org.springframework.scheduling.quartz.SchedulerFactoryBean startScheduler
INFO: Starting Quartz Scheduler now
I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean
I am called by Quartz jobBean using CronTriggerFactoryBean
I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean
I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean
I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean

    除了前面的那些输出的日志,这里每2秒钟会输出simpleJobDetail的内容,每5秒钟则会输出complexDetail的那个任务的内容。

 

总结

    在这两个示例里,我们首先通过一个纯手工的过程来完成一个任务调度的示例。它的主要步骤为1.定义job 2. 定义trigger 3. 定义scheduler来拼接。在后续使用spring的示例里,其实也是这么一个步骤,只不过spring提供了一些实现的支持,需要在配置文件里指定不同的jobDetail类型和trigger类型。

 

参考材料

http://websystique.com/spring/spring-4-quartz-scheduler-integration-example/

http://docs.spring.io/spring/docs/4.1.4.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#scheduling-quartz

 

 

分享到:
评论
2 楼 frank-liu 2015-02-03  
在世界的中心呼喚愛 写道
楼主,我用你例子运行,提示找不到
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'anotherBean' is defined


是不是还少了spring配置

我前面没有把详细的spring配置文件给贴出来,是你需要在配置文件里添加一个bean的定义,就是前面代码里声明public class AnotherBean所对应的那个。你可以添加一个类似如下的bean定义应该就可以了:<bean id="anotherBean" class="com.yunzero.spring.scheduling.AnotherBean"/>
1 楼 在世界的中心呼喚愛 2015-02-03  
楼主,我用你例子运行,提示找不到
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'anotherBean' is defined


是不是还少了spring配置

相关推荐

    spring quartz学习总结: cluster的配置和示例

    Spring Quartz是一款广泛使用的Java任务调度框架,用于在应用程序中安排周期性或一次性任务。Quartz集群(Cluster)是指多个Quartz实例(节点)共享相同的作业和触发器,从而实现高可用性和故障转移。本文将深入探讨...

    Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置

    Quartz是一款开源的作业调度框架,它允许程序在特定时间执行预定的任务,而Spring则是一个强大的企业级应用开发框架,提供了丰富的依赖注入(DI)和面向切面编程(AOP)等功能。将两者结合,可以方便地在Spring应用...

    Spring Quartz Demo

    通过这个示例项目,开发者可以学习如何在实际应用中使用Spring和Quartz进行任务调度,理解如何定义、配置和管理定时任务,以及如何在Spring环境中优雅地集成Quartz。这不仅有助于提高代码的可维护性,还能使定时任务...

    Spring线程时间配置:Quartz和CronExpression

    在Spring框架中,为了实现定时任务的调度,引入了一个强大的工具——Quartz。Quartz是一个功能丰富的开源作业调度器,可以用于Java应用程序中的作业调度。它支持触发器、作业、日历等功能,并且能够根据复杂的Cron...

    spring+quartz实现动态设置定时任务

    2. **定义Job和Trigger**:Quartz中的Job代表一个具体的任务,而Trigger则定义了任务何时执行。在Spring中,我们可以通过实现`org.springframework.scheduling.quartz.JobDetailBean`和`org.springframework....

    Spring2.5+Quartz定时任务简单例子web工程

    总结来说,这个项目是一个基础的示例,展示了如何在 Spring 2.5 框架下利用 Quartz 实现 Web 应用的定时任务。开发者可以通过学习这个例子,了解如何将这两个框架整合在一起,以及如何定义、调度和管理任务。同时,...

    Spring Quartz定时任务 jar包

    Quartz是一个开源的作业调度框架,它允许程序创建、调度和执行作业,而Spring框架则为Quartz提供了良好的整合,使得在Spring应用中配置和管理定时任务变得更加简便。 在Spring中集成Quartz,我们可以利用Spring的...

    spring_quartz项目可以直接运行

    "springquartz—项目可以直接运行" 这个压缩包中,通常会包含以下部分: 1. **pom.xml**:Maven 项目配置文件,包含了 Spring 和 Quartz 相关依赖。 2. **src/main/java**:源代码目录,可能包含自定义的 Job 类、...

    spring quartz 整合示例

    通过Spring的XML配置或注解方式,我们可以轻松地将Quartz任务与Spring应用上下文集成。这使得任务的创建、依赖注入和管理变得更加简单。 在压缩包内的文件中: 1. `FrequencyTaskSchudle.java` - 这个文件可能包含...

    Spring quartz任务调度

    标题“Spring quartz任务调度”指的是在Java开发中利用Spring框架集成Quartz库来实现应用程序的任务调度功能。Quartz是一款开源的作业调度框架,它允许开发者安排任务在特定时间执行,而Spring框架则提供了与Quartz...

    Quartz与Spring整合练习源代码

    通过阅读源代码,你可以深入了解如何在Spring环境中定义和执行Quartz定时任务,以及如何组织项目的结构。 在`YourJobClass`中,你需要定义一个`execute`方法,这是Quartz实际执行的任务。你可以在这个方法中调用...

    spring+quartz实现定时任务动态管理

    总结来说,这个项目展示了如何结合Spring、Quartz、jQuery、Bootstrap和MyBatis分页插件,构建一个功能完善的定时任务管理系统。通过这个系统,开发者和管理员可以轻松地对定时任务进行动态管理,提高工作效率,同时...

    SpringBoot集成Quartz分布式定时任务

    集成Quartz到SpringBoot项目中,不仅可以实现基本的定时任务,还可以通过分布式特性在多台服务器上实现高可用和负载均衡,提高系统的健壮性。但要注意,合理规划和设计任务调度,避免资源浪费和任务冲突,确保系统的...

    Spring Quartz应用相关jar

    Spring Quartz是将Quartz定时任务框架与Spring框架集成的一个解决方案,它允许开发者在Spring的管理环境中轻松地配置和运行Quartz作业。这个压缩包包含了实现这一功能所需的关键库文件。 1. **Spring.jar**: 这是...

    Spring Quartz 调度器的使用,定时任务[含例子]

    Spring Quartz 是一个强大的开源任务调度框架,用于在Java应用程序中执行定时任务。它与Spring框架无缝集成,使得在Spring...通过阅读和运行这些示例,开发者可以更直观地学习如何在自己的项目中应用Spring Quartz。

    Spring Quartz动态配置时间.rar

    Spring Quartz 是一个强大的任务调度库,它允许开发者在Java应用程序中安排定时任务。这个压缩包“Spring Quartz动态配置时间.rar”包含的PDF文档很可能是关于如何在Spring框架中使用Quartz进行动态配置时间的详细...

    spring的quartz定时任务相关(持久化任务)

    为了更好地管理Quartz任务,尤其是需要在系统重启后仍然能够继续执行未完成的任务,这就需要将任务状态持久化到数据库中。持久化机制不仅可以帮助我们跟踪任务的执行历史,还能确保在发生异常或系统故障时能够进行...

    11-Spring+Quartz定时任务最简集群版1

    【Spring+Quartz定时任务最简集群版1】是一个基于Spring和Quartz的定时任务解决方案,用于在分布式环境中实现任务的自动调度。本项目作为Dubbo工程的一部分,它依赖于Dubbo的一些公共组件,同时也提供了将定时任务...

    spring quartz

    Spring Quartz 是一个强大的任务调度框架,它允许开发者在Spring应用中轻松地定义和执行定时任务。这个框架结合了Spring框架的灵活性与Quartz Scheduler的功能,为应用程序提供了灵活且可扩展的定时任务管理。 ...

    Spring+quartz定时.zip

    在IT行业中,Spring框架是Java领域最常用的轻量级应用框架之一,而Quartz则是一个强大的、开源的作业调度框架,常用于实现定时任务。本文将深入探讨如何将Spring MVC与Quartz结合,以及如何利用数据库来动态管理定时...

Global site tag (gtag.js) - Google Analytics