您的位置:首页 > 编程语言 > Java开发

quartz定时任务之自定义注解实现动态配置任务

2017-08-23 14:36 381 查看

项目需求:定时任务

实现方式?

spring自带定时任务,jdk自带Timer,quartz实现。

优缺点,spring,基于注解实现,配置简单,但是后期任务丰富,之后,修改配置较为困难,且不容易控制

jdk自带,实现简单,不便于控制,

quartz,功能强大,可配置。

所以为了以后项目的扩展,果断采用quartz,引入quartz jar包,

quartz-2.2.3.jar quartz-jobs-2.2.3.jar

spring 4.0

quartz实现任务配置

编写执行代码:

@Component
public class TestJob {
public void exe(){
System.out.println("hello test");
}
}


<!--定义jobdetail-->
<bean id="testTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testJob "/>
<property name="targetMethod" value="exe"/>
</bean>
<!--定义触发器-->
<bean id="handletrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="testTask"/>
<property name="cronExpression" value="${handle_cron}"/>
</bean>
以上操作,每次
<!--定义调度器-->
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="testtrigger"/>
<ref bean="testtrigger1"/>
<ref bean="testtrigger2"/>
</list>
</property>
<property name="autoStartup" value="true"/>
</bean>


每次新增一个调度任务,都需要在xml里添加这些配置,真心麻烦

减少配置

1.分析

为了减少xml的配置,我们可以观察一下,spring项目中,启动一个任务的配置顺序,不难发现,

org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean和org.springframework.scheduling.quartz.CronTriggerFactoryBean

是实例化一个任务对象的java对象,都是spring对quartz的封装,

其次是org.springframework.scheduling.quartz.SchedulerFactoryBean

调度器,实现对上一步任务对象的调度

所以我们要减少配置,就要从SchedulerFactoryBean入手,重写SchedulerFactoryBean,使他能够自动注册任务对象,这其中用到了自定义注解

2.代码实现

自定义注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Job {
//定时任务分组
String group() default "default";
//执行任务方法
String executeMethod() default "execute";
//执行任务表达式,可支持${}表达式,默认从config/job.properties加载配置cron表达式
String cron() default "";

}


重写的任务调度器SchedulerFactoryBean,实现自动装配任务

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.quartz.JobKey;
import org.quartz.Trigger;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
/**
*
* @author ll
* 动态配置任务添加
*后期可以从数据库中配置任务,提供接口停止,重新安排,暂停任务等接口
*/
@Component
public class EcrDynamicScheduler extends SchedulerFactoryBean  implements ApplicationContextAware {
private static ApplicationContext applicationContext;
//默认配置文件地址
private static final String DEFAULT_CONFIG_PATH="config/job.properties";
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
init();
}
private void init(){
//获取自定义注解bean对象
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Job.class);
if(beansWithAnnotation!=null){
try {
Collection<Object> values = beansWithAnnotation.values();
MethodInvokingJobDetailFactoryBean jobBean=null;
CronTriggerFactoryBean triggerBean=null;
List<Trigger> triggerBeans=new ArrayList<Trigger>();
//读取默认cron表达式配置文件
Properties properties=PropertiesUtils.getProperties(DEFAULT_CONFIG_PATH);
for(Object targetObject:values){
//创建jobbean
jobBean=new MethodInvokingJobDetailFactoryBean();
//获取bean上的注解
Job jobAnno = targetObject.getClass().getAnnotation(Job.class);
//获取注解内容
String group = jobAnno.group();
String executeMethod = jobAnno.executeMethod();
String beanName=targetObject.getClass().getSimpleName();
String cron=jobAnno.cron();
if(cron.contains("${")){//如果cron是el表达式,则从配置文件中获取
cron=properties.getProperty(cron.substring(2, cron.indexOf("}")), "");
}
jobBean.setTargetObject(targetObject);
jobBean.setGroup(group);
jobBean.setTargetMethod(executeMethod);
jobBean.setBeanName(beanName+"_jobBean");
//jobkey:group.beanName.executeMethod
jobBean.setName(beanName+"."+executeMethod);
jobBean.afterPropertiesSet();
//创建触发器
triggerBean=new CronTriggerFactoryBean();
triggerBean.setJobDetail(jobBean.getObject());
triggerBean.setCronExpression(cron);
triggerBean.setBeanName(beanName+"_triggerBean");
triggerBean.setName(beanName+"."+executeMethod);
triggerBean.afterPropertiesSet();
triggerBeans.add(triggerBean.getObject());
}
Trigger[] triggers =  triggerBeans.toArray(new Trigger[triggerBeans.size()]);
//交给执行器执行
setAutoStartup(true);
setTriggers(triggers);

} catch (Exception e) {
e.printStackTrace();
}

}
}
}


这个重写的SchedulerFactoryBean比较简单,也是因为项目需求也比较简单,所以就没有写太多功能,其实还有很多可以扩充的地方,可以保存任务对象jobkey和jobdetail,

实现任务对象的暂停,删除,重新安排等操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring quartz