SpringBoot结合Quartz开发定时任务(三)

859

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战

1、前言

​ 上一篇的分享中,我为大家分享了在SpringBoot项目中基于Quartz开发定时任务的简单实现及简单的封装。但是,现在的应用基本上很少是单体项目了,都根据不同维度将系统拆分成了微服务应用。那么本篇为大家介绍如何在微服务项目中开发定时任务。

2、微服务项目中定时任务的实现

9.png

10.png

11.png

从单体应用拆分成微服务应用,大体上都是根据业务来划分成不同的服务,尽可能地让每一种独立的业务在一个服务中进行处理。在这种情况下,对于定时任务的处理,一种是让每一个服务维护自己的定时任务,另一种是在公共服务里维护定时任务。执行任务时,对具体的任务进行http远程调用来实现。这种解决方案其实并不太好,特别是在分布式环境下不是很可靠,但实现起来很简单。下面就为大家分享下具体代码:

 //管理定时任务的Controller
public class QuartzController extends BaseController { 
	 
    //启动一个任务 
	@RequestMapping("/startTask.json")
	@ResponseBody
	public  String  startTask() {
		Map<String, Object> map =RequestSupport.getParameters();
		String id=String.valueOf(map.get("id"));
		String jobname=String.valueOf(map.get("jobname"));
		StringBuilder logInfo = new StringBuilder();
		logInfo.append("任务事件:开启任务").append("\n");
		logInfo.append("请求服务器:").append(BaseBeansConfig.HostPort).append("\n");
		if (!ScheduleJobInit.getIsRuunning()){
			try {
				String serverAddress = getDoJobCacheAddress();
				String url = "http://"+serverAddress+"/startTask.json";
				logInfo.append("处理结果:请求的服务器没有执行权限,正请求服务:").append(url).append("\n");
				String QUARTZRECORD = quartzBiz.addTaskLog(id,jobname,logInfo.toString());
				map.put("QUARTZRECORD",QUARTZRECORD);
				HttpRequester requester = new HttpRequester();
				HttpRespons httpRespons=requester.sendPost(url , map);  
				return httpRespons.getContent();
			} catch (Exception e) {
				e.printStackTrace();
				return updateFailure(e.getMessage());
			}
		}
		logInfo.append("处理结果:请求的服务器有执行权限").append("\n");
		try {
			if (map.get("QUARTZRECORD")==null) {
				String QUARTZRECORD=quartzBiz.addTaskLog(id , jobname , logInfo.toString());
				map.put("QUARTZRECORD" , QUARTZRECORD);
			}
			quartzBiz.startTask(map);
		} catch (MySchedulerException e) { 
			return updateFailure(e.getMessage());
		} 
		return updateSuccess();
		
	} 
    
    //暂停一个任务
	@RequestMapping("/pauseTask.json")
	@ResponseBody
	public String pauseTask() throws MySchedulerException{
		//代码与开始定时任务类似...		
	} 

}
 
//定时任务业务处理类
public class QuartzBiz {
    
    //这里、将每一个有权限执行定时任务的服务器ip存在了redis里面,执行任务前,会先去判断是否具有执行权限
	@Resource
	private RedisPublishHandler redisPublishHandler;
    
	public void startTask (Map<String,Object> map) throws MySchedulerException {
		QuartzInfo quartzInfo=new  QuartzInfo();
		quartzInfo.setId(Integer.parseInt(String.valueOf(map.get("id"))));
		quartzInfo.setJobName(getStrByObj(map.get("jobname")));
		quartzInfo.setServiceName(getStrByObj(map.get("servicename")));
		quartzInfo.setServiceUrl(getStrByObj(map.get("serviceurl")));
		quartzInfo.setCronExpression(getStrByObj(map.get("cronexpression")));
        //前置任务id,支持多个,以逗号【","】分割
		String preTaskId=getStrByObj(map.get("pretaskid"));
		quartzInfo.setPreTaskIds(preTaskId);
		quartzInfo.setPreJobs(getpreInfoById(preTaskId));
		quartzInfo.setDoAll(getStrByObj(map.get("doall")));
		CronTrigger cronTrigger=QuartzUtil.getCronTrigger(scheduler , quartzInfo.getJobName());
		String id=String.valueOf(quartzInfo.getId());
		if (cronTrigger == null) {
			//创建一个新的任务
			QuartzUtil.creatSchedulerJob(scheduler , quartzInfo);
			quartzDao.changeStatus(id , "1");
		} else {
			// Trigger已存在,那么更新相应的定时设置
			QuartzUtil.deleteTask(scheduler , quartzInfo.getJobName());
			//QuartzUtil.updateTask(scheduler, quartzInfo);
			QuartzUtil.creatSchedulerJob(scheduler , quartzInfo);
			quartzDao.changeStatus(id , "1");
		}
		executeTaskLog(String.valueOf(map.get("QUARTZRECORD")),String.valueOf(quartzInfo.getId()),"\n执行成功","1");
		flushTaskGrid();
	}

	//由于接收请求的服务器不一定就是任务执行服务器,所以列表的刷新存在延迟,这里使用websocket发送刷新请求
	private void flushTaskGrid() {
		try {
			redisPublishHandler.publish(RedisPublishConfig.reloadTaskGrid, null, "reload");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
	public void pauseTask (Map<String,Object> map) throws MySchedulerException {
		String id=getStrByObj(map.get("id"));
		String jobName=getStrByObj(map.get("jobName"));
		QuartzUtil.pauseSchedulerJob(scheduler , jobName );
		quartzDao.changeStatus(id , "0");
		executeTaskLog(String.valueOf(map.get("QUARTZRECORD")),id,"\n执行成功","1");
		flushTaskGrid();
	}

	@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
	public void deleteTask (Map<String,Object> map) throws MySchedulerException {
		String jobName=getStrByObj(map.get("jobName"));
		String id=getStrByObj(map.get("id"));
		QuartzUtil.deleteTask(scheduler , jobName);
		quartzDao.deleteTask(id);
		quartzDao.deleteTaskLog(id);
		executeTaskLog(String.valueOf(map.get("QUARTZRECORD")),id,"\n执行成功","1");
		flushTaskGrid();
	}  

	public void jobInit () throws MySchedulerException {
		List<Map<String, String>> listMaps=quartzDao.getStartTask();
		if (CollectionUtils.isEmpty(listMaps)) {
			return;
		}
		for (Map<String, String> map : listMaps) {
			String jobName=map.get("jobName");
			String servicename=map.get("servicename");
			String serviceurl=map.get("serviceurl");
			String cronExpression=map.get("cronexpression");
			String preTaskId=map.get("pretaskid");
			String doAll=map.get("doall");
			QuartzInfo quartzInfo=new QuartzInfo();
			quartzInfo.setJobName(jobName);
			quartzInfo.setServiceName(servicename);
			quartzInfo.setServiceUrl(serviceurl);
			quartzInfo.setCronExpression(cronExpression);
			quartzInfo.setPreTaskIds(preTaskId);
			quartzInfo.setPreJobs(getpreInfoById(preTaskId));
			quartzInfo.setDoAll(doAll);
			//在Scheduler获取触发器对象
			CronTrigger cronTrigger=QuartzUtil.getCronTrigger(scheduler , jobName);
			if (cronTrigger == null) {
				//创建一个新任务
				QuartzUtil.creatSchedulerJob(scheduler , quartzInfo);
			} else {
				QuartzUtil.deleteTask(scheduler , jobName);
				QuartzUtil.creatSchedulerJob(scheduler , quartzInfo);
			}
		}
	} 

}

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊