原始需求
项目中需要通过接口调用备份当前服务器下数据库的指定表,并且要兼容Windows和Linux的备份。而且还得支持MySQL和PostgreSQL的备份,原因是这几种情况我们的项目都可能会碰到,可能使用MySQL或者PostgreSQL,也可能部署Windows或者Linux
方案设计思路
- 经过考量我决定使用数据库自带的备份工具来备份指定的表数据:
● MySQL使用自带的mysqldump工具备份
● PostgreSQL使用自带的pg_dump工具备份 - 通过配置文件的数据库信息来获取需要备份的数据库信息
- 通过配置文件配置来获取需要备份的数据库信息
- 使用程序执行命令的方式来执行备份指令
- 下载备份成功的文件到客户机
实现逻辑
-
使用@ConfigurationProperties(prefix = “xxx.xx”)获取到相关的数据库信息
url: jdbc:postgresql://localhost:5432/acis username: admin password: admin driver-class-name: org.postgresql.Driver
通过数据库配置可以发现url包含了数据库的类型,我们可以通过jdbc后面的数据库标识来区分当前使用的是MySQL还是PostgreSQL,决定我们执行的备份命令
-
定义备份命令模板,供后期运行时装配
/** * -U表示用户 * <p> * -h表示主机 * <p> * -p表示端口号 * <p> * -t表示表名 * <p> * -f表示备份后的sql文件的名字 * <p> * -d表示要恢复数据库名称 * <p> * {5}数据库名称 */ private static final String PGSQL_BACK_COMMAND = "pg_dump -U {0} -h {1} -p {2} -t {3} -f {4} {5}"; /** * #导出命令 -u用户名 -p密码 -h主机IP地址 数据库名 表名1 > 导出文件.sql */ private static final String MYSQL_BACK_COMMAND = "mysqldump -u {0} -h {1} -P {2} {5} {3} > {4}";
-
执行备份命令,查找资料发现可以使用RunTime.getRuntime().exec()方法来执行备份指令
● 参考资料:https://www.jianshu.com/p/f3b8b4ad5bf8 -
区分Windows和Linux的方法
//Windows操作系统
if (os != null && os.toLowerCase().startsWith("windows")) {
command = new String[]{"cmd", "/c", backCommand};
} else if (os != null && os.toLowerCase().startsWith("linux")) {//Linux操作系统
command = new String[]{"/bin/bash", "-c", backCommand};
} else {
throw new BusinessException(ExceptionEnum.DATA_HANDLE_ERROR, "当前操作系统不支持备份");
}
- 注意事项
● 文件路径需要区分Windows和Linux,可以使用 File.separator 方法作为分隔符,可以自动适配
● 新版本的数据库备份命令都不支持直接在命令中填写数据库密码,因此我们使用将密码添加到环境变量的方式来执行命令,然后删除-p 密码指定参数就可以不需要密码备份数据库了。
环境变量设置方式:<