学习 quarz 定时任务调度

转自:https://blog.csdn.net/JY_He/article/details/52198952

quarz中定时任务包括三个部分:

Schedule(任务调度器),Job(作业任务)和Trigger(触发器)

Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。

JobDetail:Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。

Trigger:是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。
当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案。

Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。

一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。

使用案列:

public class HelloWord implements Job{  
  
    //实现自己的定时方法  
    public void execute(JobExecutionContext arg0) throws JobExecutionException {  
        System.out.println("hello world " + new Date());  
    }  
      
}  


public class SimpleExample {	
	public static void main(String[] args) throws SchedulerException{
		
		SimpleExample example=new SimpleExample();
		example.run();
	}
 
	public  void run() throws SchedulerException {
		
		//获取scheduler实例
		Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
		scheduler.start();
		
		//当前时间
		Date runTime=new Date();
		
		//定义一个 job 对象并绑定我们写的  HelloWord 类   
        // 真正执行的任务并不是Job接口的实例,而是用反射的方式实例化的一个JobDetail实例 
		JobDetail job=JobBuilder.newJob(HelloWord.class).withIdentity("job1","group1").build();
		
		// 定义一个触发器,startAt方法定义了任务应当开始的时间 .即下一个整数分钟执行
		Trigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger1","group1").startAt(runTime).build();
		
		   	/*  .withIdentity("myTrigger","group1")
		                   .startNow()
		                   .withSchedule(
		                           SimpleScheduleBuilder.simpleSchedule()
		                           .withIntervalInSeconds(2)
		                           .repeatForever())
		                   .build();
		                   */

		// 将job和Trigger放入scheduler
		scheduler.scheduleJob(job, trigger);
		
		//启动
		scheduler.start();
		
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
			scheduler.shutdown();
		}	
	}

quarz整合Spring框架案例

第一种方式
需要继承JobBean,并重写executeInternal(JobExecutionContext context),然后配置spring-quratz.xml文件,里配置三部分:1.任务调用类;2.任务调用方式;3.任务调用工厂。

public class QuartzTask extends QuartzJobBean{
	
	private int timeout;
	private static int i = 0;
	
	//调度工厂实例化后,经过timeout时间开始执行调度
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}
	
	@Override
	protected void executeInternal(JobExecutionContext context)
			throws JobExecutionException {
		System.out.println("task running..."+ ++i + "进行中...");
	}
	}

XML 配置

<!-- 配置任务类 -->
<bean id="quartzTask" class="org.springframework.scheduling.quartz.JobDetailBean">
	<property name="name" value="exampleJob"></property>
	<property name="quartzClass" value="spring.demo.pojo.QuartzTask"></property>
	<property name="jobDataAsMap">
		<map>
			<entry key="timeout" value="0" />
		</map>
	</property>
</bean>

<!-- 配置触发器 -->
<bean id="cronTriggerBean"
		class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail">
			<ref bean="quartzTask" />
		</property>
		<!-- cron表达式 -->
		<property name="cronExpression">
			<value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
		</property>
	</bean>
	


   <!-- 调度工厂 -->
	<bean id="SpringJobSchedulerFactoryBean"
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
				<ref bean="cronTriggerBean" />
			</list>
		</property>
	</bean>

第二种方式:
不需要继承基类,这样仍然是pojo,而是在spring-quratz.xml配置文件中,配置包装类,其他两个配置与上述一样。

public class QuartzJob {
	public void work(){
		System.out.println("work running...");
	}
}

XML配置:

<!-- 配置任务类 -->
<bean id="quartzJob" class="spring.demo.pojo.QuartzJob"></bean>
	<bean id="jobTask"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<!-- 需要包装的类,即调度类 -->
		<property name="targetObject">
			<ref bean="quartzJob" />
		</property>
		<!-- 调用类中的方法 -->
		<property name="targetMethod">
			<!-- 具体的方法 -->
			<value>work</value>
		</property>
	</bean>
	
<!-- 配置触发器 -->
<bean id="cronTriggerBean"
		class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail">
			<ref bean="jobtask" />
		</property>
		<!-- cron表达式 -->
		<property name="cronExpression">
			<value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
		</property>
	</bean>



   <!-- 调度工厂 -->
   <bean id="SpringJobSchedulerFactoryBean"
    		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<property name="triggers">
    			<list>
    				<ref bean="cronTriggerBean" />
    			</list>
    		</property>
   </bean>

.第三种方式
通过@Scheduled注解的方式实现,需要修改applicationContext.xml三个部分内容:

1.xmlns添加:
xmlns:task=“http://www.springframework.org/schema/task

2.xsi:schemaLocation添加
http://www.springframework.org/schema/task/spring-task-3.1.xsd
3.applicationContext.xml中添加
task:annotation-driven/
注解方法开发

@Service
public class QuartzService {
 
	@Scheduled(cron = "0/2 * * * * *")
	public void process() {
		System.out.println("job run...");
	}
 
	public static void main(String[] args) throws InterruptedException {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		while (true) {
			System.out.println("main running...");
			Thread.sleep(10000);
		}
	}
}

JobExecutionContext与JobDataMap

JobExecutionContext可以理解为Job实例的上下文,可以通过它获取job运行时的环境以及属性信息,一个Job对应一个JobExecutionContext的实例。当Scheduler调用一个Job时就会将JobExecutionContext传递给job的execute方法。

JobDataMap实现了Map接口,用法同Map类似,它可以装在任何可序列化的数据对象,执行Job时用来传递数据,JobDataMap存在JobExecutionContext中,要通过JobExecutionContext来获取。

Test代码:

public class TestHelloJob2 
{
    public static void main( String[] args ) throws SchedulerException
    {
        /*创建JobDetail实例,并与HelloJob绑定;Job的名字是myjob,隶属于job_group组*/
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                .withIdentity("myjob", "job_group")
                .usingJobData("data1", "Data1 Information")
                .usingJobData("data2", 10000D)
                .build();

        /*创建Trriger实例,指定Job每隔3秒钟执行一次*/
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("mytrigger", "trigger_group")
                .usingJobData("data2", 20000D)
                .usingJobData("data3", "Data3 Information")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever())
                .build();

        /*创建SchedulerFactory实例,把jobDetail与trigger绑定在一起*/
        SchedulerFactory factory = new StdSchedulerFactory();
        Scheduler scheduler = factory.getScheduler();
        scheduler.start();
        scheduler.scheduleJob(jobDetail, trigger);

    }
}

创建作业,实现Job接口,在job中获取传输的数据

public class HelloJob implements Job {

    public void execute(JobExecutionContext context) throws JobExecutionException {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sf.format(new Date()));

        /*获取job的属性*/
        JobKey key = context.getJobDetail().getKey();
        System.out.println("Job name : " + key.getName() + "; Job group : " + key.getGroup());

        /*获取Trigger的属性*/
        TriggerKey tKey = context.getTrigger().getKey();
        System.out.println("Trigger name : " + tKey.getName() + ": Trigger group : " + tKey.getGroup());

        /*获取JobDetail中的DataMap中属性*/
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        String jobData1 = dataMap.getString("data1");
        Double jobData2 = dataMap.getDouble("data2");
        System.out.println("jobData1 : " + jobData1 + " ; jobData2 : " + jobData2);

        /*获取Trigger中的DataMap属性*/
        JobDataMap tDataMap = context.getTrigger().getJobDataMap();
        Double triggerData2 = tDataMap.getDouble("data2");
        String triggerData3 = tDataMap.getString("data3");
        System.out.println("triggerData2 : " + triggerData2 + "; triggerData3 : " + triggerData3);

        System.out.println("This is hello job……");
        System.out.println("------------------------------------------");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43784980/article/details/90480256