简单封装quartz实现任务调度的配置和管理

在实际的工作和开发过程中,经常遇到有需要定时任务的场景,比如定时发送邮件,定时上传文件,定时下载文件等。当然定时任务的处理也有很多种方式.本文主要写的是对quartz的简单封装,实现方便的调用。

主要思路:

定时任务的类和定时表达式配置在自定义的配置文件中,系统启动时,读取配置文件,加载需要执行的类,并启动quartz服务。

项目结构如下:

主要包括如下类和配置文件:

1. 任务调度接口

package com.yanek.easytask.core;

/**
 * 任务调度接口
 * @author yanek
 *
 */
public interface Task {

	/**
	 * 所有都要实现该执行方法,任务被调度时会调用
	 */
	void execute();

	/**
	 * 打断执行方法
	 */
	void interrupt();

}

2. 任务配置实体类

package com.yanek.easytask.core;

/**
 * 任务配置实体类
 * @author yanek
 *
 */
public class TaskConfig {

	private String name; //任务名称
	private boolean activity = true; //是否被激活
	private String className; //任务执行的类全名
	private String scanPeriod; //任务执行的定时表达式配置

	public String getScanPeriod() {
		return scanPeriod;
	}
	public void setScanPeriod(String scanPeriod) {
		this.scanPeriod = scanPeriod;
	}

	public String getTaskClass() {
		return TaskClass;
	}
	public void setTaskClass(String taskClass) {
		TaskClass = taskClass;
	}
	private String TaskClass;

	public boolean isActivity()
	{
		return activity;
	}

	public void setActivity(boolean activity)
	{
		this.activity = activity;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}

}

3. 任务配置xml解析类

package com.yanek.easytask.core;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * 任务配置xml解析类
 * @author yanek
 *
 */
public class XmlReader {

	//配置文件路径
	public final static String configFileName = "/conf/taskconfig.xml";

	public static void main(String[] args) {

		XmlReader.getTasks();
	}

	public static List getTasks() {

		List<TaskConfig> tasks = new ArrayList<TaskConfig>();

		System.out.println("load task config start...");

		File file = new File(Constants.APPLICATION_ROOT_DIR + configFileName);

		if (file.exists() && !file.isDirectory()) {

			try {
				SAXBuilder sx = new SAXBuilder();
				Document doc = sx.build(file);
				Element rootelement = doc.getRootElement();

					List<Element> childs = rootelement.getChildren();
					for (int i = 0; i < childs.size(); i++) {
						TaskConfig taskConfig = new TaskConfig();

						System.out.println("name:"+childs.get(i).getChildText("name"));
						System.out.println("activity:"+childs.get(i).getChildText("activity"));
						System.out.println("scanPeriod:"+childs.get(i).getChildText("scanPeriod"));
						System.out.println("className:"+childs.get(i).getChildText("className"));

						taskConfig.setName(childs.get(i).getChildText("name"));

						if (childs.get(i).getChildText("activity").equals("true"))
						{
							taskConfig.setActivity(true);
						}
						else
						{
							taskConfig.setActivity(false);
						}
						taskConfig.setScanPeriod(childs.get(i).getChildText("scanPeriod"));
						taskConfig.setTaskClass(childs.get(i).getChildText("className"));
						tasks.add(taskConfig);
				}
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (JDOMException e) {

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

		} else {
			System.out.println("task config file no exist!");

		}
		System.out.println("load task config end !");
		return tasks;

	}

}

4.任务工厂类

package com.yanek.easytask.core;

/**
 * 任务工厂类
 * @author yanek
 *
 */
public class TaskFactory {

	 /**
	  * 根据任务配置对象,创建任务类的对象实例,采用反射。
	  * @param config
	  * @return
	  */
	 public static Task createTask(TaskConfig config) {
		String classname = config.getTaskClass();
		Task task = null;
		try {
			task = (Task) Class.forName(classname).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return task;
	}

}

5. 任务适配器:

package com.yanek.easytask.core;

import org.quartz.InterruptableJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;
import org.quartz.UnableToInterruptJobException;

public class TaskAdapter implements StatefulJob, InterruptableJob {
	public TaskAdapter() {
	}

	private Task task = null;

	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		Object taskObj = context.getJobDetail().getJobDataMap().get(
				Constants.JOB_NAME);
		System.out.println("job类型:" + taskObj);
		if (taskObj instanceof Task) {
			task = (Task) taskObj;
			task.execute();
		} else {
			System.out.println("未知的job类型:" + taskObj.getClass());
		}
	}

	public void interrupt() throws UnableToInterruptJobException {
		task.interrupt();
	}
}

6. 系统常量类


package com.yanek.easytask.core;

/**
 * 系统常量类
 */
public class Constants
{
	/**
	 * 应用程序根目录
	 */
	public static String APPLICATION_ROOT_DIR = null;

	//任务实例名称
	public static final String JOB_NAME = "TASK_JOB_INSTANTS";
}

7. 系统启动类

package com.yanek.easytask.core;

import java.text.ParseException;
import java.util.List;

import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

/**
 * 调度任务服务程序启动入口
 *
 * 启动时需要设置-Dappdir参数,应当设置为-Dappdir=..
 * -Dconfig=配置文件文件绝对路径 可选的属性
 *
 * 任务调度使用Quartz实现
 *
 */
public class Startup
{

	/**
	 * @param args
	 */
	public static void startup() {

	}

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

			String appdir = System.getProperty("user.dir");

			System.out.println(appdir);

			//设置系统变量
			Constants.APPLICATION_ROOT_DIR = appdir;

			//System.setProperty("appdir","E:\\work\\task");

			//初始化调度服务器
			initSchedulerServer();

			List<TaskConfig> tasks=XmlReader.getTasks();

			if(tasks == null || tasks.size() <=0)
				throw new Exception("没有配置任务实例!");

			for(int i=0;i<tasks.size();i++)
			{
				TaskConfig tc=tasks.get(i);
				try
				{
					if(tc.isActivity())
					{
						scheduleJob(tc);
						System.out.println("任务实例["+tc.getName()+"]已加入调度.");
					}
					else
					{
						System.out.println(tc.getName()+" 任务实例Activity=false 不进行处理");
					}
				}
				catch(Exception cve)
				{
					//配置错误忽略这个任务
					System.out.println(cve);
				}
			}
			/*启动调度服务器*/
			startScheduleServer();
		}
		catch(Exception ex)
		{

			System.out.println("启动出现异常,3秒钟后自动关闭");
			Thread.sleep(1000*3);
			if(server!=null)
				server.shutdown();

		}

	}

	//----------------------任务调度处理----------------------------
	//任务调度服务
	private static Scheduler server = null;

	//任务id
	private static int jobID = 0;

	private static void initSchedulerServer()
		throws SchedulerException
	{
		if(server == null)
		{
			SchedulerFactory sf = new StdSchedulerFactory();
			server = sf.getScheduler();
		}
	}

	/**
	 * 调度一个任务
	 */
	private static void scheduleJob(TaskConfig conf)
		throws SchedulerException, ParseException
	{
		jobID++;

		Task deliveryJob = TaskFactory.createTask(conf);

		//将具体的任务实例存储到jobdetail中,这样每次触发jobadapter时,都会调用我们声明的deliveryJob这个实例了。
		String jobName = conf.getName()+"_job"+jobID;
		JobDetail jobAdapter = new JobDetail(jobName,
				"Group", TaskAdapter.class);
		JobDataMap data = new JobDataMap();
		data.put(Constants.JOB_NAME, deliveryJob);
		jobAdapter.setJobDataMap(data);

		//注意下面需要5个参数
		CronTrigger trigger = new CronTrigger("trigger_"+jobID,"Group",
				jobName, "Group",conf.getScanPeriod());
		server.addJob(jobAdapter, true);
		server.scheduleJob(trigger);	

	}

	/**
	 * 启动调度服务
	 * @throws SchedulerException
	 */
	private static void startScheduleServer() throws SchedulerException
	{
		if(server != null)
			server.start();
	}
}

配置文件:

taskconfig.xml


<?xml version="1.0" encoding="UTF-8"?>
<taskconfig>
    	<task>
	    	<name>test1</name>
			<activity>true</activity>
			<scanPeriod>0/5 * * * * ?</scanPeriod>
	    	<className>com.yanek.easytask.demo.TaskA</className>
    	</task>

    	 <task>
	    	<name>test任务2</name>
			<activity>true</activity>
			<scanPeriod>0/5 * * * * ?</scanPeriod>
	    	<className>com.yanek.easytask.demo.TaskDemo</className>
    	</task>

</taskconfig>

几点说明:

1. 上述代码可以封装打包为jar包。然后在其他项目中使用即可。

2. 使用该jar包事先任务开发时,只需要编写一个Task接口的实现类,配置在配置文件中即可。

实例调用如下:

package com.yanek.easytask.demo;

import com.yanek.easytask.core.Task;
import com.yanek.easytask.core.TaskConfig;

public class TaskDemo implements Task {

	//唯一构造函数
	public TaskDemo()
	{

	}

	@Override
	public void execute() {
		System.out.println(" TaskDemo execute");
	}

	@Override
	public void interrupt() {
		System.out.println("TaskDemo interrupt");
	}

}

在配置文件中增加如下配置:

    	 <task>
	    	<name>test任务2</name>
			<activity>true</activity>
			<scanPeriod>0/5 * * * * ?</scanPeriod>
	    	<className>com.yanek.easytask.demo.TaskDemo</className>
    	</task>

启动Startup类即可。运行结果如下:

时间: 2024-08-31 11:48:07

简单封装quartz实现任务调度的配置和管理的相关文章

利器OkHttp的使用以及简单封装

前言 Android开发中网络编程是必不可少的,不接入互联网的APP就没有盈利可言.废话不多说了,下面请先看Android中网络请求的进化图: HttpURLConnection,Apache HTTP Client,Volley到现在的OKHttp,可谓天外有天,人外有人.为什么OKHttp会这么火呢,相信下面的介绍会告诉你答案. OKHttp的简介 首先,给出OKHttp的项目地址:https://github.com/square/okhttp Android为我们提供了两种HTTP交互的

项目ITP(五) spring4.0 整合 Quartz 实现任务调度

正文  spring4.0 整合 Quartz 实现任务调度.这是期末项目的最后一篇,剩下到暑假吧.    Quartz 介绍   Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java application - from the smallest stand-alone application

node爬取微博的数据的简单封装库nodeweibo使用指南_node.js

一.前言 就在去年12月份,有个想法是使用node爬取微博的数据,于是简单的封装了一个nodeweibo这个库.时隔一年,没有怎么维护,中途也就将函数形式改成了配置文件.以前做的一些其他的项目也下线了,为了是更加专注前端 & node.js.偶尔看到下载量一天超过60多,持续不断的有人在用这个库,但是看下载量很少也就没有更新.但是昨天,有人pull request这个分支了,提出一些中肯的建议和有用的代码.于是就认真回顾了下nodeweibo,发布了v2.0.3这个版本. 二.什么是nodewe

WebService 的简单封装接口调用方法

  这篇文章主要介绍了WebService 的简单封装接口调用方法,主要是通过简单的sql语句来查询数据库,从而返回dataset,十分简单实用,有需要的小伙伴可以参考下. 此方法完成了简单WebService 的简单调用封装,实现了简单Webservice简单调用的统一操作,避免了每增加一个操作都必须增加一个接口方法 的囧状! ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 3

用原生JS对AJAX做简单封装的实例代码_javascript技巧

首先,我们需要xhr对象.这对我们来说不难,封装成一个函数. var createAjax = function() { var xhr = null; try { //IE系列浏览器 xhr = new ActiveXObject("microsoft.xmlhttp"); } catch (e1) { try { //非IE浏览器 xhr = new XMLHttpRequest(); } catch (e2) { window.alert("您的浏览器不支持ajax,请

crob表达式-Quartz cron任务调度时间表达式怎么写

问题描述 Quartz cron任务调度时间表达式怎么写 每天上午10点18 和下午15点 23分,这个cron表达式怎么写,请会的帮忙看下. 解决方案 Spring 任务调度Quartz的cron表达式---------------------- 解决方案二: 没这么写过,你可以写两个:* 18 10 1/1 * * * 23 15 1/1 * * 或者让它执行4次 * 18,23 10,15 1/1 * *

Redis客户端简单封装

Redis客户端简单封装并集成spring. spring-data-redis对redis有过度封装的嫌疑,而且也没有提供sharding模式,本文遂简单封装jedis. Xml代码 收藏代码 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http

Lucene5学习之LuceneUtils工具类简单封装

     周六花了整整一下午,将Lucene5中有关索引的常见操作进行了简单封装,废话不多说,上代码:   Java代码   package com.yida.framework.lucene5.util;      import java.io.IOException;   import java.util.concurrent.ExecutorService;   import java.util.concurrent.locks.Lock;   import java.util.concu

时间段配置-quartz定时器框架时间配置

问题描述 quartz定时器框架时间配置 我想配置一个任务,触发时间是2014-02-25的每天13:00:00到2014-08-12的每天14:30:00,但中间的法定节日,如五一等(假设五一放假三天)节日不触发,这个如何配置