diff --git a/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupLog.java b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupLog.java new file mode 100644 index 00000000..be9afe2e --- /dev/null +++ b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupLog.java @@ -0,0 +1,93 @@ +package com.zyplayer.doc.data.repository.manage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * 备份记录信息 + * + * @author diantu + * @since 2023年3月3日 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("backup_log") +public class BackupLog implements Serializable { + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + /** + * 数据源id + */ + private Long dbId; + /** + * 来源(手动备份|自动备份) + */ + private String category; + /** + * 库名 + */ + private String databaseName; + /** + * 表名 + */ + private String tablesName; + /** + * 备份方式 + */ + private Integer dataType; + /** + * 是否压缩 + */ + private Boolean isCompress; + /** + * 是否上传 + */ + private Boolean isUpload; + /** + * 是否删除 + */ + private Boolean isDelete; + /** + * 文件路径 + */ + private String filePath; + /** + * 文件大小 + */ + private Long fileSize; + /** + * 备份状态(-1-失败0-备份中1-上传中200-成功) + */ + private Integer status; + /** + * 备份信息 + */ + private String msg; + /** + * 开始时间 + */ + private Date startTime; + /** + * 结束时间 + */ + private Date endTime; + /** + * 耗时(ms) + */ + private Long spendTime; + /** + * 删除状态(0--未删除1--已删除) + */ + private Integer delFlag; + +} diff --git a/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupTask.java b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupTask.java new file mode 100644 index 00000000..33d65d19 --- /dev/null +++ b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/repository/manage/entity/BackupTask.java @@ -0,0 +1,66 @@ +package com.zyplayer.doc.data.repository.manage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * 备份任务信息 + * + * @author diantu + * @since 2023年3月3日 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "backup_task", autoResultMap = true) +public class BackupTask implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + /** + * 数据源id + */ + private Long dbId; + /** + * cron表达式 + */ + private String cron; + /** + * 参数 + */ + private String param; + /** + * 状态(0-停止1-启动) + */ + private Boolean status; + /** + * 库名 + */ + private String databaseName; + /** + * 表名 + */ + private String tablesName; + /** + * 备份方式 + */ + private Integer dataType; + /** + * 备注 + */ + private String remark; + /** + * 创建时间 + */ + private Date createTime; + /** + * 删除状态(0--未删除1--已删除) + */ + private Integer delFlag; + +} diff --git a/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/utils/CleanInputCache.java b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/utils/CleanInputCache.java new file mode 100644 index 00000000..d0fb6e3f --- /dev/null +++ b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/utils/CleanInputCache.java @@ -0,0 +1,43 @@ +package com.zyplayer.doc.data.utils; + +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * 创建一个线程类来不停地来读出Process调用脚本的输出数据,防止缓冲区被缓冲数据塞满而线程阻塞 + * @author diantu + * @since 2023年3月3日 + */ +@Slf4j +public class CleanInputCache extends Thread{ + + private final String type; + private final String charSet; + private final StringBuilder msg; + private final InputStream inputStream; + + public CleanInputCache(InputStream inputStream, String type, String charSet, StringBuilder msg) { + this.type = type; + this.msg = msg; + this.charSet = charSet; + this.inputStream = inputStream; + } + + public void run() { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charSet)); + String line = null; + while ((line = reader.readLine()) != null) { + if ("error".equals(type)) { + msg.append(line); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/zyplayer-doc-db/pom.xml b/zyplayer-doc-db/pom.xml index 51c5a99f..2854d88c 100644 --- a/zyplayer-doc-db/pom.xml +++ b/zyplayer-doc-db/pom.xml @@ -51,7 +51,12 @@ org.projectlombok lombok - + + org.quartz-scheduler + quartz + 2.3.2 + + UTF-8 diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/enums/BackupCategoryEnum.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/enums/BackupCategoryEnum.java new file mode 100644 index 00000000..eeeb6fdb --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/enums/BackupCategoryEnum.java @@ -0,0 +1,39 @@ +package com.zyplayer.doc.db.framework.db.enums; + +import lombok.AllArgsConstructor; + +/** + * 备份类型枚举类 + * + * @author diantu + * @since 2023年3月8日 + */ +@AllArgsConstructor +public enum BackupCategoryEnum { + + /** + * 手动备份 + */ + MANUAL("0", "手动备份"), + + /** + * 自动备份 + */ + AUTO("1", "自动备份"); + /** + * 编码 + */ + private final String code; + /** + * 信息 + */ + private final String msg; + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } +} diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/job/BackupJob.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/job/BackupJob.java new file mode 100644 index 00000000..2bb3cacd --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/job/BackupJob.java @@ -0,0 +1,34 @@ +package com.zyplayer.doc.db.framework.db.job; + +import com.alibaba.fastjson.JSONObject; +import com.zyplayer.doc.data.repository.manage.entity.BackupLog; +import com.zyplayer.doc.db.framework.db.vo.BackupJobVO; +import com.zyplayer.doc.db.framework.utils.DatabaseBackupUtils; +import com.zyplayer.doc.db.framework.utils.QuartzManagerUtils; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 数据库备份定时任务执行 + * + * @author diantu + * @since 2023年2月8日 + */ +public class BackupJob implements Job { + + @Autowired + private DatabaseBackupUtils databaseBackupUtils; + + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + // 解析参数 + BackupJobVO jobVO = JSONObject.parseObject(context.getJobDetail().getJobDataMap().getString(QuartzManagerUtils.PARAM_KEY), BackupJobVO.class); + // TODO 保存备份记录 + BackupLog backupLog = new BackupLog(); + //开始备份 + databaseBackupUtils.saveBackUp(jobVO, backupLog); + } +} diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupJobVO.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupJobVO.java new file mode 100644 index 00000000..46b03181 --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupJobVO.java @@ -0,0 +1,62 @@ +package com.zyplayer.doc.db.framework.db.vo; + +import lombok.Data; + +/** + * 备份任务数据 + * + * @author diantu + * @since 2023年3月3日 + */ +@Data +public class BackupJobVO { + + /** + * 数据源ID + */ + private Integer dbId; + + /** + * 地址 + */ + private String host; + /** + * 端口号 + */ + private String port; + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + /** + * 数据库名 + */ + private String databaseName; + /** + * 数据库表名 + */ + private String[] tables; + /** + * 备份形式 + * 0-只备份表结构 + * 1-只备份表数据 + * 2-备份表结构+表数据 + */ + private Integer dataType; + /** + * 是否压缩 + */ + private Boolean isCompress = false; + /** + * 是否上传 + */ + private Boolean isUpload = false; + /** + * 是否删除 + */ + private Boolean isDelete = false; +} diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupRespVO.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupRespVO.java new file mode 100644 index 00000000..83de4519 --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/vo/BackupRespVO.java @@ -0,0 +1,23 @@ +package com.zyplayer.doc.db.framework.db.vo; + +import lombok.Data; + +import java.io.File; + +/** + * 备份响应数据 + * + * @author diantu + * @since 2023年3月3日 + */ +@Data +public class BackupRespVO { + + private String msg; + + private File file; + + public boolean isSuccess() { + return null != this.file && 0 < this.file.length(); + } +} diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/DatabaseBackupUtils.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/DatabaseBackupUtils.java index 4b0d67d3..3000431b 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/DatabaseBackupUtils.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/DatabaseBackupUtils.java @@ -1,7 +1,14 @@ package com.zyplayer.doc.db.framework.utils; +import cn.hutool.core.util.IdUtil; +import com.alibaba.excel.util.DateUtils; +import com.zyplayer.doc.data.repository.manage.entity.BackupLog; +import com.zyplayer.doc.data.utils.CleanInputCache; +import com.zyplayer.doc.db.framework.db.vo.BackupJobVO; +import com.zyplayer.doc.db.framework.db.vo.BackupRespVO; +import org.springframework.scheduling.annotation.Async; import java.io.*; -import java.time.LocalDate; +import java.util.Date; /** * 数据库备份恢复工具类 @@ -12,113 +19,211 @@ import java.time.LocalDate; public class DatabaseBackupUtils { /** - * MySQL数据库导出 - * - * @param hostIP MySQL数据库所在服务器地址IP - * @param userName 进入数据库所需要的用户名 - * @param password 进入数据库所需要的密码 - * @param savePath 数据库导出文件保存路径 - * @param fileName 数据库导出文件文件名 - * @param databaseName 要导出的数据库名 - * @return 返回true表示导出成功,否则返回false。 + * 项目路径 */ - public static boolean exportDatabaseForMysql(String mysqldumpPath, String hostIP, String userName, String password, String savePath, String fileName, String databaseName) throws InterruptedException { - File saveFile = new File(savePath); - if (!saveFile.exists()) {// 如果目录不存在 - saveFile.mkdirs();// 创建文件夹 - } - if(!savePath.endsWith(File.separator)){ - savePath = savePath + File.separator; - } + public static final String PROJECT_PATH = System.getProperty("user.dir"); - PrintWriter printWriter = null; - BufferedReader bufferedReader = null; - try { + /** + * 当前系统类型 + */ + public static final String OS_NAME = System.getProperty("os.name"); - printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(savePath + fileName), "utf8")); - Process process = Runtime.getRuntime().exec(" "+mysqldumpPath+"/mysqldump -h" + hostIP + " -u" + userName + " -p" + password + " " + databaseName); - InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8"); - bufferedReader = new BufferedReader(inputStreamReader); - String line; - while((line = bufferedReader.readLine())!= null){ - printWriter.println(line); - } - printWriter.flush(); - if(process.waitFor() == 0){//0 表示线程正常终止。 - return true; - } - }catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (bufferedReader != null) { - bufferedReader.close(); - } - if (printWriter != null) { - printWriter.close(); - } - } catch (IOException e) { - e.printStackTrace(); + /** + * 编码格式 + */ + public static final String CHAR_SET = OS_NAME.startsWith("Win") ? "GBK" : "UTF-8"; + + /** + * 异步执行备份任务,更新备份记录 + * + * @param jobVO 备份参数 + * @param backupLog 备份记录 + */ + @Async + public void saveBackUp(BackupJobVO jobVO, BackupLog backupLog) { + // 执行备份 + BackupRespVO respVO = doBackup(jobVO); + backupLog.setStatus(respVO.isSuccess() ? (jobVO.getIsUpload() ? 1 : 2) : -1); + backupLog.setMsg(respVO.getMsg()); + // 备份成功 + if (respVO.isSuccess()) { + // 文件相对路径 + backupLog.setFilePath(respVO.getFile().getPath().replace(PROJECT_PATH + File.separator, "")); + backupLog.setFileSize(respVO.getFile().length()); + } + // 备份失败 + if (!respVO.isSuccess()) { + if (null != respVO.getFile()) { + respVO.getFile().delete(); } } - return false; + // 计算耗时 + backupLog.setEndTime(new Date()); + backupLog.setSpendTime(backupLog.getEndTime().getTime() - backupLog.getStartTime().getTime()); + //@TODO 存入备份记录信息 + // 备份文件上传至文件服务器 + if (!jobVO.getIsUpload()) { + return; + } + //@TODO 备份文件上传至文件服务器 } - public static void backup(String savePath) { - File file = new File(savePath); - if (!file.exists()) { - file.mkdirs(); - } - String fileName = savePath + "/" + LocalDate.now() + ".sql"; - /** 默认使用linux*/ - //String cmdPrefix = "/bin/sh -c "; - String c1 = "/bin/sh"; - String c2 = "-c"; - String os_name = System.getProperty("os.name"); - // 判断是否是windows系统 - if (os_name.toLowerCase().startsWith("win")){ - //cmdPrefix = "cmd /c "; - c1 = "cmd"; - c2 = "/c"; - } - //参考示例:# /usr/local/mysql/bin/mysqldump -uroot -p123456 -P3306 shuju > shuju.sql - String cmd = "mysqldump" // mysqldump的绝对路径,配置环境变量,直接写mysqldump即可 - + " -h" + "127.0.0.1" // 数据库端口号 - + " -P" + "3306" // 数据库端口号 - + " -u" + "root" // 数据库用户名 - + " -p" + "root" // 数据库密码 - + " " + "zyplayer_doc_manage" // 数据库名 - + " > " + fileName; // 最终写入的文件路径 + /** + * 执行备份命令(mysql) + */ + public static BackupRespVO doBackup(BackupJobVO jobVO) { + // 返回对象 + BackupRespVO respVO = new BackupRespVO(); try { - System.out.println("第一个参数 " + c1); - System.out.println("第二个参数 " + c2); - System.out.println("具体命令 " + cmd); + // 当前年月日yyyyMMdd + String date = DateUtils.format(new Date(),"yyyyMMdd"); + // 文件目录 + String path = PROJECT_PATH + File.separator + "static" + File.separator + date + File.separator; + // 文件名 + String fileName = IdUtil.fastSimpleUUID() + ".sql" + (jobVO.getIsCompress() ? ".gz" : ""); + // 创建文件 + File file = new File(path, fileName); + // 路径不存在,则新建 + if (!file.getParentFile().exists()) { + boolean flag = file.getParentFile().mkdirs(); + if (!flag) { + respVO.setMsg("文件夹创建失败"); + return respVO; + } + } + respVO.setFile(file); + // shell 命令脚本 + String[] commands = createBackupCommandForMysql(jobVO, path, fileName); - //log.error("数据库备份START" + LocalDateTime.now()); - /** - * exec重载方法有一个参数的,window下执行正常,linux下无法完成备份。 - * 使用多参数重载方法都可以正常备份 - */ - Process process = Runtime.getRuntime().exec(new String[]{c1, c2, cmd}); - process.waitFor(); - //log.error("数据库备份END" + LocalDateTime.now()); + ProcessBuilder processBuilder = new ProcessBuilder(); + Process process = processBuilder.command(commands).start(); + //Process process = Runtime.getRuntime().exec(commands); + // 创建一个线程类来不停地来读出Process调用脚本的输出数据,防止缓冲区被缓冲数据塞满而线程阻塞 + new CleanInputCache(process.getInputStream(), "info", CHAR_SET, null).start(); + // 错误信息 + StringBuilder msg = new StringBuilder("【" + jobVO.getDatabaseName() + "】备份失败,原因:"); + new CleanInputCache(process.getErrorStream(), "error", CHAR_SET, msg).start(); + // 备份成功 + if (process.waitFor() == 0) { + respVO.setMsg("备份成功"); + } + // 备份失败 + else { + respVO.setMsg(msg.toString()); + } } catch (Exception e) { - e.printStackTrace(); - //log.error("数据库备份失败:{}", e.getMessage()); + respVO.setMsg("【" + jobVO.getDatabaseName() + "】备份失败,原因:" + e.getMessage()); } + return respVO; } + /** + * 创建命令头(只支持Windows平台和Linux平台) + */ + public static String[] createBaseCommand() { + // shell 命令 + String[] commands = new String[3]; + if (OS_NAME.startsWith("Win")) { + commands[0] = "cmd.exe"; + commands[1] = "/c"; + } else { + commands[0] = "/bin/sh"; + commands[1] = "-c"; + } + return commands; + } - public static void main(String[] args){ - try { - if (exportDatabaseForMysql("C:/Program Files/MySQL/MySQL Server 5.7/bin","127.0.0.1", "root", "root", "D:/backupDatabase", "2023-2-8.sql", "zyplayer_doc_manage")) { - System.out.println("数据库成功备份!!!"); - } else { - System.out.println("数据库备份失败!!!"); + /** + * 拼接备份命令(mysql) + * + * @param jobVO 备份参数 + * @param path 备份文件目录 + * @param fileName 备份文件名 + */ + public static String[] createBackupCommandForMysql(BackupJobVO jobVO, String path, String fileName) { + String[] commands = createBaseCommand(); + // 拼接命令 + StringBuilder mysqldump = new StringBuilder(); + //需配置mysql安装路径bin目录环境变量 + mysqldump.append("mysqldump"); + mysqldump.append(" --opt"); + + // 用户,密码 + mysqldump.append(" --user=").append(jobVO.getUsername()); + mysqldump.append(" --password=\"").append(jobVO.getPassword()).append("\""); + + // ip,端口 + mysqldump.append(" --host=").append(jobVO.getHost()); + mysqldump.append(" --port=").append(jobVO.getPort()); + + // 使用的连接协议,包括:tcp, socket, pipe, memory + mysqldump.append(" --protocol=tcp"); + + // 设置默认字符集,默认值为utf8 + mysqldump.append(" --default-character-set=utf8"); + // 在导出数据之前提交一个BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态 + mysqldump.append(" --single-transaction=TRUE"); + + // 导出存储过程以及自定义函数 + mysqldump.append(" --routines"); + // 导出事件 + mysqldump.append(" --events"); + + // 只备份表结构 + if (null != jobVO.getDataType()) { + if (0 == jobVO.getDataType()) { + mysqldump.append(" --no-data"); + } + // 只备份表数据 + else if (1 == jobVO.getDataType()) { + mysqldump.append(" --no-create-info"); } - } catch (InterruptedException e) { - e.printStackTrace(); } - //backup("D:/backupDatabase"); + + // 数据库名 + mysqldump.append(" ").append(jobVO.getDatabaseName()); + + // 数据表名 + if (null != jobVO.getTables() && 0 < jobVO.getTables().length) { + for (String item : jobVO.getTables()) { + mysqldump.append(" ").append(item); + } + } + + // 保存文件路径 + if (jobVO.getIsCompress()) { + // gzip压缩 + mysqldump.append(" | gzip"); + } + mysqldump.append(" > ").append(path).append(fileName); + + commands[2] = mysqldump.toString(); + return commands; } + + /** + * 拼接备份命令(oracle) + * @param jobVO 备份参数 + * @param path 备份文件目录 + * @param fileName 备份文件名 + */ + public static String[] createBackupCommandForOracle(BackupJobVO jobVO, String path, String fileName) { + + String[] commands = createBaseCommand(); + // 拼接命令 + StringBuilder oracledump = new StringBuilder(); + //需配置mysql安装路径bin目录环境变量 + oracledump.append("expdp "); + + // 用户,密码 + oracledump.append(jobVO.getUsername()); + oracledump.append("/").append(jobVO.getPassword()); + + //数据库名 + oracledump.append("@").append(jobVO.getDatabaseName()); + //@TODO 待完善 + + return commands; + } + } diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/QuartzManagerUtils.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/QuartzManagerUtils.java new file mode 100644 index 00000000..5a523a12 --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/QuartzManagerUtils.java @@ -0,0 +1,142 @@ +package com.zyplayer.doc.db.framework.utils; + +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +/** + * quartz工具类 + * + * @author diantu + * @since 2023年3月8日 + */ +@Slf4j +@Component +public class QuartzManagerUtils { + + /** + * 参数传递key + */ + public static final String PARAM_KEY = "params"; + + /** + * 执行任务类名 + */ + public static final String CLASS_NAME = "com.zyplayer.doc.db.framework.db.job.BackupJob"; + + /** + * 程序调度器 + */ + @Autowired + private Scheduler scheduler; + + + + + /** + * 添加定时任务 + */ + public void add(Integer id, String cronExpression, String param, Boolean status) { + try { + // 构建job信息 + JobDetail jobDetail = JobBuilder.newJob(getClass(CLASS_NAME).getClass()).withIdentity(getKey(id)).usingJobData(PARAM_KEY, param).build(); + // 表达式调度构建器(即任务执行的时间) + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getKey(id)).withSchedule(scheduleBuilder).build(); + // 创建定时任务 + scheduler.scheduleJob(jobDetail, trigger); + // 停止 + if (!status) { + stop(id); + } + } catch (Exception e) { + log.error("添加定时任务失败:{}", e.getMessage()); + } + } + + /** + * 编辑定时任务 + */ + public void update(Integer id, String cronExpression, String param, Boolean status) { + try { + // 判断是否存在,存在先删除 + if (scheduler.checkExists(JobKey.jobKey(getKey(id)))) { + scheduler.deleteJob(JobKey.jobKey(getKey(id))); + } + // 再创建 + add(id, cronExpression, param, status); + } catch (Exception e) { + log.error("修改定时任务失败:{}", e.getMessage()); + } + } + + /** + * 暂停任务 + */ + public void stop(Integer id) { + try { + scheduler.pauseJob(JobKey.jobKey(getKey(id))); + } catch (SchedulerException e) { + // 暂停定时任务失败 + log.error("暂停定时任务失败:{}", e.getMessage()); + } + } + + /** + * 恢复任务 + */ + public void start(Integer id) { + try { + scheduler.resumeJob(JobKey.jobKey(getKey(id))); + } catch (SchedulerException e) { + // 暂停定时任务失败 + log.error("启动定时任务失败:{}", e.getMessage()); + } + } + + /** + * 立即执行一次 + */ + public void run(Integer id) { + try { + scheduler.triggerJob(JobKey.jobKey(getKey(id))); + } catch (SchedulerException e) { + // 暂停定时任务失败 + log.error("执行定时任务失败:{}", e.getMessage()); + } + } + + /** + * 删除定时任务 + */ + public void delete(Integer id) { + try { + // 停止触发器 + scheduler.pauseTrigger(TriggerKey.triggerKey(getKey(id))); + // 移除触发器 + scheduler.unscheduleJob(TriggerKey.triggerKey(getKey(id))); + // 删除任务 + scheduler.deleteJob(JobKey.jobKey(getKey(id))); + } catch (Exception e) { + log.error("删除定时任务失败:{}", e.getMessage()); + } + } + + /** + * 根据类名获取类 + */ + private Job getClass(String className) throws Exception { + Class class1 = Class.forName(className); + return (Job) class1.newInstance(); + } + + /** + * 拼接key + */ + public String getKey(Integer id) { + return "dbBackUp-" + id; + } +} diff --git a/zyplayer-doc-manage/src/main/resources/sql/full/full.sql b/zyplayer-doc-manage/src/main/resources/sql/full/full.sql index d541b1eb..5c436b2d 100644 --- a/zyplayer-doc-manage/src/main/resources/sql/full/full.sql +++ b/zyplayer-doc-manage/src/main/resources/sql/full/full.sql @@ -405,6 +405,42 @@ CREATE TABLE `system_config` ( PRIMARY KEY (`id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='系统配置表'; +CREATE TABLE `backup_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID', + `dbId` bigint(20) NULL DEFAULT NULL COMMENT '数据源ID', + `category` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源(手动备份|自动备份)', + `database_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '库名', + `tables_name` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '表名', + `data_type` tinyint(1) NULL DEFAULT NULL COMMENT '备份方式', + `is_compress` tinyint(1) NULL DEFAULT NULL COMMENT '是否压缩', + `is_upload` tinyint(1) NULL DEFAULT NULL COMMENT '是否上传', + `is_delete` tinyint(1) NULL DEFAULT NULL COMMENT '是否删除', + `file_path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件路径', + `file_size` bigint(20) NULL DEFAULT NULL COMMENT '文件大小', + `status` tinyint(1) NULL DEFAULT NULL COMMENT '备份状态(-1-失败0-备份中1-上传中2-成功)', + `msg` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '返回信息', + `start_time` datetime(0) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(0) NULL DEFAULT NULL COMMENT '结束时间', + `spend_time` bigint(20) NULL DEFAULT NULL COMMENT '耗时(ms)', + `del_flag` tinyint(1) NULL DEFAULT NULL COMMENT '删除状态(0--未删除1--已删除)', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='备份记录表'; + +CREATE TABLE `backup_task` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '备份任务信息主键', + `dbId` bigint(20) NULL DEFAULT NULL COMMENT '数据源ID', + `cron` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'cron表达式', + `param` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '参数', + `status` tinyint(1) NULL DEFAULT NULL COMMENT '状态(0-停止1-启动)', + `database_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '库名', + `tables_name` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '表名', + `data_type` tinyint(1) NULL DEFAULT NULL COMMENT '备份方式', + `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `del_flag` tinyint(4) NULL DEFAULT NULL COMMENT '删除状态(0--未删除1--已删除)', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '备份任务信息'; + -- -------------------插入必要的数据------------------- -- 用户信息 INSERT INTO `user_info` (id, user_no, password, user_name, email, del_flag, creation_time, update_time, sex)