最近项目中有一个这样的需求,要求定时备份数据库。看了一些网上的资料,了解到主要思路是是使用java中的Runtime类的exec()方法,可以直接调用windows的cmd命令,参数就是Mysql的备份命令。
一、Runtime类
首先说说这个神奇的Runtime类,主要封装了Java程序的运行环境,每一个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与运行时环境相连,应用程序不能创建自己的Runtime实例,但可以通过getRuntime()方法获得与之关联的Runtime对象。
Runtime代表Java程序的运行时环境,可以访问JVM的相关信息,如处理器数量,内存信息。
1.1、常用API
addShutdownHook(Thread hook)
注册新的虚拟机来关闭挂钩。
availableProcessors()
向 Java 虚拟机返回可用处理器的数目。
exec(String command)
在单独的进程中执行指定的字符串命令。
exec(String[] cmdarray)
在单独的进程中执行指定命令和变量。
exec(String[] cmdarray, String[] envp)
在指定环境的独立进程中执行指定命令和变量。
exec(String[] cmdarray, String[] envp, File dir)
在指定环境和工作目录的独立进程中执行指定的命令和变量。
exec(String command, String[] envp)
在指定环境的单独进程中执行指定的字符串命令。
exec(String command, String[] envp, File dir)
在有指定环境和工作目录的独立进程中执行指定的字符串命令。
exit(int status)
通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。
freeMemory()
返回 Java 虚拟机中的空闲内存量。
gc()
运行垃圾回收器。
InputStream getLocalizedInputStream(InputStream in)
已过时。 从 JDK 1.1 开始,将本地编码字节流转换为 Unicode 字符流的首选方法是使用 InputStreamReader 和 BufferedReader 类。
OutputStream getLocalizedOutputStream(OutputStream out)
已过时。 从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 类。
getRuntime()
返回与当前 Java 应用程序相关的运行时对象。
halt(int status)
强行终止目前正在运行的 Java 虚拟机。
load(String filename)
加载作为动态库的指定文件名。
loadLibrary(String libname)
加载具有指定库名的动态库。
maxMemory()
返回 Java 虚拟机试图使用的最大内存量。
removeShutdownHook(Thread hook)
取消注册某个先前已注册的虚拟机关闭挂钩。
runFinalization()
运行挂起 finalization 的所有对象的终止方法。
runFinalizersOnExit(value)
已过时。 此方法本身具有不安全性。它可能对正在使用的对象调用终结方法,而其他线程正在操作这些对象,从而导致不正确的行为或死锁。
totalMemory()
返回 Java 虚拟机中的内存总量。
traceInstructions(on)
启用/禁用指令跟踪。
traceMethodCalls(on)
启用/禁用方法调用跟踪。
1.2、使用exec(String cmd)方法备份数据库
DatabaseTool类
package com.china_amss.base.tools; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import com.china_amss.base.thread.ErrorStreamThread; public class DatabaseTool { /** * 备份数据库 ,控制台执行命令格式 "mysql的bin目录/mysqldump --databases -h主机ip -P端口 -u用户名 -p密码 --default-character-set=字符集 数据库名 * @param mysqlPath mysql路径 * @param mysqlIp mysql主机ip * @param mysqlPort 端口 * @param userName 用户名 * @param password 密码 * @param charset 字符集 * @param database 数据库名 * @param resultFile 备份文件全路径 */ public static void backup(String mysqlPath, String mysqlIp, String mysqlPort, String userName, String password, String database, String resultFile) { InputStream in = null; InputStreamReader isr = null; BufferedReader br = null; FileOutputStream fout = null; OutputStreamWriter writer = null; try { Runtime rt = Runtime.getRuntime(); // 调用mysql的安装目录的命令 Process process = rt.exec("\"" + mysqlPath + File.separator + "mysqldump\" --databases -h" + mysqlIp
+ " -P" + mysqlPort + " -u" + userName + " -p" + password + " --add-drop-database --default-character-set=utf8 "+ database + " --result-file="+resultFile); // 设置导出编码为utf-8。这里必须是utf-8 in = process.getInputStream();// 控制台的输出信息作为输入流 ErrorStreamThread errStream = new ErrorStreamThread(process.getErrorStream()); //错误流另开线程,不然会阻塞 errStream.start(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(writer != null){ writer.close(); } if(fout != null){ fout.close(); } if(br != null){ br.close(); } if(isr != null){ isr.close(); } if(in != null){ in.close(); } } catch (IOException e) { e.printStackTrace(); } } }
ErrorStreamThread类:
package com.china_amss.base.thread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import com.china_amss.ktms.exception.KTMSException; public class ErrorStreamThread extends Thread { private InputStream input; // 控制台errorStream public ErrorStreamThread(InputStream input) { this.input = input; } @Override public void run() { InputStreamReader isr = null; BufferedReader buff = null; try { isr = new InputStreamReader(input); buff = new BufferedReader(isr); String line; while ((line = buff.readLine()) != null) { if (line.indexOf("Warning") != 0) { throw new Exception(line); } } } catch (Exception e) { throw new Exception("错误流线程方法异常", e); } finally { try { if (buff != null) { buff.close(); } if (isr != null) { isr.close(); } } catch (IOException e) { throw new Exception("错误流线程方法异常", e); } } } }
注意:此处因为要输出错误提示,所以要使用另外一条线程输出,不然会阻塞
注意:上面用到的命令参数可以去查看我的另一篇专门整理了Mysql备份命令参数的文章,链接在这Mysql备份命令参数详解