本文转自:点击打开链接
In this post we will see how to schedule Jobs using Quartz Scheduler
with Spring. Spring provides couple of classes that simplify the usage of Quartz within Spring-based applications.
- Secure Spring REST API using OAuth2
- AngularJS+Spring Security using Basic Authentication
- Secure Spring REST API using Basic Authentication
- Spring 4 Caching Annotations Tutorial
- Spring 4 Cache Tutorial with EhCache
- Spring 4 MVC+JPA2+Hibernate Many-to-many Example
- Spring 4 Email Template Library Example
- Spring 4 Email With Attachment Tutorial
- Spring 4 Email Integration Tutorial
- Spring MVC 4+JMS+ActiveMQ Integration Example
- Spring 4+JMS+ActiveMQ @JmsLister @EnableJms Example
- Spring 4+JMS+ActiveMQ Integration Example
- Spring MVC 4+AngularJS Example
- Spring MVC 4+Hibernate 4 Many-to-many JSP Example
- Spring MVC 4+Hibernate 4+MySQL+Maven integration example using annotations
- Spring MVC4 FileUpload-Download Hibernate+MySQL Example
- TestNG Mockito Integration Example Stubbing Void Methods
- Maven surefire plugin and TestNG Example
- Spring MVC 4 Form Validation and Resource Handling
Following technologies being used:
- Spring 4.0.6.RELEASE
- Quartz 2.2.1
- Maven 3
- JDK 1.6
- Eclipse JUNO Service Release 2
Project directory structure:
Following will be the final project directory structure for this example:
Let’s now add the content mentioned in above structure explaining each in detail.
Step 1: Provide Dependencies in Maven 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.websystique.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
>
<
build
>
<
pluginManagement
>
<
plugins
>
<
plugin
>
<
groupId
>org.apache.maven.plugins</
groupId
>
<
artifactId
>maven-compiler-plugin</
artifactId
>
<
version
>3.2</
version
>
<
configuration
>
<
source
>1.6</
source
>
<
target
>1.6</
target
>
</
configuration
>
</
plugin
>
</
plugins
>
</
pluginManagement
>
</
build
>
</
project
>
|
Step 2: Configure Jobs in Quartz Scheduler
There are 2 ways to configure a Job in Spring using Quartz
A : Using MethodInvokingJobDetailFactoryBean
Really handy when you just need to invoke a method on a specific bean. This is the simplest among two.
<!-- 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
>
|
Above job configuration simply invokes printMessage method of bean myJobBean which is simple POJO
B : Using JobDetailFactoryBean
When you need more advanced setup, need to pass data to job, being more flexible.
<!-- 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.websystique.spring.quartz.ScheduledJob"
/>
<
property
name
=
"jobDataMap"
>
<
map
>
<
entry
key
=
"anotherBean"
value-ref
=
"anotherBean"
/>
</
map
>
</
property
>
<
property
name
=
"durability"
value
=
"true"
/>
</
bean
>
|
jobClass
refers to a class which extends QuartzJobBean
, an implementation of Quartz job interface. On invocation of this job, it’s executeInternal
method gets called.
jobDataMap
provides opportunity to pass some data to underlying job bean. In this case, we are passing a bean ‘anotherBean’ which will be used by ScheduledJob.
Below is the referred jobclass (ScheduledJob
) implementation.
com.websystique.spring.quartz.ScheduledJob
package
com.websystique.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;
}
}
|
Step 3: Configure Triggers to be used in Quartz Scheduler
Trigger defines the time when scheduler will run your scheduled job. There are two possible trigger type:
A: Simple Trigger , using SimpleTriggerFactoryBean
You can specify start time, delay between triggers and repeatInterval(frequency) to run the job.
<!-- 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
>
|
B: Cron Trigger , using CronTriggerFactoryBean
It’s more flexible and allows you to choose scheduled job at specific instance (time, day, date,..) and frequency in future.
<!-- 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
>
|
Step 4: Configure SchedulerFactoryBean that creates and configures Quartz Scheduler
SchedulerFactoryBean
glues together jobDetails
and triggers
to Configure Quartz Scheduler
<!-- 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
>
|
Below shown is complete context file for our example
src/main/resources/quartz-context.xml
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context
=
"http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<
context:component-scan
base-package
=
"com.websystique.spring"
/>
<!-- 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
>
<!-- 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.websystique.spring.quartz.ScheduledJob"
/>
<
property
name
=
"jobDataMap"
>
<
map
>
<
entry
key
=
"anotherBean"
value-ref
=
"anotherBean"
/>
</
map
>
</
property
>
<
property
name
=
"durability"
value
=
"true"
/>
</
bean
>
<!-- 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
>
<!-- 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
>
<!-- 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
>
</
beans
>
|
Step 5: Create simple POJO’s Task Beans used in this example
com.websystique.spring.scheduling.MyBean
package
com.websystique.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"
);
}
}
|
com.websystique.spring.scheduling.AnotherBean
package
com.websystique.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"
);
}
}
|
Step 6: Create Main, and Run the application
package
com.websystique.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"
);
}
}
|
Run it as Java application, you will see following output.
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 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
I am called by Quartz jobBean using CronTriggerFactoryBean
I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean
|
You can see that SimpleTrigger invoked job is called every two seconds while the one from CronTrigger is called every five seconds.
That’s it.
Download Source Code