quartz与spring整合实现动态任务增删改查

本文最初是为了实现定时推送功能,为推送设置一个时间,到时间后推送到云巴服务器。

所以这里会用到quartz定时任务调度,而且我新增一个定时推送,同时就要新增一个定时任务。所以这里也涉及到了任务的增删改查。

以下是代码实现:

1、定时任务管理类,实现对任务的CURD

package com.qbyy.util.yunba.task;

import java.util.Date;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

/**
 * 定时任务管理类
 * 
 * @author FJB
 * 2015年6月1日 下午3:04:10
 */
@SuppressWarnings("rawtypes")
@Component("pushQuartzManager")
public class PushQuartzManager {
	
	@Autowired
<span style="white-space:pre">	</span>private SchedulerFactoryBean gSchedulerFactory;  
    private String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";  		//任务组名
    private String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME"; //触发器名
    
    @Autowired
    public void setgSchedulerFactory(SchedulerFactoryBean gSchedulerFactory) {
		this.gSchedulerFactory = gSchedulerFactory;
	}

	/** 
     * @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名 
     * @param jobName  任务名 
     * @param cls  任务
     * @param time  时间设置【我这里用的是java.util.Date,这样可以直接查询出数据库的日期,并设置为定时任务的开始时间】
     */  
	public void addJob(String jobName, Class cls, Date startTime) {  
        try {  
        	System.out.println("新增定时任务"+jobName);
        	//Scheduler sched = schedulerFactoryBean.getScheduler();
            Scheduler sched = gSchedulerFactory.getScheduler();  
            JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类  
            //jobDetail.getJobDataMap().put("targetObjectId", jobName);
            // 触发器  
            SimpleTrigger simpleTrigger =  new SimpleTrigger(jobName, TRIGGER_GROUP_NAME);
            simpleTrigger.setStartTime(startTime);
            simpleTrigger.setRepeatCount(0);<span style="white-space:pre">	</span>//重复次数为0,不重复
            sched.scheduleJob(jobDetail, simpleTrigger);
            // 启动  
            if (!sched.isShutdown()) {  
                sched.start();  
            }  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    } 
    
    /**
     * 修改定时任务
     * @param jobName 任务名
     * @param time 时间
     */
    public void modifyJobTime(String jobName,  Date time) {  
        try {  
        	//Scheduler sched = schedulerFactoryBean.getScheduler();
            Scheduler sched = gSchedulerFactory.getScheduler();  
            SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(jobName,TRIGGER_GROUP_NAME);  
            if (trigger == null) {  
                return;  
            }  
            Date oldTime = trigger.getStartTime();
            if (!oldTime.equals(time)) {  
            	System.out.println("时间不相等,修改时间");
                JobDetail jobDetail = sched.getJobDetail(jobName,JOB_GROUP_NAME);  
                Class objJobClass = jobDetail.getJobClass();  
                removeJob(jobName);  
                addJob(jobName, objJobClass, time);  
            }  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }
    
    /**
     * 移除一个定时任务
     * @param jobName
     */
    public void removeJob(String jobName) {  
        try {  
            Scheduler sched = gSchedulerFactory.getScheduler();  
            sched.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 停止触发器  
            sched.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器  
            sched.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    } 
}


2、任务处理类,定时任务所处理的业务

package com.qbyy.util.yunba.task;

import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.wunding.service.system.PushSendServiceI;

/**
 * 定时任务执行类
 * 
 * @author FJB
 * 2015年6月1日 上午11:29:31
 */
public class PushQuartzJob extends QuartzJobBean  {
	
	Logger logger = Logger.getLogger(PushQuartzJob.class);
	
//【关键】推送的业务类,不能直接通过spring注解注入,必须在xml文件中配置
	private PushSendServiceI pushSendService;

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		String id="";
		 try {     
	            //获取JobExecutionContext中的service对象    
	            SchedulerContext skedCtx = context.getScheduler().getContext();     
	            //获取SchedulerContext中的service    
	            //这里的service就是通过配置文件 配置的    
	            pushSendService = (PushSendServiceI)skedCtx.get("pushSendService");     
	            id = context.getJobDetail().getName();
				pushSendService.sendPush(id);
				System.out.println("ID= ["+id+"] 的推送,定时发送成功");
				logger.info("ID= ["+id+"] 的推送,定时发送成功");
			} catch (Exception e) {
				logger.info("ID= ["+id+"] 的推送,定时发送失败");
				e.printStackTrace();
			}    
	}

}


3、配置quartz,这个配置文件要包含到spring的总配置文件中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

	<!-- quartz的调度工厂 -->
	<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="schedulerContextAsMap">      
            <map>      
                <!-- 【关键】spring 管理的service需要放到这里,才能够注入成功<span style="font-family: Arial, Helvetica, sans-serif;">PushQuartzJob 要使用到的业务类要在这里注入才能使用</span> -->      
                <description>schedulerContextAsMap</description>      
                <entry key="pushSendService" value-ref="pushSendServiceImpl" />      
            </map>      
        </property>   
	</bean>
</beans>


4、业务逻辑类

@Service
@Transactional
public class PushManageServiceImpl extends BaseService implements PushManageServiceI {
	
	@Autowired
	private PushManageMapper pushManageMapper;
	
	@Autowired
	private PushQuartzManager pushQuartzManager;

	@Override
	public void savePush(PushManage pushManage) throws Exception {
		String pushId = newId();
		pushManage.setId(pushId);	
	//新增定时任务,这里直接将推送消息对象的ID作为jobName,这样做的好处是,在任务执行时可以直接根据jobName到数据库中查询推送信息
		pushQuartzManager.addJob(pushId, PushQuartzJob.class, pushManage.getTaskpushtime());
		pushManageMapper.save(pushManage);
	}
}


5、每2步中,任务执行所调用的方法所在类,任务推送类

package com.wunding.service.system.impl;

import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wunding.domain.system.PushManage;
import com.wunding.persistence.system.PushManageMapper;
import com.wunding.service.system.PushSendServiceI;
import com.wunding.util.yunba.YunBaPushUtil;

/**
 * 推送定时发送管理类
 * 
 * @author FJB
 * 2015年6月2日 下午3:10:12
 */
@Service
@Transactional
public class PushSendServiceImpl implements PushSendServiceI {

	@Autowired
	private PushManageMapper pushManageMapper;
	@Autowired
	private YunBaPushUtil yunBaPushUtil;

	@Override
	public void sendPush(String id) throws Exception {
		PushManage pushManage = new PushManage();
		pushManage.setId(id);
		Date nowDate = new Date();
		pushManage.setPushtime(nowDate);
		pushManage.setIsavailable(1);
		pushManageMapper.update(pushManage);
		PushManage push = pushManageMapper.get(id);
		yunBaPublish(push);
	}
	
	/**
	 * 发推送到服务器
	 * @param push
	 */
	private void yunBaPublish(PushManage push){
		//调研发送推送的方法
		/**
		 * ----要推送的内容----
		 * 1.推送内容[msg]
		 * 2.内容id [contentId]
		 * 3.内容类型,资讯、考试等 [contentType]
		 * 4.推送目标人员或部门 [topic or alias]
		 * 5.按别名或频道推送 [pushType]
		 */
		try {
			String pushStr = "{'topic': 'topic1', 'msg': '"+push.getMessages()+"', 'qos': 1}";
			JSONObject json = new JSONObject(pushStr);
			yunBaPushUtil.getSocket().emit("publish", json);
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}

}


要注意的地方:第2步中注入的service类与第4步中的业务逻辑类不能是同一个类,这也是我单独提取出第5步中的类的原因,因为如果是同一个类,会存在相互注入,也就是循环注入,会报类似如下的错误:

This means that said other beans do not use the final version of the bean. This is often the 
result of S type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, 
for example.


6、特别声明:在编码过程中参考网上多个地方的代码,在这里我也提供参考的链接地址:

(1)http://blog.csdn.net/whaosy/article/details/6298686 这里参考了在Job中注入service的方法

(2)http://blog.csdn.net/pengpegv5yaya/article/details/37595889 这里参考了对定时任务的CURD

(3)http://www.ibm.com/developerworks/cn/java/j-quartz/#ibm-pcon 这里参考了SimpleTrigger


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值