百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

从零搭建定时任务框架(定时任务管理框架)

sinye56 2024-09-27 21:27 6 浏览 0 评论

IT牛哥与你分享

最近项目上需要接入很多外围系统接口,需要一个定时任务框架,以前的旧框架是用xml配置的方式,而且是需要部署到web容器上,每次停任务或者更改任务的执行频率,都需要重启应用,对于生产环境来说,这个是比较致命的!所以打算重新搭建一个定时任务框架。下面从需求、技术选型与实现、部署几个方面给大家分享一下搭建的过程。

需求

  • 功能需求
  1. 启动、停止、配置执行频率:这个是最基本的需求,主要是满足任务按需启停或者更改执行的频率,不需要对工程进行启停。
  2. 日志:主要记录任务的调用情况、调用开始与结束时间等信息,便于查找问题。
  3. 监控与告警:对记录日志进行监控,针对调用异常的任务及时短信或邮件告警。
  4. restful接口文档自动生成与在线调用:对开发的restful api可以自动生成接口文档,并且可以在线调用。
  • 非功能需求
  1. 更改配置不需要重启。
  2. 部署简单。

技术选型

经过一番考虑,最终选择使用springboot+quartz+mybatis+oracle+swagger+maven来搭建这个框架。

  • springboot:①开源、轻量级框架②简化spring框架的搭建与开发过程③内嵌tomcat④不生成代码、不配置xml
  • quartz:①开源作业调度框架②包含调度器监听、作业和触发器监听③使用简单,JOB接口就一个execute方法
  • mybatis:①mapper中可以生成一些基本的方法,sql在xml中可配置②主要是感觉hibernate和jpa不好用
  • oracle:①用户提供,所以没有②了
  • swagger:①用于生成、描述、调用和可视化restful风格的服务②接口文档的在线自动生成③功能测试
  • maven:①项目管理工具,管理jar包

实现

  • 工程结构树状图
job_schedule_demo
│      
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─demo
│  │  │          └─schedule
│  │  │              │  JobScheduleApp.java
│  │  │              │  
│  │  │              ├─base
│  │  │              │      BaseTask.java
│  │  │              │      JobFactory.java
│  │  │              │      MybatisJavaTypeResolver.java
│  │  │              │      QuartzManager.java
│  │  │              │      SwaggerConfiguration.java
│  │  │              │      
│  │  │              ├─common
│  │  │              │      Constants.java
│  │  │              │      
│  │  │              ├─controller
│  │  │              │      JobConfigController.java
│  │  │              │      
│  │  │              ├─entity
│  │  │              │      TJobRunningLog.java
│  │  │              │      TJobRunningLogCriteria.java
│  │  │              │      TJobsConfig.java
│  │  │              │      TJobsConfigCriteria.java
│  │  │              │      
│  │  │              ├─job
│  │  │              │      HelloWorldJob.java
│  │  │              │      
│  │  │              ├─listener
│  │  │              │      ScheduleJobInitListener.java
│  │  │              │      
│  │  │              ├─mapper
│  │  │              │      TJobRunningLogMapper.java
│  │  │              │      TJobRunningLogMapper.xml
│  │  │              │      TJobsConfigMapper.java
│  │  │              │      TJobsConfigMapper.xml
│  │  │              │      
│  │  │              ├─service
│  │  │              │  │  JobService.java
│  │  │              │  │  
│  │  │              │  └─ipml
│  │  │              │          JobServiceImpl.java
│  │  │              │          
│  │  │              └─utils
│  │  └─resources
│  │      │  application.yml
│  │      │  
│  │      └─mybatis
│  │              gencfg-mybatis-oracle.xml
│  │              mybatis-config.xml
│  │              
│  └─test
│      └─java
└─target
  • 启动类
@SpringBootApplication
@MapperScan("com.demo.schedule.mapper")
public class JobScheduleApp {

	public static void main(String[] args) {
		SpringApplication.run(JobScheduleApp.class, args);
	}
}
  • 监听器
@Component
@Order(value = 1)
public class ScheduleJobInitListener implements CommandLineRunner {

	private static Logger logger = LoggerFactory.getLogger(ScheduleJobInitListener.class);
	
    @Autowired
    JobService jobService;

    @Override
    public void run(String... arg0) throws Exception {
        try {
        	jobService.initSchedule();
        } catch (Exception e) {
        	logger.error("ScheduleJobInitListener Exception", e);
        }
    }
}
  • 初始化有效的任务
/**
	 * 
	 * @Title: initSchedule
	 * @Description: 初始化所有有效job
	 * @throws SchedulerException    
	 * @throws
	 */
	@Override
	public void initSchedule() throws SchedulerException {
		TJobsConfigCriteria example = new TJobsConfigCriteria();
		TJobsConfigCriteria.Criteria criteria = example.createCriteria();
		criteria.andJobStatusEqualTo(Constants.JObSTATUS_MAPPING.get("RUNNING"));
		criteria.andJobGroupEqualTo("DEMO");
		List<TJobsConfig> jobList = tjobsconfigMapper.selectByExample(example);
		for (TJobsConfig job : jobList) {
			if (Constants.JObSTATUS_MAPPING.get("RUNNING").equals(job.getJobStatus())) {
				logger.info("will add job:{}", job.getJobName());
				quartzManager.addJob(job);
			}
		}
	}

这个地方使用了quartz的添加任务

/**
     * 添加任务
     * 
     * @param job
     * @throws SchedulerException
     */    
    @SuppressWarnings("unchecked")
    public void addJob(TJobsConfig job) {
        try {
            // 创建jobDetail实例,绑定Job实现类
            // 指明job的名称,所在组的名称,以及绑定job类

            Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(job.getBeanClass()).newInstance()
                    .getClass());
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(job.getJobName(), job.getJobGroup())// 任务名称和组构成任务key
                    .build();
            // 定义调度触发规则
            // 使用cornTrigger规则
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())// 触发器key
                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).startNow().build();
            // 把作业和触发器注册到任务调度中
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
        	log.error("添加任务 异常", e);
        }
    }
  • 配置用来测试的任务HelloWorldJob

BaseTask中实现了Job接口的execute方法,分别记录了任务执行前后的日志,所有的任务继承BaseTask。

@DisallowConcurrentExecution //作业不并发
@Component
public class HelloWorldJob extends BaseTask{
    public void perform()  {
       System.out.println("欢迎使用,这是一个定时任务框架!");
    }
}

在数据库表中配置执行频率

执行启动类,定时任务就可以运行了!

部署

mvn install打成jar包上传到服务器指定目录,执行java -jar jar包就可以了。

感兴趣的朋友可以关注我或者给我留言,大家共同学习,共同进步!

相关推荐

Linux两种光驱自动挂载的方法

环境:CentOS6.4西昆云服务器方式一修改fstab文件/etc/fstab是系统保存文件系统信息?静态文件,每一行描述一个文件系统;系统每次启动会读取此文件信息以确定需要挂载哪些文件系统。参...

linux系统运维,挂载和分区概念太难?在虚机下操作一次全掌握

虚拟机的好处就是可以模拟和学习生产环境的一切操作,假如我们还不熟悉磁盘操作,那先在虚机环境下多操作几次。这次来练习下硬盘扩容操作。虚拟机环境:centos8vm11linux设备命名规则在linux中...

Linux 挂载 NFS 外部存储 (mount 和 /etc/fstab)

mount:手工挂载,下次重启需再重新挂载,操作命令:mount-tnfs-ooptionsserver:/remote/export/local/directory上面命令中,本地目录...

在Linux中如何设置自动挂载特定文件系统(示例)

Linux...

Linux环境中的绑定挂载(bind mount)

简介:Linux中的mount命令是一个特殊的指令,主要用于挂载文件目录。而绑定挂载(bindmount)命令更为特别。mount的bind选项将第一个目录克隆到第二个。一个目录中的改变将会在...

Linux挂载CIFS共享 临时挂载 1. 首先

如何解决服务器存储空间不足的问题?大家好,欢迎回来。在上一期视频中,我为大家介绍了如何利用Linux挂载来扩容服务器存储空间。这一期视频,我将以Linux为例,教大家如何进行扩容。群辉使用的是Linu...

Linux 硬盘挂载(服务器重启自动挂载)

1、先查看目前机器上有几块硬盘,及已挂载磁盘:fdisk-l能够查看到当前主机上已连接上的磁盘,以及已经分割的磁盘分区。(下面以/dev/vdb磁盘进行分区、挂载为例,挂载点设置为/data)df...

linux 挂载磁盘

在Linux中挂载硬盘的步骤如下:...

笨小猪教您Linux磁盘挂载

本教程针对Linux系统比较熟悉或者想学习Linux基础的用户朋友,本教程操作起来比较傻瓜式,跟着步骤就会操作,本文使用的工具是XShell同时多多注意空格(文中会有提示)。【问答】什么是磁盘挂载?答...

Linux 磁盘挂载和docker安装命令

本篇给大家介绍Linux磁盘挂载和docker安装的相关内容,Linux服务器的操作是一个手熟的过程,一些不常用的命令隔断时间就忘记了,熟话说好记性不如烂笔头,还需在平时的工作中多练习记录。...

Linux设置开机自动挂载分区

有时候,我们在安装完Linux系统之后,可能在使用过程中添加硬盘或者分区进行使用,这时候就需要手动把磁盘分区挂载到某个路径,但是开机之后就会消失,需要重新挂载,非常麻烦,那么我们应该如何设置开机自动挂...

在linux挂载一个新硬盘的完整步骤

以下是在Linux中挂载新原始磁盘的完整步骤,包括分区、创建文件系统以及使用UUID在/etc/fstab中启动时挂载磁盘:将新的原始磁盘连接到Linux系统并打开电源。运行以下命令,...

Linux系统如何挂载exFAT分区

简介:Linux系统中不能像Windows系统那样自动识别加载新设备,需要手动识别,手动加载。Linux中一切皆文件。文件通过一个很大的文件树来组织,文件树的根目录是:/,从根目开始录逐级展开。这些文...

Linux系统挂载硬盘

fdisk-l查看可挂载的磁盘都有哪些df-h查看已经挂载的磁盘...

WSL2发布,如何在Win10中挂载Linux文件系统

WSL2是最新版本的架构,它为Windows子系统提供支持,使其能够在Windows上运行ELF64Linux二进制文件。通过最近的更新,它允许使用Linux文件系统访问存储在硬盘中的文件。如果你...

取消回复欢迎 发表评论: