工作中常常遇到需要定时执行任务的需求,记录一下
**1.引入相关需要的jar包**
**2.配置文件**
**3.编写任务业务逻辑**
第二步:配置文件
Spring创建jobDetailbean 有两种方式分别是
配置Spring的任务调度抽象层简化了任务调度,在Quartz的基础上提供了更好的调度对象。Spring使用Quartz框架来完成任务调度,创建Quartz的作业Bean(JobDetail),有以下两种方法:
1:利用JobDetailBean包装QuartzJobBean子类(即Job类)的实例。 2:利用MethodInvokingJobDetailFactoryBean工厂Bean包装普通的Java对象(即Job类)。
说明:
1:采用第一种方法 创建job类,一定要继承QuartzJobBean ,实现 executeInternal(JobExecutionContext jobexecutioncontext)方法,此方法就是被调度任务的执行体,然后将此Job类的实例直接配置到JobDetailBean中即可。这种方法和在普通的Quartz编程中是一样的。
2:采用第二种方法 创建Job类,无须继承父类,直接配置MethodInvokingJobDetailFactoryBean即可。但需要指定一下两个属性:
targetObject:指定包含任务执行体的Bean实例。
targetMethod:指定将指定Bean实例的该方法包装成任务的执行体。 concurrent:是否并发进行,false,表示不可以并发,其他进程延迟调用,一般用于定时调用多个程序时。
第一种实现
<bean name="autoCardAmortizeJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="default" autowire="default">
<property name="jobClass" value="cn.xx.job.AutoOrderAmortizeJob" />
<property name="jobDataAsMap">
<map><entry key="size" value="10" /></map>
</property>
<property name="applicationContextJobDataKey" value="applicationContext" />
</bean>
**● jobClass:类型为Class,实现Job接口的任务类;
● beanName:默认为Bean的id名,通过该属性显式指定Bean名称,对应任务的名称;
● jobDataAsMap:类型为Map,为任务所对应的JobDataMap提供值。之所以需要提供这个属性,是因为除非你手工注册一 个编辑器,你不能直接配置JobDataMap类型的值,所以Spring通过jobDataAsMap设置JobDataMap的值;
●applicationContextJobDataKey:你可以将Spring ApplicationContext的引用保存到JobDataMap中,以便在Job的代码中访问ApplicationContext。为了达到这个目的,你需要指定一个键,用以在jobDataAsMap中保存ApplicationContext,如果不设置此键,JobDetailBean就不将ApplicationContext放入到JobDataMap中;
●jobListenerNames:类型为String[],指定注册在Scheduler中的JobListeners名称,以便让这些监听器对本任务的事件进行监听**。
第二种实现
<bean name="autoCardAmortizeJob" class="cn.xx.job.AutoOrderAmortizeJob"/>
<bean id="autoCardAmortizeJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="autoCardAmortizeJob" />
<property name="targetMethod" value="studyCardAmortize" />
<property name="concurrent" value="false" />
</bean>
**说明:1. targetObject:指定包含任务执行体的Bean实例。
2. targetMethod:指定将指定Bean实例的该方法包装成任务的执行体。
3.concurrent:是否并发进行,false,表示不可以并发,其他进程延迟调用,一般用于定时调用多个程序时。**
触发器配置
<!--学习卡自动摊销任务触发器配置 -->
<bean id="autoCardAmortizeCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="autoCardAmortizeJobDetail" />
<!-- 每5秒钟执行一次 -->
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
调度配置
<!-- 总配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 添加触发器 -->
<property name="triggers">
<list>
<ref bean="autoCardAmortizeCronTrigger" />
</list>
</property>
</bean>
最后就可以在自己的job中写自己的业务逻辑
/***
* 订单自动摊销任务
*
*
*/
public class AutoOrderAmortizeJob{
private Logger log;
@Autowired
private TeacherAchievementNewService teacherAchievementNewService;
public void studyCardAmortize() throws Exception {
try {
System.out.println("当前时间是"+DateUtil.format(new Date(), DateUtil.BOTH));
List<TeacherInfo> teacherInfoList = teacherAchievementNewService.getTeacherInfo();
for (TeacherInfo teacherInfo : teacherInfoList) {
System.out.println(teacherInfo.getTeacherName());
}
} catch (Exception e) {
log.error("自动学习卡摊销任务执行异常!");
e.printStackTrace();
}
}
完整配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 总配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 添加触发器 -->
<property name="triggers">
<list>
<ref bean="autoCardAmortizeCronTrigger" />
</list>
</property>
</bean>
<!--学习卡自动摊销任务配置 -->
<bean name="autoCardAmortizeJob" class="cn.xxx.scheduler.job.AutoOrderAmortizeJob"/>
<bean id="autoCardAmortizeJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="autoCardAmortizeJob" />
<property name="targetMethod" value="studyCardAmortize" />
<property name="concurrent" value="false" />
</bean>
<!--学习卡自动摊销任务触发器配置 -->
<bean id="autoCardAmortizeCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="autoCardAmortizeJobDetail" />
<!-- 每5秒钟执行一次 -->
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
</beans>
还有种更为简单的实现方式那就是 —–注解
如下:
package com.main.scheduler.job;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TimeSayHelloJobAnnoation {
// 每5秒执行一次
@Scheduled(cron = "0 0/2 * * * ? ")
public void myTest() {
System.out.println("注解方式定时器进入测试"+new Date().toString());
}
}
使用注解方式只需记得在spring配置文件中启用注解即可
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
遇到的问题:
Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class
原因是Spring 3.0版本中内置的Quartz版本是<2.0的,在使用最新的Quartz包(>2.0)之后,接口不兼容。
解决办法有两种:
1.降低Quartz版本,降到1.X去。
2.升级Spring版本到3.1+,根据Spring的建议,将原来的**TriggerBean替换成**TriggerFactoryBean,例如CronTriggerBean 就可以替换成 CronTriggerFactoryBean。替换之后问题解决。
2014-04-22补充解决办法:
解决办法有三种:
1.降低Quartz版本,降到1.X去。
2.升级Spring版本到3.1+,根据Spring的建议,将原来的**TriggerBean替换成**TriggerFactoryBean,例如CronTriggerBean 就可以替换成 CronTriggerFactoryBean。替换之后问题解决。
3.如果不在xml配置文件中引用 Spring 3.0 是支持 Quartz2.2.1(目前最新版本),直接在程序中调用即可。(我们的文件中转站系统用的是 Spring 3.0+quartz 2.2.1集群模式)
原文地址:http://www.cnblogs.com/interdrp/p/3587221.html
http://blog.csdn.net/zeb_perfect/article/details/50826079