Vue springboot 备份数据库

后端 Springboot

Controller

@RestController
@RequestMapping("api")
public class BackupController {
	
    @Autowired
    private BackupService backupService;
	// 获取备份记录
    @GetMapping(value = "/backup/backup")
    public ResponseEntity getBackup(){
        return new ResponseEntity(backupService.queryBackup(),HttpStatus.OK);
    }
	// 备份
    @PostMapping(value = "/backup/backup")
    public ResponseEntity backup(@Validated @RequestBody String name){
        backupService.backup(name);
        return new ResponseEntity(HttpStatus.CREATED);
    }
	// 还原
    @PutMapping(value = "/backup/restore")
    public ResponseEntity restore(@Validated @RequestBody String name){
        backupService.restore(name);
        return new ResponseEntity(HttpStatus.OK);
    }
	// 删除备份记录
    @DeleteMapping(value = "/backup/del")
    public ResponseEntity delBackup(@Validated @RequestBody String name){
        backupService.delBackup(name);
        return new ResponseEntity(HttpStatus.OK);
    }
}

BackupService

public interface BackupService {
    List<Map<String, String>> queryBackup();
    void backup(String name);
    void restore(String name);
    void delBackup(String name);
}

BackupServiceImpl

功能实现代码如下,BackupConstants为常量接口,此外还需要FileUtilsMySqlBackupRestoreUtils用于文件操作(删除备份的sql文件)、数据库sql语句执行(备份和还原)

public class BackupServiceImpl implements BackupService {
    @Override
    public List<Map<String, String>> queryBackup(){
        List<Map<String, String>> backupRecords = new ArrayList<>();
        File restoreFolderFile = new File(BackupConstants.RESTORE_FOLDER);
        if(restoreFolderFile.exists()) {
            for(File file:restoreFolderFile.listFiles()) {
                Map<String, String> backup = new HashMap<>();
                backup.put("title", file.getName());
                backupRecords.add(backup);
            }
        }
        // 按时间戳排序,新备份在前面
        backupRecords.sort((o1, o2) -> o2.get("title").compareTo(o1.get("title")));
        return backupRecords;
    }

    @Override
    public void backup(String name){
        String host = BackupConstants.HOST;
        String userName = BackupConstants.USER_NAME;
        String password = BackupConstants.PASSWORD;
        String database = BackupConstants.DATABASE;
        String backupFolderPath = BackupConstants.BACKUP_FOLDER + name + File.separator;
        String fileName = name;
        try {
            boolean success = MySqlBackupRestoreUtils.backup(host, userName, password, backupFolderPath, fileName, database);
            if(!success) {
                System.out.println("数据备份失败");
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    @Override
    public void restore(String name){
        String host = BackupConstants.HOST;
        String userName = BackupConstants.USER_NAME;
        String password = BackupConstants.PASSWORD;
        String database = BackupConstants.DATABASE;
        String restoreFilePath = BackupConstants.RESTORE_FOLDER + name;
        try {
            MySqlBackupRestoreUtils.restore(restoreFilePath, host, userName, password, database);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    @Override
    public void delBackup(String name){
        String restoreFilePath = BackupConstants.BACKUP_FOLDER + name;
        try {
            FileUtils.deleteFile(new File(restoreFilePath));
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

BackupConstants

用于存储一些常量

public interface BackupConstants {
    /** 备份目录名称 */
    public static final String BACKUP_FOLDER_NAME = "_backup";
    /** 备份目录 */
    public static final String BACKUP_FOLDER = Constants.FOLDER_NAME + BACKUP_FOLDER_NAME + File.separator;
    /** 还原目录,默认就是备份目录 */
    public static final String RESTORE_FOLDER = BACKUP_FOLDER;
    /** SQL拓展名 */
    public static final String SQL_EXT = ".sql";

    /** 目标备份数据库信息 */
    public static final String HOST = "127.0.0.1";
    public static final String USER_NAME = "root";
    public static final String PASSWORD = "123456";
    public static final String DATABASE = "database";
}

FileUtils

public class FileUtils {
    /**
     * 递归删除文件
     * @param file
     */
    public static void deleteFile(File file) {
        // 判断是否是一个目录, 不是的话跳过, 直接删除; 如果是一个目录, 先将其内容清空.
        if(file.isDirectory()) {
            // 获取子文件/目录
            File[] subFiles = file.listFiles();
            // 遍历该目录
            for (File subFile : subFiles) {
                // 递归调用删除该文件: 如果这是一个空目录或文件, 一次递归就可删除.
                // 如果这是一个非空目录, 多次递归清空其内容后再删除
                deleteFile(subFile);
            }
        }
        // 删除空目录或文件
        file.delete();
    }
}

MySqlBackupRestoreUtils

/**
 * MySQL备份还原工具类
 * @author Louis
 * @date Sep 21, 2018
 */
public class MySqlBackupRestoreUtils {

    /**
     * 备份数据库
     * @param host host地址,可以是本机也可以是远程
     * @param userName 数据库的用户名
     * @param password 数据库的密码
     * @param backupFolderPath 备份的路径
     * @param fileName 备份的文件名
     * @param database 需要备份的数据库的名称
     * @return
     * @throws IOException
     */
    public static boolean backup(String host, String userName, String password, String backupFolderPath, String fileName,
                                 String database) throws Exception {
        File backupFolderFile = new File(backupFolderPath);
        if (!backupFolderFile.exists()) {
            // 如果目录不存在则创建
            backupFolderFile.mkdirs();
        }
        if (!backupFolderPath.endsWith(File.separator) && !backupFolderPath.endsWith("/")) {
            backupFolderPath = backupFolderPath + File.separator;
        }
        // 拼接命令行的命令
        String backupFilePath = backupFolderPath + fileName;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("mysqldump --opt").append(" --add-drop-database").append(" --add-drop-table");
        stringBuilder.append(" -h").append(host).append(" -u").append(userName).append(" -p").append(password);
        stringBuilder.append(" --result-file=").append(backupFilePath).append(".sql").append(" --default-character-set=utf8 ").append(database);
        System.out.println(stringBuilder.toString());
        // 调用外部执行 exe 文件的 Java API
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        if (process.waitFor() == 0) {
            // 0 表示线程正常终止
            System.out.println("数据已经备份到 " + backupFilePath + " 文件中");
            return true;
        }
        System.out.println(process.getInputStream());
        System.out.println(process.getErrorStream());

        System.out.println(process.exitValue());
        byte[] bytes = new byte[process.getInputStream().available()];
        process.getInputStream().read(bytes);
        System.out.println(new String(bytes));
        process.getErrorStream().read(bytes);
        System.out.println(new String(bytes));
        return false;
    }

    /**
     * 还原数据库
     * @param restoreFilePath 数据库备份的脚本路径
     * @param host IP地址
     * @param database 数据库名称
     * @param userName 用户名
     * @param password 密码
     * @return
     */
    public static boolean restore(String restoreFilePath, String host, String userName, String password, String database)
            throws Exception {
        File restoreFile = new File(restoreFilePath);
        if (restoreFile.isDirectory()) {
            for (File file : restoreFile.listFiles()) {
                if (file.exists() && file.getPath().endsWith(".sql")) {
                    restoreFilePath = file.getAbsolutePath();
                    break;
                }
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("mysql -h").append(host).append(" -u").append(userName).append(" -p").append(password);
        stringBuilder.append(" ").append(database).append(" < ").append(restoreFilePath);
        System.out.println(stringBuilder.toString());
        try {
            Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
            if (process.waitFor() == 0) {
                System.out.println("数据已从 " + restoreFilePath + " 导入到数据库中");
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        System.out.println("数据从 " + restoreFilePath + " 导入到数据库失败");
        return false;
    }

    private static String[] getCommand(String command) {
        String os = System.getProperty("os.name");
        String shell = "/bin/bash";
        String c = "-c";
        if(os.toLowerCase().startsWith("win")){
            shell = "cmd";
            c = "/c";
        }
        String[] cmd = { shell, c, command };
        return cmd;
    }
}

前端VUE

backup.vue

<script>
// 封装好的axios请求
import { getbackup, delbackup } from '@/api/backup'
export default {
  data() {
    return {
      // 略
    }
  },
  created() {
    this.$nextTick(() => {
      this.init()
    })
  },
  methods: {
    // 获取备份记录
    async init() {
      return new Promise((resolve, reject) => {
        this.loading = true
        getbackup().then(res => {
          this.tableData = res
          this.loading = false
          resolve(res)
        }).catch(err => {
          this.loading = false
          reject(err)
        })
      })
    },
    // 删除备份
    subDelete(title) {
      this.delLoading = true
      delbackup(title).then(res => {
        this.delLoading = false
        this.$refs[title].doClose()
        this.init()
        this.$notify({
          title: '删除成功',
          type: 'success',
          duration: 2500
        })
      }).catch(err => {
        this.delLoading = false
        this.init()
        console.log(err.response.data.message)
      })
    },
    // 备份
    backup() {
      this.isBackup = true
      this.timeFormat()
      const _this = this.$refs.form
      _this.form = { title: this.nowTime }
      _this.dialog = true
    },
    // 还原
    restore(data) {
      this.isBackup = false
      const _this = this.$refs.form
      _this.form = { title: data.title }
      _this.dialog = true
    },
    timeFormat() {
      const timeStamp = new Date().getTime()
      const year = new Date(timeStamp).getFullYear()
      const month = new Date(timeStamp).getMonth() + 1 < 10 ? '0' + (new Date(timeStamp).getMonth() + 1) : new Date(timeStamp).getMonth() + 1
      const date = new Date(timeStamp).getDate() < 10 ? '0' + new Date(timeStamp).getDate() : new Date(timeStamp).getDate()
      const hh = new Date(timeStamp).getHours() < 10 ? '0' + new Date(timeStamp).getHours() : new Date(timeStamp).getHours()
      const mm = new Date(timeStamp).getMinutes() < 10 ? '0' + new Date(timeStamp).getMinutes() : new Date(timeStamp).getMinutes()
      const ss = new Date(timeStamp).getSeconds() < 10 ? '0' + new Date(timeStamp).getSeconds() : new Date(timeStamp).getSeconds()
      this.nowTime = year + '-' + month + '-' + date + '_' + hh + mm + ss
    }
  }
}
</script>
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值