Project Requirements: Timing Tasks
How to achieve it?
spring has its own timing task, jdk has its own Timer, quartz implementation.
Advantages and disadvantages, spring, annotation-based implementation, simple configuration, but rich tasks in the latter stage, after the modification of configuration is more difficult, and not easy to control.
jdk comes with it, which is easy to implement and not easy to control.
quartz, powerful and configurable.
So in order to expand the project in the future, quartz is adopted decisively and quartz jar package is introduced.
quartz-2.2.3.jar quartz-jobs-2.2.3.jar
spring 4.0
quartz implements task configuration
Write execution code:
@Component
public class TestJob {
public void exe(){
System.out.println("hello test");
}
}
<!--Definition jobdetail-->
<bean id="testTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testJob "/>
<property name="targetMethod" value="exe"/>
</bean>
<!--Define triggers-->
<bean id="handletrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="testTask"/>
<property name="cronExpression" value="${handle_cron}"/>
</bean>
//Above operations, each time
<!--Define scheduler-->
<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>
Every time you add a new scheduling task, you need to add these configurations in xml. It's a real hassle.
Reduce configuration
1. analysis
In order to reduce the configuration of xml, we can observe the configuration sequence of launching a task in spring project, which is not difficult to find.
Org. spring framework. scheduling. quartz. MethodInvoking JobDetailFactory Bean and org. spring framework. scheduling. quartz. CronTriggerFactory Bean
It is a java object that instantiates a task object. It is spring's encapsulation of quartz.
Next is org. spring framework. scheduling. quartz. SchedulerFactoryBean.
Scheduler, to achieve the scheduling of the next task object
So to reduce configuration, we need to start with Scheduler FactoryBean and rewrite Scheduler FactoryBean so that it can automatically register task objects, which uses custom annotations.
2. Code Implementation
Custom Annotations
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 {
//Timing task grouping
String group() default "default";
//Task Execution Method
String executeMethod() default "execute";
//Execute task expression, support ${} expression, default load configuration cron expression from config/job.properties
String cron() default "";
}
Rewritten task scheduler Scheduler FactoryBean for automatic assembly tasks
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
* Dynamic Configuration Task Addition
*Later, tasks can be configurated from the database, providing interfaces to stop, rearrange, suspend tasks and so on.
*/
@Component
public class EcrDynamicScheduler extends SchedulerFactoryBean implements ApplicationContextAware {
private static ApplicationContext applicationContext;
//Default profile address
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(){
//Get custom annotation bean objects
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>();
//Read the default cron expression configuration file
Properties properties=PropertiesUtils.getProperties(DEFAULT_CONFIG_PATH);
for(Object targetObject:values){
//Create jobbean
jobBean=new MethodInvokingJobDetailFactoryBean();
//Get annotations on bean s
Job jobAnno = targetObject.getClass().getAnnotation(Job.class);
//Getting annotation content
String group = jobAnno.group();
String executeMethod = jobAnno.executeMethod();
String beanName=targetObject.getClass().getSimpleName();
String cron=jobAnno.cron();
if(cron.contains("${")){//If cron is an el expression, it is retrieved from the configuration file
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();
//Create triggers
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()]);
//Deliver to the actuator for execution
setAutoStartup(true);
setTriggers(triggers);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
This rewritten Scheduler FactoryBean is relatively simple, but also because the project requirements are relatively simple, so there is not much to write, in fact, there are many extensible places to save task objects jobkey and jobdetail.
Implementing pause, deletion, rearrangement of task objects, etc.