quartz实现动态任务管理系统

我们在开发中经常要对任务进行系统性的管理,比如新加一个任务每天0点更新,修改任务,删除任务,暂停任务等,就需要写一个集中的任务管理器,这边实现一个简单的任务管理系统

在数据库中创建任务表以及字段进行任务数据管理
实现任务实体类,调用quartz官方api,实现对任务管理的逻辑
书写对应的接口,主要为增加任务,删除任务,修改任务,任务详情,暂停任务
实现了简单的前端测试代码,可以对任务动态管理进行测试
在实际项目中一般使用数据库存储任务,使用quartz框架进行增删改查暂停开启,达到定时任务的管理

1.创建任务表,sql脚本为

CREATE TABLE scheduled_tasks (
    task_id INT AUTO_INCREMENT PRIMARY KEY, -- 任务ID,自增主键
    task_name VARCHAR(255) NOT NULL, -- 任务名称,不允许为空
    task_group VARCHAR(255), -- 任务分组
    cron_expression VARCHAR(255) NOT NULL, -- Cron表达式,不允许为空
    job_class_name VARCHAR(255) NOT NULL, -- 任务类名,不允许为空
    is_active BOOLEAN -- 是否启用任务
);

2.加上quartz依赖



    org.quartz-scheduler
    quartz
    2.3.2

3.编写yml配置

# 数据源配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database  # 数据库连接URL
    username: your_username  # 数据库用户名
    password: your_password  # 数据库密码
    driver-class-name: com.mysql.cj.jdbc.Driver  # 数据库驱动类名

# Quartz调度器配置
quartz:
  job-store-type: jdbc  # Quartz作业存储类型为JDBC
  properties:
    org:
      quartz:
        scheduler:
          instanceName: your_instance_name  # Quartz调度器实例名称
          instanceId: your_instance_id  # Quartz调度器实例ID
        jobStore:
          class: org.quartz.impl.jdbcjobstore.JobStoreTX  # Quartz作业存储类型
          driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # Quartz数据库操作委托类
          dataSource: your_data_source_name  # 数据源名称,连接到Spring中的数据源
          tablePrefix: QRTZ_  # Quartz表格前缀
          isClustered: true  # 启用Quartz集群模式
          clusterCheckinInterval: 20000  # 集群检查间隔时间(毫秒)

4.编写实体任务类

创建一个Java实体类(ScheduledTask)来映射数据库表,并创建一个JPA Repository来执行CRUD操作
@Data
public class ScheduledTask {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long taskId;            // 主键自动生成的任务ID
    private String taskName;        // 任务名称
    private String taskGroup;       // 任务分组
    private String cronExpression;  // Cron表达式,用于调度任务执行时间
    private String jobClassName;    // 任务执行的类名
    private boolean isActive;       // 任务是否处于活动状态
}

5.实现一个ScheduledTaskRepository,对任务进行操作

public interface ScheduledTaskRepository extends JpaRepository {
    // 通过任务名称和分组查找任务
    Optional findByTaskNameAndTaskGroup(String taskName, String taskGroup);

    // 查找所有处于指定活动状态的任务
    List findAllByIsActive(boolean isActive);
}

6.实现任务服务逻辑

创建一个服务类,负责任务的增加、删除、修改、查询、暂停和开启等操作
@Service
public class ScheduledTaskService {

    @Autowired
    private ScheduledTaskRepository taskRepository; // 任务数据存储库

    @Autowired
    private Scheduler scheduler; // 调度器

    // 获取所有已计划任务
    public List getAllTasks() {
        return taskRepository.findAll();
    }

    // 通过任务ID获取指定任务
    public Optional getTaskById(Long taskId) {
        return taskRepository.findById(taskId);
    }

    // 添加新任务
    public void addTask(ScheduledTask task) {
        taskRepository.save(task); // 保存任务信息到数据库

        try {
            // 创建JobDetail,定义任务的执行类和唯一标识
            JobDetail jobDetail = JobBuilder.newJob()
                    .ofType((Class) Class.forName(task.getJobClassName()))
                    .withIdentity(task.getTaskName(), task.getTaskGroup())
                    .build();

            // 创建CronTrigger,定义任务的调度策略
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(task.getTaskName(), task.getTaskGroup())
                    .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression()))
                    .build();

            // 将任务和触发器添加到调度器中
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException | ClassNotFoundException e) {
            // 处理异常
        }
    }

    // 更新任务信息
    public void updateTask(ScheduledTask task) {
        taskRepository.save(task); // 更新任务信息到数据库

        try {
            // 获取原始任务的触发器标识
            TriggerKey triggerKey = new TriggerKey(task.getTaskName(), task.getTaskGroup());

            // 创建新的CronTrigger,更新任务的调度策略
            CronTrigger newTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(task.getTaskName(), task.getTaskGroup())
                    .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression()))
                    .build();

            // 重新调度任务
            scheduler.rescheduleJob(triggerKey, newTrigger);
        } catch (SchedulerException e) {
            // 处理异常
        }
    }
   // 通过任务ID删除任务
   public void deleteTask(Long taskId) {
    
    Optional task = taskRepository.findById(taskId);
    if (task.isPresent()) {
        // 从存储库中删除任务
        taskRepository.deleteById(taskId);

        try {
            // 根据任务信息创建作业键和触发器键
            JobKey jobKey = new JobKey(task.get().getTaskName(), task.get().getTaskGroup());
            TriggerKey triggerKey = new TriggerKey(task.get().getTaskName(), task.get().getTaskGroup());

            // 从调度程序中删除计划作业并取消其触发器
            scheduler.deleteJob(jobKey);
            scheduler.unscheduleJob(triggerKey);
        } catch (SchedulerException e) {
            // 处理调度程序操作可能引发的异常
        }
    }
}
   // 暂停开始任务
   public void toggleTaskStatus(Long taskId) {
    
    Optional task = taskRepository.findById(taskId);
    if (task.isPresent()) {
        // 切换任务的活动状态
        task.get().setActive(!task.get().isActive());
        // 将更新后的任务信息保存到存储库中
        taskRepository.save(task.get());

        try {
            // 根据任务信息创建作业键
            JobKey jobKey = new JobKey(task.get().getTaskName(), task.get().getTaskGroup());

            // 检查任务状态并相应地恢复或暂停作业
            if (task.get().isActive()) {
                scheduler.resumeJob(jobKey);
            } else {
                scheduler.pauseJob(jobKey);
            }
        } catch (SchedulerException e) {
            // 处理调度程序操作可能引发的异常
        }
    }
}

7.实现控制器

@RestController
@RequestMapping("/api/tasks")
public class ScheduledTaskController {

    @Autowired
    private ScheduledTaskService taskService;

    // 获取所有计划任务的端点
    @GetMapping
    public ResponseEntity> getAllTasks() {
        List tasks = taskService.getAllTasks();
        return ResponseEntity.ok(tasks);
    }

    // 通过任务ID获取单个计划任务的端点
    @GetMapping("/{taskId}")
    public ResponseEntity getTaskById(@PathVariable Long taskId) {
        Optional task = taskService.getTaskById(taskId);
        return task.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
    }

    // 添加计划任务的端点
    @PostMapping
    public ResponseEntity addTask(@RequestBody ScheduledTask task) {
        taskService.addTask(task);
        return ResponseEntity.created(null).build();
    }

    // 更新计划任务的端点
    @PutMapping("/{taskId}")
    public ResponseEntity updateTask(@PathVariable Long taskId, @RequestBody ScheduledTask task) {
        if (!taskService.getTaskById(taskId).isPresent()) {
            return ResponseEntity.notFound().build();
        }

        taskService.updateTask(task);
        return ResponseEntity.noContent().build();
    }

    // 删除计划任务的端点
    @DeleteMapping("/{taskId}")
    public ResponseEntity deleteTask(@PathVariable Long taskId) {
        if (!taskService.getTaskById(taskId).isPresent()) {
            return ResponseEntity.notFound().build();
        }

        taskService.deleteTask(taskId);
        return ResponseEntity.noContent().build();
    }

    // 切换计划任务状态的端点
    @PatchMapping("/{taskId}/toggle-status")
    public ResponseEntity toggleTaskStatus(@PathVariable Long taskId) {
        if (!taskService.getTaskById(taskId).isPresent()) {
            return ResponseEntity.notFound().build();
        }

        taskService.toggleTaskStatus(taskId);
        return ResponseEntity.noContent().build();
    }
}

前端简单的html如下




    Scheduled Task Management


    

Scheduled Task Management

List of Tasks

Add a Task

Update a Task

Delete a Task

Toggle Task Status

这样子的话就可以实现一个简单的动态定时任务管理系统

你可能感兴趣的:(java,数据库,开发语言)