Tạo scheduler Jobs trong Spring sử dụng Quartz Scheduler
Trong bài này tôi sẽ giới thiệu cách tạo scheduler Jobs trong Spring sử dụng Quartz Scheduler. Công cụ và môi trường phát triển: Spring 4.0.6.RELEASE Quartz 2.2.1 Maven 3 JDK 1.8 Eclipse Neon Release (4.6.0) Cấu trúc project: 1. Thư viện sử dụng trong project ...
Trong bài này tôi sẽ giới thiệu cách tạo scheduler Jobs trong Spring sử dụng Quartz Scheduler.
Công cụ và môi trường phát triển:
- Spring 4.0.6.RELEASE
- Quartz 2.2.1
- Maven 3
- JDK 1.8
- Eclipse Neon Release (4.6.0)
Cấu trúc project:
1. Thư viện sử dụng trong project
<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> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> </dependency> </dependencies>
2. Configure Jobs trong Quartz Scheduler
Có 2 cách để configure job trong Spring Quartz
- Sử dụng MethodInvokingJobDetailFactoryBean
Đây là cách đơn giản nhất trong 2 cách để gọi 1 method đối với 1 bean cụ thể
<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="firstBean" /> <property name="targetMethod" value="printMessage" /> </bean>
Trong job configuration trên ta đơn giản chỉ gọi printMessage method trong firstBean.
- Sử dụng JobDetailFactoryBean
Đây là cách làm khi ta cần thiết lập nâng cao cho việc setting job, pass data một cách flexible cho job.
<bean name="complexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="demo.spring.quartz.ScheduledJob" /> <property name="jobDataMap"> <map> <entry key="secondBean" value-ref="secondBean" /> </map> </property> <property name="durability" value="true" /> </bean>
Trong configuration trên ta đã configure jobClass refer tới cách extends QuartzJobBean, implement Quartz job interface. Trong cách gọi job này, method executeInternal đã được gọi. jobDataMap cho phép ta truyền data cho bean job. Trong trường hợp này, ta đã truyền secondBean sễ sử dụng bởi ScheduledJob.
Dưới đây là referred jobclass cài đặt ScheduledJob
package demo.spring.quartz; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import demo.spring.scheduling.SecondBean; public class ScheduledJob extends QuartzJobBean { private SecondBean secondBean; @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { secondBean.printAnotherMessage(); } public void setAnotherBean(SecondBean secondBean) { this.secondBean = secondBean; } }
3. Configure Triggers cho việc sử dụng Quartz Scheduler
Trigger xác dịnh khoảng thời gian cho 1 scheduler job. Ta có 2 cách để kích hoạt trigger:
- Simple Trigger : Các đơn giản nhất là sử dụng SimpleTriggerFactoryBean
Chúng ta có thể chỉ cụ thể về thời gian bắt đầu, khoảng thời gian delay giữa các triggers và khoảng thời gian lập lại 1 job.
<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>
- Cron Trigger : sử dụng CronTriggerFactoryBean
Cách này flexible hơn cách 1. Nó cho phép ta chọn 1 intance job cụ thể (time, day, date...) và tần suất trong tương lai.
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="complexJobDetail" /> <property name="cronExpression" value="0/5 * * ? * SAT-SUN" /> </bean>
4. Configure SchedulerFactoryBean để tạo và configure Quartz Scheduler
SchedulerFactoryBean kết gắn giữa 2 thành phần jobDetails và triggers để 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>
Dưới đây là file tổng hợp configure quartz demo
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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="demo.spring" /> <bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="firstBean" /> <property name="targetMethod" value="printMessage" /> </bean> <bean name="complexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="demo.spring.quartz.ScheduledJob" /> <property name="jobDataMap"> <map> <entry key="secondBean" value-ref="secondBean" /> </map> </property> <property name="durability" value="true" /> </bean> <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> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="complexJobDetail" /> <property name="cronExpression" value="0/5 * * ? * SAT-SUN" /> </bean> <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>
5. Tạo các POJO đơn giản cho Task Bean
package demo.spring.scheduling; import org.springframework.stereotype.Component; @Component("firstBean") public class FirstBean { public void printMessage() { System.out.println("FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean"); } }
package demo.spring.scheduling; import org.springframework.stereotype.Component; @Component("secondBean") public class SecondBean { public void printAnotherMessage(){ System.out.println("secondBean: I am called by Quartz jobBean using CronTriggerFactoryBean"); } }
6. Tạo Main và Run application
package demo.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 application, output:
INFO: Starting Quartz Scheduler now FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean secondBean: I am called by Quartz jobBean using CronTriggerFactoryBean FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean secondBean: I am called by Quartz jobBean using CronTriggerFactoryBean FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean FirstBean: I am called by MethodInvokingJobDetailFactoryBean using SimpleTriggerFactoryBean