quartz-2.2.1定制工具类,方便nutz使用js配置quartz

前言:本文主要提供quartz简单配置的解决方案。

      附上quartzWithtool2.2.1.jar和本人增加的org.quartz.tool包里面的源码下载。

      quartzWithtool2.2.1.jar:csdn下载

      org.quartz.tool包:csdn下载

开发背景:在使用nutz框架的时候,需要用到quartz来开启定时任务的时候,不能像spring那样使用xml配置一系列的定时任务。需要自己编写代码去实现定时任务的添加,不利于代码维护。


使用方法:

1.添加quartzWithtool2.2.1.jar

2.nutz的ioc.js里面添加如下配置信息

quartz : {
		type : "org.quartz.tool.QuartzBean",
		fields : {
			list : [
					{
						type : "org.quartz.tool.QuartzBean",
						fields : {
							name : "clientdie",
							clazz : "com.chat.quartz.job.ClientDieJob",
							trigger : "0 */1 * * * ?"//每到整数分钟就执行ClientDieJob
						}
					},
					{
						type : "org.quartz.tool.QuartzBean",
						fields : {
							name : "faqtip",
							clazz : "com.chat.quartz.job.FaqTipJob",
							trigger : "0 0 */1 * * ?",//每到整数小时就执行ClientDieJob和FaqTipJob
							simpleDelay : "0s"//启动项目之后立即执行1次FaqTipJob
							,jobDatas:[{
								type : "org.quartz.tool.JobData",
								fields : {
									key : "mykey",
									value : "myvalue"
								}
							},{
								type : "org.quartz.tool.JobData",
								fields : {
									key : "mybool",
									value : "false"
								}
							}]
						}
					} ]
		}
	}
  3.在项目启动的时候调用
QuartzTool.loadSchedule(Mvcs.getIoc().get(QuartzBean.class, "quartz") );
  :也可以不使用js配置的方式注入 QuartzBean,可以自行在代码中动态生成 QuartzBean,然后调用loadSchedule。

关于QuartzBean的配置说明

//-------------------------单个定时任务对应两个触发器(一个simple一个cron规则)-------------------------------------
{
	type : "com.chat.quartz.QuartzBean",
	fields : {
		name : "clientdie",
		clazz : "com.chat.quartz.job.ClientDieJob",
		trigger : "0 */1 * * * ?",//每到整数分钟就执行ClientDieJob
		simpleDelay : "7s", //启动项目之后7秒开始每间隔1秒执行ClientDieJob,一共执行10次
		simpleRepeat : "10",
		simpleRepeatDelay : "1s"
	}
}

//-------------------------多个定时任务对应两个触发器(一个simple一个cron规则)-------------------------------------
{
	type : "com.chat.quartz.QuartzBean",
	fields : {
		name : "faqtip",
		clazz : "com.chat.quartz.job.ClientDieJob,com.chat.quartz.job.FaqTipJob",
		trigger : "0 0 */1 * * ?",//每到整数小时就执行ClientDieJob和FaqTipJob
		simpleDelay : "0s",//启动项目之后立即每间隔2秒执行ClientDieJob和FaqTipJob,一共执行3次
		simpleRepeat : "3",
		simpleRepeatDelay : "2s"
	}
}

//-------------------------一个定时任务对应一个simple------------------------------------
{
	type : "com.chat.quartz.QuartzBean",
	fields : {
		name : "faqtipsimple5",
		clazz : "com.chat.quartz.job.FaqTipJob",
		simpleDelay : "0s",//启动项目之后立即每间隔5秒执行FaqTipJob,不限执行次数
		simpleRepeat : "-1",
		simpleRepeatDelay : "5s"
	}
}

//-----------------------------------如果需要给定时任务传递数据请配置jobDatas属性-------------------------------------------
jobDatas:[{
	type : "com.chat.quartz.JobData",
	fields : {
		key : "mykey",
		value : "myvalue"
	}
},{
	type : "com.chat.quartz.JobData",
	fields : {
		key : "mybool",
		value : "false"
	}
}]
//设置了jobdata之后,在具体的job里面 像下面那样使用使用
System.out.println( arg0.getJobDetail().getJobDataMap().get("mykey") );
System.out.println( arg0.getJobDetail().getJobDataMap().getBooleanValue("mybool") );

org.quartz.tool包的源码:



package com.chat.quartz;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.ScheduleBuilder;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.MutableTrigger;

/**
 * 定时任务工具类
 * 
 * @author hp
 * 
 */
public class QuartzTool {
	/**
	 * quartz的Scheduler工厂类
	 */
	private static SchedulerFactory sf = null;

	/**
	 * 定时器map,主要是停止定时器的时候使用
	 */
	private static Map <String, Scheduler> schedMap= new HashMap<String, Scheduler>();
    /**
     * 定时器配置对象
     */
	private static QuartzBean quartzBean = null;
	
	/**
     * 启动定时器
     * @param key 定时器名称
     */
    private static void startSchedule(String key){
    	for (QuartzBean bean : getQuartzBean().getList()) {
    		if(bean.getName().equals( key )){
    			startSchedule(bean);
    			break;
    		}
		}
    }
    
    /**
     * 重新启动定时器
     * @param key 定时器名称
     */
    public void reStartSchedule(String key){
    	for (QuartzBean bean : getQuartzBean().getList()) {
    		if(bean.getName().equals( key )){
    			shutdownSchedule(key);
    			startSchedule(bean);
    			break;
    		}
    	}
    }
    /**
     * 获取定时器配置对象
     * @return
     */
    public static QuartzBean getQuartzBean() {
		return quartzBean;
	}

	/**
     * 启动定时器
     * @param bean 定时bean的
     */
    public static void startSchedule(QuartzBean bean){    	
    	try {
    		//map使用bean的name作为key
    		String key = bean.getName();
    		if( schedMap.containsKey(key) ){//如果已经启动了该定时器,先停止再启动
    			shutdownSchedule(key);
    		}
    		
    		Scheduler sched = getSf().getScheduler();
    		
    		//根据配置生成job集合
    		Set<JobDetail> jobSet = makeJobSet( bean );
    		if(jobSet.size() <= 0){
    			System.out.println("初始化SCheduler失败:" + bean.getName()+"没有配置job的clazz属性。");
    			return ;
    		}    		
    		
    		//根据配置bean生成trigger集合
    		Set<Trigger> tSet = makeTriggerSet( bean );
    		if(tSet.size() <= 0){
    			System.out.println("初始化SCheduler失败:" + bean.getName()+"没有配置任何trigger。");    			
    			return ;
    		}
    		
    		//根据job集合和触发器集合生成schedule需要的map参数
    		Map map = makeSchedMap(jobSet, tSet);
    		
    		sched.scheduleJobs(map, true);
    		//sched.scheduleJob( job, tSet , true);
    		sched.start();
    		
    		schedMap.put(key, sched);
    	} catch (SchedulerException e) {
    		e.printStackTrace();
    	} catch (ClassNotFoundException e) {
    		e.printStackTrace();
    	}
    }
    
    /**
     * 根据job集合和触发器集合生成schedule需要的map参数
     * @param jobSet
     * @param tSet
     * @return
     */
    private static Map makeSchedMap(Set<JobDetail> jobSet, Set<Trigger> tSet) {
    	Map map = new HashMap();
    	int i = 0;//job循环变量
    	for (JobDetail job : jobSet) {
    		Set<Trigger> cloneTriggerSet = new HashSet<Trigger>();
    		//根据每个任务动态生成对应的jobkey
    		for (Trigger trigger : tSet) {
    			MutableTrigger mTrigger = (MutableTrigger) trigger;
    			
    			if(mTrigger != null){
    				MutableTrigger cloneTrigger = (MutableTrigger) mTrigger.clone();
    				cloneTrigger.setJobKey(job.getKey());
    				//因为triggerkey不能重复,所以这里重新设置trigger的key为原来的值加上jobkey的值
    				cloneTrigger.setKey(cloneTrigger.getKey().triggerKey(
    						cloneTrigger.getKey().getName() + cloneTrigger.getJobKey()
					));
    				//为了让trigger同时触发的时候有个优先顺序,这里设置一下优先级,job越靠前的 优先级越高
    				cloneTrigger.setPriority(Trigger.DEFAULT_PRIORITY + 90 - i);
        			cloneTriggerSet.add(cloneTrigger);
    			}
			}
    		
    		map.put(job, cloneTriggerSet);
    		
    		i ++;
		}
    	
		return map;
	}

	/**
     * 根据配置生成job集合
     * @param bean
     * @return
     * @throws ClassNotFoundException 
     */
    private static Set<JobDetail> makeJobSet(QuartzBean bean) throws ClassNotFoundException {
    	Set<JobDetail> jobSet = new HashSet<JobDetail>();  
    	//clazz没有直接返回
    	if(StringIsEmpty(bean.getClazz()) ){
    		return jobSet;
    	}
    	//构建jobDataMap 
    	JobDataMap jobDataMap = makeJobDataMap(bean);
    	
    	String[] clazzArr = bean.getClazz().split(",");
    	for (int i = 0; i < clazzArr.length; i++) {
    		String clazz = clazzArr[i];
    		JobDetail job = JobBuilder.newJob((Class<? extends Job>) Class.forName(clazz ))
    						.usingJobData(jobDataMap)
    						.withIdentity(bean.getName() + i ) .build();
    		jobSet.add(job);
		}
    	
		return jobSet;
	}
    /**
     * 根据bean里面的JobDatas生成quartz里面的jobDataMap
     * @param bean
     * @return
     */
	private static JobDataMap makeJobDataMap(QuartzBean bean) {
		JobDataMap jobDataMap = new JobDataMap();
		for (JobData jobData : bean.getJobDatas()) {
			jobDataMap.put(jobData.getKey(), jobData.getValue());
		}
		
		return jobDataMap;
	}

	/**
     * 生成调度规则集合,暂时只支持一个cron和一个simple
     * @param bean 调度规则配置对象
     * @return
     */
    private static Set<Trigger> makeTriggerSet(QuartzBean bean) {
    	Set<Trigger> tSet = new HashSet<Trigger>();
    	
		CronTrigger cTrigger = makeCTrigger( bean );
		SimpleTrigger sTrigger = makeSTrigger( bean );
		if( cTrigger!=null ) tSet.add(cTrigger);
		if( sTrigger!=null ) tSet.add(sTrigger);
		
		return tSet;
	}
    /**
     * 生成简单的trigger
     * @param bean
     * @return
     */
	private static SimpleTrigger makeSTrigger(QuartzBean bean) {
    	//根据delay生成相对当前时间的一个时间,只支持加时间。
    	Date beginDate = makeDate( bean.getSimpleDelay() );
    	if( beginDate == null )
    		return null;
    	//简单调度规则的开始时间
    	TriggerBuilder tBulder = TriggerBuilder.newTrigger()
								.withIdentity( "sTrigger", bean.getName() )
								.startAt(beginDate );
    	//生成简单调度规则的重复次数
    	ScheduleBuilder sBulder = makeSimpleTriggerRepeat(bean);
    	if(sBulder != null)
    		tBulder.withSchedule(sBulder);
    	
    	SimpleTrigger sTrigger = (SimpleTrigger) tBulder.build();
    	
		return sTrigger;
	}

	/**
	 * 根据规则生成trigger
	 * @param bean 调度任务配置对象
	 * @return
	 */
	private static CronTrigger makeCTrigger(QuartzBean bean) {
		//调度规则
		String role = bean.getTrigger();
		
		if( StringIsEmpty(role) ){
			return null;
		}
		
		CronScheduleBuilder schedule = CronScheduleBuilder.cronSchedule(role);
		CronTrigger trigger = TriggerBuilder.newTrigger().withSchedule(schedule)
								.withIdentity( "cTrigger", bean.getName() ).build();
		return trigger;
	}
	
	/**
	 * 生成简单调度规则的重复次数
	 * @param bean
	 * @return
	 */
	private static ScheduleBuilder makeSimpleTriggerRepeat(QuartzBean bean) {
		ScheduleBuilder sBulder = null;
		
		//重复次数
		Integer count = bean.getSimpleRepeat();
		
		//不重复直接返回null,重复次数为0 或者没有重复的间隔时间即为不重复
		if( count == 0 || StringIsEmpty(bean.getSimpleRepeatDelay() ) ){
			return null;
		}
		
		//根据delay字符串生成时间对象
		IntervalObject io = makeIntervalObj(bean.getSimpleRepeatDelay());		
		if(io == null){
			return null;
		}
		
		if(count == -1)//-1次表示一直循环
			sBulder = SimpleScheduleBuilder.repeatSecondlyForever(io.getSecond());
		else
			sBulder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(count, io.getSecond() );
		
		return sBulder;
	}
	
	
	/**
	 * 根据delay生成相对当前时间的一个时间,只支持加时间。
	 * @param delay 相对时间字符串,比如20s(20秒) 3m(3分钟) 60D(60天)
	 * @return
	 */
	private static Date makeDate(String delay) {
		if( StringIsEmpty(delay ) ){
    		return null;
    	}
		//根据delay字符串生成时间对象
		IntervalObject io = makeIntervalObj(delay);
		if(io == null){
			return null;
		}
		
		Date date = DateBuilder.futureDate(io.getInterval(), io.getUnit());
		
		return date;
	}
	/**
	 * 根据delay字符串生成时间对象
	 * @param delay
	 * @return
	 */
	private static IntervalObject makeIntervalObj(String delay) {
		String[] numArr = delay.split("[^\\d]");
		Integer interval = Integer.valueOf( StringsJoin("", numArr) );
		if(interval == null || interval < 0){
			return null;
		}
		
		//不带单位的时候,默认使用毫秒作单位
		IntervalUnit unit = IntervalUnit.MILLISECOND;
		if( delay.endsWith("ms") ){
			unit = IntervalUnit.MILLISECOND;
		}else if( delay.endsWith("s") ){
			unit = IntervalUnit.SECOND;
		}else if( delay.endsWith("m") ){
			unit = IntervalUnit.MINUTE;
		}else if( delay.endsWith("D") ){
			unit = IntervalUnit.DAY;
		}else if( delay.endsWith("M") ){
			unit = IntervalUnit.MONTH;
		}else if( delay.endsWith("Y") ){
			unit = IntervalUnit.YEAR;
		}
		

		IntervalObject io = new IntervalObject(interval, unit);
		
		return io;
	}

	/**
     * 停止定时器
     */
    public static void shutdownSchedule(String key) {
    	if( ! schedMap.containsKey(key)){
    		return;
    	}
    	
    	Scheduler sched = schedMap.remove(key);
        if (null != sched) {
            try {
                sched.shutdown();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 初始化系统定时器
     */
    public static void loadSchedule(QuartzBean baseBean){
    	quartzBean = baseBean;
    	
    	for (QuartzBean bean : baseBean.getList()) {
			startSchedule(bean);
		}
    }
	

	/**
	 * 获取quartz的Scheduler工厂类
	 * @return
	 */
	public static SchedulerFactory getSf() {
		if(sf == null)
			sf = new StdSchedulerFactory();
		return sf;
	}
	
	/**
     * 判断字符串是否为null或者空字符串
     * @param clazz
     * @return
     */
    private static boolean StringIsEmpty(String str) {
		if(str == null || str.trim() == ""){
			return true;
		}
		return false;
	}
    
    /**
	 * 字符串数组连接成一个字符串
	 * @param split 分割字符串
	 * @param numArr 字符串数组
	 * @return
	 */
	private static String StringsJoin(String split, String[] numArr) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < numArr.length; i++) {
			sb.append(numArr[i] );
			if(i != numArr.length - 1 )
				sb.append(split);
		}
		return sb.toString();
	}
}


/**
 * Quartz配置的bean
 * @author chencong
 *
 */
public class QuartzBean {
	
	/*
	 * 定时任务名称
	 * 用于停止的时候使用
	 */
	private String name;
	/**
	 * 任务的class<br/>
	 * 多个调度任务的情况下,使用,分割
	 */
	private String clazz;
	/**
	 * 定时任务的数据集合
	 */
	private List<JobData> jobDatas = new ArrayList<JobData>();
	
	/**
	 * 调度规则
	 */
	private String trigger;
	/**
	 * 启动后多久执行一次,简单调度规则的开始时间<br/>
	 * 格式使用数字加单位,纯数字的单位为ms(毫秒)<br/>
	 * 单位:ms(毫秒) s(秒) m(分) h(小时) D(天) M(月) Y(年)<br/>
	 * 比如20s(20秒) 3m(3分钟) 60D(60天)
	 */
	private String simpleDelay;
	/**
	 * 简单调度规则的重复次数 0表示不重复 -1表示一直重复 <br/>
	 * 默认为1 当指定了简单调度规则但是没指定重复次数默认执行1次
	 */
	private Integer simpleRepeat = 1;
	/**
	 * 简单调度规则的重复间隔时间<br/>
	 * 格式使用数字加单位,纯数字的单位为ms(毫秒)<br/>
         * 单位:ms(毫秒) s(秒) m(分) h(小时) D(天) M(月) Y(年)<br/>
	 * 比如20s(20秒) 3m(3分钟) 60D(60天)
         * 没有指定这个属性不会重复执行简单调度规则
	 */
	private String simpleRepeatDelay;
	
	/**
	 * Quartz配置集合 用于多
	 */
	private List<QuartzBean> list = new ArrayList<QuartzBean>();
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClazz() {
		return clazz;
	}
	public void setClazz(String clazz) {
		this.clazz = clazz;
	}
	public String getTrigger() {
		return trigger;
	}
	public void setTrigger(String trigger) {
		this.trigger = trigger;
	}
	public List<QuartzBean> getList() {
		return list;
	}
	public void setList(List<QuartzBean> list) {
		this.list = list;
	}
	public String getSimpleDelay() {
		return simpleDelay;
	}
	public void setInitDelay(String simpleDelay) {
		this.simpleDelay = simpleDelay;
	}
	
	public Integer getSimpleRepeat() {
		return simpleRepeat;
	}
	public void setSimpleRepeat(Integer simpleRepeat) {
		this.simpleRepeat = simpleRepeat;
	}
	public String getSimpleRepeatDelay() {
		return simpleRepeatDelay;
	}
	

	public void setSimpleRepeatDelay(String simpleRepeatDelay) {
		this.simpleRepeatDelay = simpleRepeatDelay;
	}
	public List<JobData> getJobDatas() {
		return jobDatas;
	}
	public void setJobDatas(List<JobData> jobDatas) {
		this.jobDatas = jobDatas;
	}
}
package com.chat.quartz;

/**
 * 定时任务的数据
 * @author lenovo
 *
 */
public class JobData{
	private String key;
	private Object value;
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	
	public Object getValue() {
		return value;
	}
	
	public void setValue(Object value) {
		this.value = value;
	}
}
package com.chat.quartz;

import org.quartz.DateBuilder.IntervalUnit;

/**
 * 时间对象,内部类,包含时间数字和时间单位
 * @author lenovo
 *
 */
public class IntervalObject {
	/**
	 * 时间的数字
	 */
	private Integer interval;
	/**
	 * 时间的单位
	 */
	private IntervalUnit unit;
	
	/**
	 * 获取时间的数字
	 * @return
	 */
	public Integer getInterval() {
		return interval;
	}
	/**
	 * 设置时间的数字
	 * @param interval
	 */
	public void setInterval(Integer interval) {
		this.interval = interval;
	}
	/**
	 * 获取时间的单位
	 * @return
	 */
	public IntervalUnit getUnit() {
		return unit;
	}
	/**
	 * 设置时间的单位
	 * @param unit
	 */
	public void setUnit(IntervalUnit unit) {
		this.unit = unit;
	}
	/**
	 * 获取时间的秒数
	 * @return
	 */
	public Integer getSecond(){
		if(this.getUnit() == null){
			return null;
		}			
		Integer Second = null;
		switch (getUnit()) {
			case MILLISECOND:
				Second = (int) Math.ceil(this.getInterval() / 1000.0 );
				break;
			case SECOND:
				Second = this.getInterval();
				break;
			case MINUTE:
				Second = this.getInterval() * 60;
				break;
			case HOUR:
				Second = this.getInterval() * 60 * 60;
				break;
			case DAY:
				Second = this.getInterval() * 60 * 60 * 24;
				break;
			case MONTH:
				//这里有问题 月按照30天一个月来计算
				Second = this.getInterval() * 60 * 60 * 24 * 30;
				break;
			case YEAR:
				//这里有问题 年按照365天来算
				Second = this.getInterval() * 60 * 60 * 24 * 365;
				break;
	
			default:
				break;
		}
		
		return Second;
	}
	
	public IntervalObject(Integer interval, IntervalUnit unit) {
		super();
		this.interval = interval;
		this.unit = unit;
	}
	public IntervalObject() {
		super();
	}
}










  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值