Spring整合Quartz实现定时任务

一、版本说明

spring3.1以上的版本才支持quartz 2.x,不然会出错。 此示例所选版本:spring版本号4.3.18.RELEASE,quartz版本2.3.0。

二、添加jar包

我的是maven工程,pom.xml相关配置如下: 

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.3.18.RELEASE</spring.version>
        <quartz.version>2.3.0</quartz.version>
    </properties>    

    <dependencies>
	<!-- quartz begin -->
	<dependency>
	    <groupId>org.quartz-scheduler</groupId>
	    <artifactId>quartz</artifactId>
	    <version>${quartz.version}</version>
	</dependency>
	<dependency>
	    <groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz-jobs</artifactId>
		<version>${quartz.version}</version>
	</dependency>
	<!-- quartz end -->	
    </dependencies>

三、整合实现

1、QuartzActiveJob 定时任务工作类

package com.whitelake.modules.sys.task;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.whitelake.modules.mes.wechat.entity.MesEventSourceTask;
import com.whitelake.modules.mes.wechat.service.MesEventSourceTaskService;
import com.whitelake.modules.mes.wechat.service.WechatService;
import com.whitelake.modules.sys.entity.User;
import com.whitelake.modules.sys.util.UserUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
 
/**
 * 实现Job接口,定义运行的任务
 * 发送微信消息
 * @author lixiuwu
 * @date 2018年12月18日 
 *
 */
@Component
public class QuartzActiveJob implements Job {
	private static Logger log = LoggerFactory.getLogger(QuartzActiveJob.class);
    @Autowired
    private MesEventSourceTaskService eventSourceTaskService;
    @Autowired
    private WechatService wechatService;
    
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
    	// 使得job对象可以通过注解实现依赖注入
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        
        // JobExecutionContext类提供了调度上线问的各种信息,为JobDetail和Trigger提供必要的信息
        // JobKey是由name和group组成,并且name必须在group内是唯一的。如果只指定一组则将使用默认的组名。
        JobKey jobKey = context.getJobDetail().getKey();
        log.info("QuartzActiveJob says: " + jobKey + " executing at " + new Date());
        String taskId = jobKey.getName(); //定时任务表ID
        MesEventSourceTask eventSourceTask = eventSourceTaskService.get(taskId);
        //将相应数据插入到待发送表中
        User user = UserUtils.getUser();
      	String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); //当前时间
      	String eventSourceCode = eventSourceTask.getEventSource().getCode(); //事件编码
      	Integer beforeDays = eventSourceTask.getBeforeDays(); //提前天数
       	List<Map<String,Object>> listMap = eventSourceTaskService.getJsonData(eventSourceCode,beforeDays,user.getCorpId()); //根据事件编码取出对应数据
      	for (int i = 0; i < listMap.size(); i++) {
      		Map<String,Object> map = listMap.get(i);
      		String id = null,total=null;
      		if(map.get("id")!=null){
      			id = map.get("id").toString();
      		}
      		if(map.get("total")!=null){
      			total = map.get("total").toString();
      		}
      		String userId = map.get("userId").toString(); //创建者ID
      		String userName = map.get("userName").toString(); //用户名称
      		
      		//将相应数据插入到待发送表中
      		if("produce_work_order_day_quant_notice".equals(eventSourceCode)){ //生产工单-日完工数量通知
      			wechatService.dataSourceParms(user.getCorpId(),eventSourceCode,userId,userName,currentTime,
      					"/mes/mesReportWorkOrder/list","",total,"","","","","","","","","");
      			
      		}else if("produce_flow_card_day_quant_notice".equals(eventSourceCode)){ //生产流转卡-日完工数量通知
      			wechatService.dataSourceParms(user.getCorpId(),eventSourceCode,userId,userName,currentTime,
      					"/mes/mesReportFlowCard/list","",total,"","","","","","","","","");
      			
      		}else if("sale_bill_ship_date_warn".equals(eventSourceCode)){ //销售订单-发货日期预警
      			wechatService.dataSourceParms(user.getCorpId(),eventSourceCode,userId,userName,currentTime,
      					"/mes/mesSaleBill/form?id="+id,"",beforeDays.toString(),"","","","","","","","","");
      			
      		}else if("produce_bill_start_date_warn".equals(eventSourceCode)){ //生产订单-开工日期预警
      			wechatService.dataSourceParms(user.getCorpId(),eventSourceCode,userId,userName,currentTime,
      					"/mes/mesProductionBill/form?id="+id,"",beforeDays.toString(),"","","","","","","","","");
      			
      		}else if("produce_bill_end_date_warn".equals(eventSourceCode)){ //生产订单-完工日期预警
      			wechatService.dataSourceParms(user.getCorpId(),eventSourceCode,userId,userName,currentTime,
      					"/mes/mesProductionBill/form?id="+id,"",beforeDays.toString(),"","","","","","","","","");
      		}
      		updateExecuteTime(eventSourceTask);//成功发送微信消息后,更新定时任务列表的“最后执行时间”和“下次执行时间”。
		}
    }
    
    /**
     * 成功发送微信消息后,更新定时任务列表的“最后执行时间”和“下次执行时间”。
     * @param eventSourceTask
     */
    public void updateExecuteTime(MesEventSourceTask eventSourceTask){
		Integer timerPeriod = eventSourceTask.getTimerPeriod();
		Integer perQuant = eventSourceTask.getPerQuant();
		int repeatInterval =0; //单位是秒
		switch(timerPeriod){
			case 1://年
				repeatInterval = 365*86400*perQuant;
				break;
			case 2://月
				repeatInterval = 30*86400*perQuant;
				break;
			case 3://周
				repeatInterval = 7*86400*perQuant;
				break;
			case 4://天
				repeatInterval = 86400*perQuant;
				break;
			case 5://小时
				repeatInterval = 3600*perQuant;
				break;
			case 6://分钟
				repeatInterval = 60*perQuant;
				break;
			default:
				break;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateStr = sdf.format(new Date().getTime() + repeatInterval * 1000L);
		Date date = null;
		try {
			date= sdf.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		eventSourceTask.setLastExecuteTime(new Date());//最后执行时间就是当前时间
		eventSourceTask.setNextExecuteTime(date);//下次执行时间=最后执行时间+时间间隔(timerPeriod*perQuant)
		eventSourceTaskService.updateExecuteTime(eventSourceTask);
    }
    
}

 

2.QuartzUtils 定时任务工具类

package com.whitelake.modules.sys.util;
 
import com.whitelake.modules.sys.task.QuartzActiveJob;
import org.quartz.*;
import org.quartz.Trigger.TriggerState;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
 
/**
 * SimpleTrigger:在某个时刻开始到某个时刻结束,在其间以某个时间间隔重复执行;<br>
 * SimpleTrigger属性包括:开始时间,结束时间,重复次数,重复间隔时间。
 */
public class QuartzUtils {
	private static Logger log = LoggerFactory.getLogger(QuartzUtils.class);
    private static String JOB_GROUP_NAME = "group1";  //任务组名称
    private static String TRIGGER_GROUP_NAME = "trigger1"; //触发器组名称
    private static StdSchedulerFactory sf = new StdSchedulerFactory();// 通过SchedulerFactory获取一个调度器实例
    private static Scheduler scheduler = null;
    private static TriggerKey triggerKey = null;
    
	/**
	 * 添加一个任务
	 * 在startTime时执行调试,endTime结束执行调度,重复执行repeatCount次,每隔repeatInterval秒执行一次
	 * @param jobName  任务名
	 * @param startTime 调度开始时间
	 * @param endTime 调度结束时间
	 * @param repeatCount 重复执行次数 :设为REPEAT_INDEFINITELY无限次重复
	 * @param repeatInterval 执行时间间隔秒数
	 * @param eventSourceId 事件源ID
	 * @return date 执行完时间
	 */
	public static void addJob(String jobName,Date startTime,Date endTime,int repeatInterval) throws SchedulerException {
        // 代表一个Quartz的独立运行容器
        scheduler = sf.getScheduler();

        // 创建一个JobDetail实例,此版本JobDetail已经作为接口(interface)存在,通过JobBuilder创建
        // 并指定Job在Scheduler中所属组及名称
        JobDetail jobDetail = JobBuilder.newJob(QuartzActiveJob.class).withIdentity(jobName,JOB_GROUP_NAME).build();// 任务名,任务组名,任务执行类
        // 设置定时任务执行规则为在指定的开始时间startTime进行执行,在endTime停止执行,其间 每隔repeatInterval秒执行一次,重复执行repeatCount次。
        // 当指定为SimpleScheduleBuilder时,会发现不用对结果进行强制转换为SimpleTrigger了。
        SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
        		.withIdentity(jobName, TRIGGER_GROUP_NAME)//定义触发器名,触发器组名
        		.startAt(startTime).endAt(endTime) //定义开始和结束时间
                .withSchedule( //定义任务调度的时间间隔和次数
                		SimpleScheduleBuilder.simpleSchedule()
                		.withIntervalInSeconds(repeatInterval)//定义时间间隔秒数
                		.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY)//定义重复执行次数是无限次
                		).build();
        // 添加JobDetail到Scheduler容器中,并且和Trigger进行关联,返回执行时间
        Date date = scheduler.scheduleJob(jobDetail,simpleTrigger);
        log.info(jobDetail.getKey() + " will run at: " + date + " and repeat: " + simpleTrigger.getRepeatCount()
        	+ " times, every " + simpleTrigger.getRepeatInterval() / 1000L + " seconds");
        // 在scheduler.start之后调用,可以重新定义trigger,重新注册
        scheduler.start();
        log.info("------- Started Scheduler -----------------");
//	        scheduler.shutdown(true);
//	        SchedulerMetaData metaData = scheduler.getMetaData();
//	        System.out.println("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");

	}
	
	/**
	 * 移除一个任务
	 * @param jobName
	 * @return 执行结果提示语
	 */
    public static void removeJob(String jobName){
        try {
        	triggerKey = TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME);
    		scheduler.pauseTrigger(triggerKey);//停止触发器
            scheduler.unscheduleJob(triggerKey);//移除触发器
            JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME);
            scheduler.deleteJob(jobKey);//删除任务
            log.info("删除任务=> [任务名:" + jobName + " 任务组:" + JOB_GROUP_NAME + "] ");
        } catch (SchedulerException e) {
            e.printStackTrace();
           log.error("删除任务=> [任务名:" + jobName + " 任务组:" + JOB_GROUP_NAME + "]=> [失败]");
        }
    }
    
    /**
     * 判断某个任务是否正在运行
     * @param jobName
     * @return  true为正在运行
     */
	public static boolean jobIsRun(String jobName){
		if(scheduler != null){
    		triggerKey = TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME);
            TriggerState triggerState;
			try {
				triggerState = scheduler.getTriggerState(triggerKey);
				//[NONE,   NORMAL, PAUSED, COMPLETE, ERROR, BLOCKED]
				//[-1 不存在, 0 正常,   1 暂停,    2 完成,     3 错误,  4 阻塞]
	            if("NORMAL".equals(triggerState.name())){
	            	return true;
	            }
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
			
		}
		return false;
	}
	
}

 

 

3、定时任务调用业务类

	/**
	 * 事件源定时任务-保存
	 * @param mesEventSourceTask
	 * @param model
	 * @param redirectAttributes
	 * @return
	 * @throws SchedulerException 
	 */
	@RequiresPermissions("mes:mesEventSource:edit")
	@RequestMapping(value = "taskSave")
	public String taskSave(MesEventSourceTask mesEventSourceTask, Model model, RedirectAttributes redirectAttributes) throws SchedulerException {
		Map<String,String> map = isTimer(mesEventSourceTask.getEventSource().getId());
		String isTimer = map.get("isTimer");
		if("0".equals(isTimer)){
			addMessage(redirectAttributes, "非定时事件不能被保存,请重试");
		}else{
			if (!beanValidator(model, mesEventSourceTask)){
				return taskForm(mesEventSourceTask, model);
			}
			mesEventSourceTask.setCorpId(UserUtils.getUser().getCorpId());
			mesEventSourceTaskService.save(mesEventSourceTask);
			addMessage(redirectAttributes, "保存定时任务成功");

			
			String jobName = mesEventSourceTask.getId();//存在任务名称相同的情况,因此用任务ID来唯一标识。
			//如果该定时任务正在运行中
			if(QuartzUtils.jobIsRun(jobName)){
				QuartzUtils.removeJob(jobName); //先删除该任务
				addMessage(redirectAttributes, "该定时任务已关闭");
			}
			//状态为“启用”,才新增定时任务
			if(mesEventSourceTask.getIsEnable()==1){
				//某个定时任务jobName,在startTime时执行调试,endTime结束执行调度,每隔repeatInterval秒执行一次
				Integer timerPeriod = mesEventSourceTask.getTimerPeriod();
				Integer perQuant = mesEventSourceTask.getPerQuant();
				int repeatInterval =0; //单位是秒
				switch(timerPeriod){
					case 1://年
						repeatInterval = 365*86400*perQuant;
						break;
					case 2://月
						repeatInterval = 30*86400*perQuant;
						break;
					case 3://周
						repeatInterval = 7*86400*perQuant;
						break;
					case 4://天
						repeatInterval = 86400*perQuant;
						break;
					case 5://小时
						repeatInterval = 3600*perQuant;
						break;
					case 6://分钟
						repeatInterval = 60*perQuant;
						break;
					default:
						break;
				}
				QuartzUtils.addJob(jobName,mesEventSourceTask.getStartTime(),mesEventSourceTask.getEndTime(),repeatInterval);
				addMessage(redirectAttributes, "该定时任务已启用");
			}
		}
		return "redirect:"+Global.getAdminPath()+"/mes/wechat/mesEventSource/taskList";
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值