quartz实现动态任务管理系统
2023-12-14 15:42:10
我们在开发中经常要对任务进行系统性的管理,比如新加一个任务每天0点更新,修改任务,删除任务,暂停任务等,就需要写一个集中的任务管理器,这边实现一个简单的任务管理系统
没有简单了解请看?quartz入门详解
在数据库中创建任务表以及字段进行任务数据管理
实现任务实体类,调用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依赖
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
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<ScheduledTask, Long> {
// 通过任务名称和分组查找任务
Optional<ScheduledTask> findByTaskNameAndTaskGroup(String taskName, String taskGroup);
// 查找所有处于指定活动状态的任务
List<ScheduledTask> findAllByIsActive(boolean isActive);
}
6.实现任务服务逻辑
创建一个服务类,负责任务的增加、删除、修改、查询、暂停和开启等操作
@Service
public class ScheduledTaskService {
@Autowired
private ScheduledTaskRepository taskRepository; // 任务数据存储库
@Autowired
private Scheduler scheduler; // 调度器
// 获取所有已计划任务
public List<ScheduledTask> getAllTasks() {
return taskRepository.findAll();
}
// 通过任务ID获取指定任务
public Optional<ScheduledTask> 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<ScheduledTask> 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<ScheduledTask> 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<List<ScheduledTask>> getAllTasks() {
List<ScheduledTask> tasks = taskService.getAllTasks();
return ResponseEntity.ok(tasks);
}
// 通过任务ID获取单个计划任务的端点
@GetMapping("/{taskId}")
public ResponseEntity<ScheduledTask> getTaskById(@PathVariable Long taskId) {
Optional<ScheduledTask> task = taskService.getTaskById(taskId);
return task.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
// 添加计划任务的端点
@PostMapping
public ResponseEntity<Void> addTask(@RequestBody ScheduledTask task) {
taskService.addTask(task);
return ResponseEntity.created(null).build();
}
// 更新计划任务的端点
@PutMapping("/{taskId}")
public ResponseEntity<Void> 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<Void> 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<Void> toggleTaskStatus(@PathVariable Long taskId) {
if (!taskService.getTaskById(taskId).isPresent()) {
return ResponseEntity.notFound().build();
}
taskService.toggleTaskStatus(taskId);
return ResponseEntity.noContent().build();
}
}
前端简单的html如下
<!DOCTYPE html>
<html>
<head>
<title>Scheduled Task Management</title>
</head>
<body>
<h1>Scheduled Task Management</h1>
<!-- 列出所有任务 -->
<h2>List of Tasks</h2>
<ul id="taskList">
</ul>
<!-- 添加任务表单 -->
<h2>Add a Task</h2>
<form id="addTaskForm">
<label for="taskName">Task Name:</label>
<input type="text" id="taskName" name="taskName" required>
<button type="submit">Add Task</button>
</form>
<!-- 更新任务表单 -->
<h2>Update a Task</h2>
<form id="updateTaskForm">
<label for="taskIdToUpdate">Task ID to Update:</label>
<input type="text" id="taskIdToUpdate" name="taskIdToUpdate" required>
<label for="updatedTaskName">Updated Task Name:</label>
<input type="text" id="updatedTaskName" name="updatedTaskName" required>
<button type="submit">Update Task</button>
</form>
<!-- 删除任务表单 -->
<h2>Delete a Task</h2>
<form id="deleteTaskForm">
<label for="taskIdToDelete">Task ID to Delete:</label>
<input type="text" id="taskIdToDelete" name="taskIdToDelete" required>
<button type="submit">Delete Task</button>
</form>
<!-- 切换任务状态表单 -->
<h2>Toggle Task Status</h2>
<form id="toggleTaskStatusForm">
<label for="taskIdToToggle">Task ID to Toggle Status:</label>
<input type="text" id="taskIdToToggle" name="taskIdToToggle" required>
<button type="submit">Toggle Status</button>
</form>
<script>
// JavaScript代码,用于与Spring Boot服务进行交互
// 列出所有任务
function listTasks() {
fetch('/api/tasks')
.then(response => response.json())
.then(data => {
const taskList = document.getElementById('taskList');
taskList.innerHTML = '';
data.forEach(task => {
const listItem = document.createElement('li');
listItem.textContent = `Task ID: ${task.id}, Task Name: ${task.name}, Status: ${task.status}`;
taskList.appendChild(listItem);
});
});
}
// 添加任务
document.getElementById('addTaskForm').addEventListener('submit', function (event) {
event.preventDefault();
const taskName = document.getElementById('taskName').value;
fetch('/api/tasks', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: taskName })
})
.then(() => {
listTasks();
});
});
// 更新任务
document.getElementById('updateTaskForm').addEventListener('submit', function (event) {
event.preventDefault();
const taskId = document.getElementById('taskIdToUpdate').value;
const updatedTaskName = document.getElementById('updatedTaskName').value;
fetch(`/api/tasks/${taskId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ id: taskId, name: updatedTaskName })
})
.then(() => {
listTasks();
});
});
// 删除任务
document.getElementById('deleteTaskForm').addEventListener('submit', function (event) {
event.preventDefault();
const taskId = document.getElementById('taskIdToDelete').value;
fetch(`/api/tasks/${taskId}`, {
method: 'DELETE'
})
.then(() => {
listTasks();
});
});
// 切换任务状态
document.getElementById('toggleTaskStatusForm').addEventListener('submit', function (event) {
event.preventDefault();
const taskId = document.getElementById('taskIdToToggle').value;
fetch(`/api/tasks/${taskId}/toggle-status`, {
method: 'PATCH'
})
.then(() => {
listTasks();
});
});
// 页面加载时列出所有任务
listTasks();
</script>
</body>
</html>
这样子的话就可以实现一个简单的动态定时任务管理系统
文章来源:https://blog.csdn.net/m0_69156017/article/details/134996019
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!