我们在开发中经常要对任务进行系统性的管理,比如新加一个任务每天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 extends Job>) 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
这样子的话就可以实现一个简单的动态定时任务管理系统