Quartz学习笔记(二) 转自 learnworld 之 spring任务调度方法之Quartz (推荐)

一、Quartz简介 

    Quartz是一个开放源码项目,专注于任务调度器,提供了极为广泛的特性如持久化任务,集群和分布式任务等。Spring对Quartz的集成与其对JDK Timer的集成在任务、触发器和调度计划的声明式配置方面等都非常相似。 

    Quartz的核心由两个接口和两个类组成:Job和Scheduler接口,JobDetail和Trigger类。不同于JDK Timer,任务不是从实现一个Job接口的类实例开始运行,实际上Quartz在需要的时候才创建job类实例。可以使用JobDetail类来包装任务状态,并传递一个信息给Job,或在一个Job的多次执行过程之间保存信息。 

二、Quartz任务调度 

1. 简单任务调度 

    在Quartz中创建一个任务并执行,只需要实现Job接口类,在其execute()方法中处理你的业务逻辑。下面举例说明。 

HelloWorldJob.java 

package com.learnworld.quartz;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloWorldJob implements Job {

	public void execute(JobExecutionContext context) throws JobExecutionException {
                  //实现你的业务逻辑
		System.out.println("Hello!");
		
	}
}

HelloScheduling.java 

package com.learnworld.quartz;

import java.util.Date;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

public class HelloScheduling {
	public static void main(String[] args) throws Exception {

		Scheduler scheduler = new StdSchedulerFactory().getScheduler();
		scheduler.start();

		JobDetail jobDetail = new JobDetail("helloWorldJob",
				Scheduler.DEFAULT_GROUP, HelloWorldJob.class);

		Trigger trigger = new SimpleTrigger("simpleTrigger",
				Scheduler.DEFAULT_GROUP, new Date(), null,
				SimpleTrigger.REPEAT_INDEFINITELY, 1000);
		
		scheduler.scheduleJob(jobDetail, trigger);

	}
}

需要说明几点: 

    1)开始使用StdSchedulerFactory来获取Scheduler的实例。每一个scheduler可以被启动(start)、中止(stop)和暂停(pause)。如果一个scheduler没有被启动或已经被暂停,则没有触发器会被启用,所以首先使用start()方法启动scheduler。 

    2)创建JobDetail实例。它的构造参数有三个,第一个是任务名,任务名可以被用作参数来应用需要暂停的任务;第二个是组名,组名可以用来引用一组被集合在一起的任务,这里采用缺省组名,每一个任务名在组内必须是唯一的;第三个参数是实现了特定任务的类。 

    3)创建Trigger实例。我们使用SimpleTrigger类,它提供了类似JDK Timer风格的触发器行为。它的构造参数有六个,第一个和第二个为触发器名和组名,和上面类似;第三个为任务开始时间;第四个为结束时间,如果设置为空,表示不存在结束时间;第五个为重复次数,允许你指的触发器被触发的最大次数,使用REPEAT_INDEFINITELY允许触发器可以被触发无限次;第六个是触发器运行的时间间隔,是毫秒数。 

    4)最后通过scheduler.scheduleJob()方法调度任务。 

2. 使用JobDetail传递数据 

    每个JobDetail实例都有关联的JobDataMap实例,它实现了Map接口并允许通过键值来传递任务相关的数据。任务也可以修改JobDataMap中的数据,在同一任务的多次执行之间传递数据。下面举例说明。 

MessageJob.java 

package com.learnworld.quartz;

import java.util.Map;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MessageJob implements Job {

	public void execute(JobExecutionContext context) throws JobExecutionException {
		
		Map properties = context.getJobDetail().getJobDataMap();
		
		System.out.println("Previous Fire Time: " + context.getPreviousFireTime());
		System.out.println("Current Fire Time: " + context.getFireTime());
		System.out.println("Next Fire Time: " + context.getNextFireTime());
		System.out.println(properties.get("message"));
		
	}
}

MessageScheduling.java 

package com.learnworld.quartz;

import java.util.Date;
import java.util.Map;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

public class MessageScheduling {
	public static void main(String[] args) throws Exception {

		Scheduler scheduler = new StdSchedulerFactory().getScheduler();
		scheduler.start();

		JobDetail jobDetail = new JobDetail("messageJob",
				Scheduler.DEFAULT_GROUP, MessageJob.class);
		
		Map map = jobDetail.getJobDataMap();
		map.put("message", "This is a message from Quartz");

		Trigger trigger = new SimpleTrigger("simpleTrigger",
				Scheduler.DEFAULT_GROUP, new Date(), new Date("Sat, 12 Aug 2011 13:30:00 GMT+0430"),
				SimpleTrigger.REPEAT_INDEFINITELY, 5000);
		
		scheduler.scheduleJob(jobDetail, trigger);

	}
}

3. 使用CronTrigger 

   上面提到了SimpleTrigger类,它提供了类似JDK Timer风格的触发器功能。Quartz的出色在于它使用CronTrigger提供了对复杂触发器的支持。 

    一个CronTrigger表达式,包含六个必须组件和一个可选组件。关于cron表达式,可以参考这篇文档:http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html 

   下面举例说明CronTrigger的使用。 

CronWithCalendarScheduling.java 

package com.learnworld.quartz;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.HolidayCalendar;

public class CronWithCalendarScheduling {
	public static void main(String[] args) throws Exception {

		Calendar cal = Calendar.getInstance();
		cal.set(2010, Calendar.OCTOBER, 31);
		
		HolidayCalendar calendar  = new HolidayCalendar();
		calendar.addExcludedDate(cal.getTime());
		
		Scheduler scheduler = new StdSchedulerFactory().getScheduler();
		scheduler.start();
		
		scheduler.addCalendar("calendar", calendar, true, false);
		
		JobDetail jobDetail = new JobDetail("messageJob",
				Scheduler.DEFAULT_GROUP, MessageJob.class);
		
		Map map = jobDetail.getJobDataMap();
		map.put("message", "This is a message from Quartz");

		String cronExpression = "3/5 * 17,18,19,20 * * ?";
		
		Trigger trigger = new CronTrigger("cronTrigger",
				Scheduler.DEFAULT_GROUP, cronExpression);
		
		scheduler.scheduleJob(jobDetail, trigger);
	}
}

需要说明几点: 

    1)创建了HolidayCalendar实例,使用addExcluderData()方法排除了2010年10月31日。再使用addCalendar()方法,将这个Calendar加入到Scheduler中。 

    2)这个cron表达式的含义是,每天17:00-20:59之间每一分钟的第三秒开始运行,每五秒执行一次。 

三. Spring对Quartz调度的支持 

    Spring对Quartz集成与其对JDK Timer调度集成类似,你可以在配置文件中配置任务调度。仅需要在程序里加载ApplicationContext,Spring会自动启动调度器。 

quartz.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="job"
		class="org.springframework.scheduling.quartz.JobDetailBean">
		<property name="jobClass">
			<value> com.learnworld.quartz.MessageJob </value>
		</property>
		<property name="jobDataAsMap">
			<map>
				<entry key="message">
					<value>This is a message from Spring Quartz configuration!</value>
				</entry>
			</map>
		</property>
	</bean>
	<bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
		<property name="startDelay">
			<value>1000</value>
		</property>
		<property name="repeatInterval">
			<value>3000</value>
		</property>
		<property name="jobDetail">
			<ref local="job" />
		</property>
	</bean>

	<bean id="schdulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
				<ref local="trigger" />
			</list>
		</property>
	</bean>
</beans>

SimpleSpringQuartzIntegration.java 

package com.learnworld.quartz;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class SimpleSpringQuartzIntegration {

	public static void main(String[] args) {

		ApplicationContext ac = new FileSystemXmlApplicationContext("src/conf/quartz.xml");
	}

}

需要说明几点: 

    1)采用JobDetailBean类,它扩展了JobDetai类,采用可声明方式配置任务数据。缺省情况下,采用<bean>标签的id作为任务名,使用缺省组作为组名,通过jobDataAsMap作为配置任务数据。 

    2)建立触发器。可以选择SimpleTriggerBean或CronTriggerBean类。SimpleTriggerBean缺省情况下把可重复执行次数设为无限。 

    3)创建schedulerFactory。缺省情况下,SchedulerFactoryBean创建一个StdSchedulerFactory的实例,后者创建Scheduler的实现。可以通过设置schedulerFactoryClass属性来覆盖这个行为,需要继承SchedulerFactory接口来实现你自己的版本。


===============另附一评论========================

建议大家看看bbossgroups中所带的quartz任务调度器,也比较好用哩 
任务管理配置文件 
一个简单的配置文件 
/bbossaop/resources/org/frameworkset/task/quarts-task.xml的内容如下:

<properties>
<property name="taskconfig" enable="true">
<list>
<property name="定时任务执行器" taskid="default"
class="org.frameworkset.task.DefaultScheduleService" used="true">
<!--
可执行的任务项
属性说明:
name:任务项名称
id:任务项标识
action:具体的任务执行处理程序,实现org.frameworkset.task.Execute接口
cron_time: cron格式的时间表达式,用来管理任务执行的生命周期,相关的规则请参照日期管理控件quartz的说明文档
used 是否使用
true 加载,缺省值
false 不加载  
子元素说明:
Map 和property:设置任务执行的参数,name标识参数名称,value指定参数的值
-->
<list>
<property name="workbroker" jobid="workbroker"
class="org.frameworkset.task.TestJob"
cronb_time="0 56 14 * * ?" used="true">
<map>
<property name="send_count" value="2" />
</map>
</property>
</list>
</property>
</list>
</property>
</properties>

说明: 
org.frameworkset.task.DefaultScheduleService是系统中默认提供的任务管理组件,用来加载系统中默认的静态的任务,可以配置多个,例如:
 

<property name="workbroker" jobid="workbroker"
action="org.frameworkset.task.TestJob"
cronb_time="0 56 14 * * ?" used="true">
<map>
<property name="send_count" value="2" />
</map>
</property>

属性说明: 
Taskid:用来区分任务组,可以作为任务组的唯一标识,系统中通过Taskid和jobid来区分唯一的一个作业任务,TaskService组件的很多方法中都有groupid和jobname两个参数,taskid就对应于groupid参数,jobid对应于 jobname参数。 
Name 任务的名称 
Jobid 任务的标识 
Action任务执行的操作 
cronb_time 任务执行的调度时间,具体需要参考cronb_time的语法。 
use:区分任务是否生效 
内嵌的节点 
<map> 
<property name="send_count" value="2" /> 
</map> 
用来指定任务执行时需要的参数。 
需要特别说明的是Action类必须实现org.frameworkset.task.Execute接口,例如:

public class TestJob implements Execute, Serializable {
public void execute(Map parameters) {
System.out.println("send_count = "+parameters.get("send_count"));
}

} 


在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值