1、Spring建立JobDetail的两种方式java
定时任务两种方式,Spring很好的封装使用Quartz的细节,第一种方式是利用SPring封装的Quartz类进行特定方法的实现,第二种是经过透明的使用Quartz达到定时任务开发的目的,整体说第二种对开发人员更方便!web
配置Spring的任务调度抽象层简化了任务调度,在Quartz的基础上提供了更好的调度对象。Spring使用Quartz框架来完成任务调度,建立Quartz的做业Bean(JobDetail),有一下两种方法:spring
1:利用JobDetailBean包装QuartzJobBean子类(即Job类)的实例。编程
2:利用MethodInvokingJobDetailFactoryBean工厂Bean包装普通的Java对象(即Job类)。app
说明:框架
1:采用第一种方法 建立job类,必定要继承QuartzJobBean ,实现 executeInternal(JobExecutionContextthis
jobexecutioncontext)方法,此方法就是被调度任务的执行体,而后将此Job类的实例直接配置到JobDetailBean中便可。这种方法和在普通的Quartz编程中是同样的。spa
2:采用第二种方法建立Job类,无须继承父类,直接配置MethodInvokingJobDetailFactoryBean便可。但须要指定一下两个属性:线程
targetObject:指定包含任务执行体的Bean实例。code
targetMethod:指定将指定Bean实例的该方法包装成任务的执行体。
2、整合方式一示例步骤
1、将spring核心jar包和Spring-context-support.jar导入类路径。
###不用导入quartz.jar?,千万不忘了导入spring-context-support-3.2.0.M2.jar:这是由于这种方式是利用SPring封装的Quartz类进行特定方法的实现。
咱们用到的两个JobDetail:org.springframework.scheduling.quartz.JobDetailBean和org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
触发器:org.springframework.scheduling.quartz.CronTriggerBean ;调度器:org.springframework.scheduling.quartz.SchedulerFactoryBean 都来源于这个jar包。
2、编写Job类PunchJob(该类必须继承QuartzJobBean)
package org.crazyit.hrsystem.schedule; import java.util.Date; import org.springframework.scheduling.quartz.QuartzJobBean; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.crazyit.hrsystem.service.EmpManager; public class PunchJob extends QuartzJobBean { //判断做业是否执行的旗标 private boolean isRunning = false; //该做业类所依赖的业务逻辑组件 private EmpManager empMgr; public void setEmpMgr(EmpManager empMgr) { this.empMgr = empMgr; } //定义任务执行体 public void executeInternal(JobExecutionContext ctx) throws JobExecutionException { if (!isRunning) { System.out.println("开始调度自动打卡"); isRunning = true; //调用业务逻辑方法 empMgr.autoPunch(); isRunning = false; } } }
3、编写quartz.xml配置文件
<?xml version="1.0" encoding="GBK"?> <!-- 指定Spring配置文件的Schema信息 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" default-lazy-init="false"> <!-- 定义<SPAN style="FONT-FAMILY: 'courier new', 'courier'">一</SPAN>个业务逻辑组件,继承业务逻辑组件的模板 --> <bean id="empManager" class="org.crazyit.hrsystem.service.impl.EmpManagerImpl" parent="managerTemplate"/> <!-- 定义触发器来管理任务Bean --> <bean id="cronTriggerPunch" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <!-- 使用嵌套Bean的方式来定义任务Bean --> <bean class="org.springframework.scheduling.quartz.JobDetailBean"> <!-- 指定任务Bean的实现类 --> <property name="jobClass" value="org.crazyit.hrsystem.schedule.PunchJob"/> <!-- 为任务Bean注入属性 --> <property name="jobDataAsMap"> <map> <entry key="empMgr" value-ref="empManager"/> </map> </property> </bean> </property> <!-- 指定Cron表达式:周一到周五7点、12点执行调度 --> <property name="cronExpression" value="0 0 7,12 ? * MON-FRI"/> </bean> <!-- 执行实际的调度器--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTriggerPunch"></ref> <!--<ref local="cronTriggerPunch"/> 二者均可以用 --> </list> </property> </bean> </beans>
job data map(jobDataAsMap)可经过JobExecutionContext (执行时传递)获取。JobDetailBean将 job data map的属性映射到job的属性。如例所示,若是job类PunchJob中包含一个empMgr属性,JobDetailBean将自动注入到Job类PunchJob的实例中,可用于传递参数。若是不写明,就会报
java.lang.NullPointerException错误,主要是由于没有注入Bean。
在上面的配置中咱们是让触发器和任务嵌套的,其实还能够将他们分离,形如:
<!-- 定义JobDetail的Bean --> <bean id="saveProjectJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <!-- 定义Job的Bean --> <property name="jobClass"> <value> com.gresoft.fileupload.service.ParseFileQuartz </value> </property> <!-- 定义Job的Bean中引用到的其余Bean --> <property name="jobDataAsMap"> <map> <entry key="readXmlService"> <ref bean="readXmlService" /> </entry> </map> </property> </bean> <!-- ----------------------------------------------------------- --> <!-- 定义触发器的Bean --> <bean id="saveCron" class="org.springframework.scheduling.quartz.CronTriggerBean"> <!-- 指定jobDetail --> <property name="jobDetail"> <!-- <ref bean="saveProjectJob"></ref>二者均可以用 --> <ref local="saveProjectJob" /> </property> <!-- 指定任务触发的时间 --> <property name="cronExpression"> <value>0/30 * * * * ?</value> </property> </bean>
4、让容器加载quartz.xml
在web.xml中添加:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml,/WEB-INF/quartz.xml</param-value> </context-param>
###其实quartz.xml文件的内容彻底能够写在applicationContext.xml中的,不过那样会显得杂乱。
5、配置quartz的运行环境:quartz.properties文件(放在类路径下)
文件名必须叫此名字,其实此文件咱们也能够不配置的。
# 配置主调度器属性 org.quartz.scheduler.instanceName = QuartzScheduler org.quartz.scheduler.instanceId = AUTO # 配置线程池 # Quartz线程池的实现类 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool # 线程池的线程数量 org.quartz.threadPool.threadCount = 1 # 线程池里线程的优先级 org.quartz.threadPool.threadPriority = 10 # 配置做业存储 org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
若是咱们不配置此文件的话,默认使用quartz-2.1.6.jar中的quartz.properties文件(在该压缩文件的org/quartz路径下),若是须要改变其运行属性,咱们能够本身建立一个quartz.properties文件,并将该文件放在系统加载的类路径下,ClassLoader就会自动加载并启用其中的各类属性。
3、注意事项
在Spring配置和Quartz集成内容时,有两点须要注意
1、在<Beans>中不可以设置default-lazy-init="true",不然定时任务不触发,若是不明确指明default-lazy-init的值,默认是false。
2、在<Beans>中不可以设置default-autowire="byName"的属性,不然后台会报org.springframework.beans.factory.BeanCreationException错误,这样就不能经过Bean名称自动注入,必须经过明确引用注入