从零搭建定时任务框架(定时任务管理框架)
sinye56 2024-09-27 21:27 6 浏览 0 评论
IT牛哥与你分享
最近项目上需要接入很多外围系统接口,需要一个定时任务框架,以前的旧框架是用xml配置的方式,而且是需要部署到web容器上,每次停任务或者更改任务的执行频率,都需要重启应用,对于生产环境来说,这个是比较致命的!所以打算重新搭建一个定时任务框架。下面从需求、技术选型与实现、部署几个方面给大家分享一下搭建的过程。
需求
- 功能需求
- 启动、停止、配置执行频率:这个是最基本的需求,主要是满足任务按需启停或者更改执行的频率,不需要对工程进行启停。
- 日志:主要记录任务的调用情况、调用开始与结束时间等信息,便于查找问题。
- 监控与告警:对记录日志进行监控,针对调用异常的任务及时短信或邮件告警。
- restful接口文档自动生成与在线调用:对开发的restful api可以自动生成接口文档,并且可以在线调用。
- 非功能需求
- 更改配置不需要重启。
- 部署简单。
技术选型
经过一番考虑,最终选择使用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文件系统访问存储在硬盘中的文件。如果你...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle忘记用户名密码 (59)
- oracle11gr2安装教程 (55)
- mybatis调用oracle存储过程 (67)
- oracle spool的用法 (57)
- oracle asm 磁盘管理 (67)
- 前端 设计模式 (64)
- 前端面试vue (56)
- linux格式化 (55)
- linux图形界面 (62)
- linux文件压缩 (75)
- Linux设置权限 (53)
- linux服务器配置 (62)
- mysql安装linux (71)
- linux启动命令 (59)
- 查看linux磁盘 (72)
- linux用户组 (74)
- linux多线程 (70)
- linux设备驱动 (53)
- linux自启动 (59)
- linux网络命令 (55)
- linux传文件 (60)
- linux打包文件 (58)
- linux查看数据库 (61)
- linux获取ip (64)
- 关闭防火墙linux (53)