package com.ims.service.sys.impl;
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 java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ims.service.sys.DataBaseBS;
import com.ims.common.DateUtil;
import com.ims.common.FileUtil;
import com.ims.service.sys.BackupRestoreBS;
@Service("backupRestoreBS")
public class BackupRestoreBSImpl implements BackupRestoreBS{
private static Log logger = LogFactory.getLog(BackupRestoreBSImpl.class);
private static final String uploadPath = System.getProperty("webapp.root")+"uploadFile\\backupRestore\\";
@Autowired
public DataBaseBS dataBaseBS;
/**
* 备份单个数据库
* @param dbName 数据库名称
* @return 备份成功或者失败
*/
@Override
public boolean backup(String dbName){
InputStream in = null;
InputStreamReader inReader = null;
BufferedReader br = null;
OutputStreamWriter writer = null;
FileOutputStream fout = null;
try {
logger.info(dbName + "开始备份!");
// mysqldump的安装路径,支持带空格
String cmd = "\"\" \""+dataBaseBS.getInstallPath() +"bin\\mysqldump\" -hlocalhost -uroot -p123456 " + dbName;
// cmd命令在后台执行,没有命令窗口出现或者一闪而过的情况
Process process = Runtime.getRuntime().exec("cmd /c start /b " + cmd);
// 把进程执行中的控制台输出信息写入.sql文件,即生成了备份文件。
// 注:如果不对控制台信息进行读出,则会导致进程堵塞无法运行
in = process.getInputStream();// 控制台的输出信息作为输入流
inReader = new InputStreamReader(in, "utf8");// 设置输出流编码为utf8。这里必须是utf8,否则从流中读入的是乱码
String inStr;
StringBuffer sb = new StringBuffer("");
String outStr;
// 组合控制台输出信息字符串
br = new BufferedReader(inReader);
while ((inStr = br.readLine()) != null) {
sb.append(inStr + "\r\n");
}
outStr = sb.toString();
// 要用来做导入用的sql目标文件:
fout = new FileOutputStream(uploadPath + dbName + ".sql");
writer = new OutputStreamWriter(fout, "utf8");
writer.write(outStr);
// 注:这里如果用缓冲方式写入文件的话,会导致中文乱码,用flush()方法则可以避免
writer.flush();
} catch (Exception e) {
logger.error(dbName + "备份失败!",e);
return false;
} finally{
// 别忘记关闭输入输出流
try {
in.close();
inReader.close();
br.close();
writer.close();
fout.close();
} catch (Exception e) {
logger.error(dbName + "备份失败!",e);
return false;
}
}
logger.info(dbName + "备份成功!");
return true;
}
/**
* 备份所有的数据库
*/
@Override
public Map<String, Object> backupAll(){
Map<String, Object> result = new HashMap<String, Object>();
String[] dataBases = dataBaseBS.getDataBases();
if(FileUtil.deleteAll(uploadPath)){
File[] srcfile = new File[dataBases.length];
for(int i=0;i<dataBases.length;i++){
if(backup(dataBases[i])){
srcfile[i] = new File(uploadPath+dataBases[i]+".sql");
}else{
result.put("status", false);
result.put("msg", dataBases[i] + "数据备份失败");
return result;
}
}
String filename = DateUtil.getCurrDate() + "_backup.zip";
File zipfile = new File(uploadPath + filename);
if(FileUtil.zip(srcfile, zipfile)){
result.put("status", true);
result.put("msg", filename);
}else{
result.put("status", false);
result.put("msg", "文件压缩失败");
}
}else{
result.put("status", false);
result.put("msg", "文件夹清空失败");
}
return result;
}
/**
* 还原单个数据库
* @param dbName 数据库名称
* @return 还原成功或者失败
*/
@Override
public boolean restore(String dbName){
OutputStream out = null;
BufferedReader br = null;
OutputStreamWriter writer = null;
try {
logger.info(dbName + "开始还原!");
// mysql的安装路径,支持带空格
String cmd = "\"\" \""+dataBaseBS.getInstallPath() +"bin\\mysql\" -hlocalhost -uroot -p123456 " + dbName;
// cmd命令在后台执行,没有命令窗口出现或者一闪而过的情况
Process process = Runtime.getRuntime().exec("cmd /c start /b " + cmd);
out = process.getOutputStream();//控制台的输入信息作为输出流
String inStr;
StringBuffer sb = new StringBuffer("");
String outStr;
br = new BufferedReader(new InputStreamReader(
new FileInputStream(uploadPath + dbName + ".sql"), "utf8"));
while ((inStr = br.readLine()) != null) {
sb.append(inStr + "\r\n");
}
outStr = sb.toString();
writer = new OutputStreamWriter(out, "utf8");
writer.write(outStr);
// 注:这里如果用缓冲方式写入文件的话,会导致中文乱码,用flush()方法则可以避免
writer.flush();
} catch (Exception e) {
logger.error(dbName + "还原失败!",e);
return false;
} finally {
// 别忘记关闭输入输出流
try {
out.close();
br.close();
writer.close();
} catch (IOException e) {
logger.error(dbName + "还原失败!",e);
return false;
}
}
logger.info(dbName + "还原成功!");
return true;
}
/**
* 还原所有的数据库
*/
@Override
public Map<String, Object> restoreAll(String zipFile){
Map<String, Object> result = new HashMap<String, Object>();
String[] dataBases = dataBaseBS.getDataBases();
if(zipFile.length()>0&&checkFile(zipFile)){
if(FileUtil.unZip(new File(uploadPath+zipFile), uploadPath)){
for(int i=0;i<dataBases.length;i++){
if(!restore(dataBases[i])){
result.put("status", false);
result.put("msg", dataBases[i] + "数据还原失败");
return result;
}
}
System.gc();// 强制回收内存垃圾,否则zip文件一直被占用删除不了
result.put("status", true);
result.put("msg", "数据还原成功");
}else{
result.put("status", false);
result.put("msg", "解压缩包失败");
}
}else{
result.put("status", false);
result.put("msg", "没有找到可还原的数据压缩文件");
}
return result;
}
/**
* 根据文件名验证文件是否合法
* @param fileName
* @return
*/
public boolean checkFile(String fileName){
String[] strs = fileName.split("_");
if(strs.length>1){
String checkStr = strs[strs.length-1];
if("backup.zip".equals(checkStr)){
return true;
}else{
return false;
}
}else{
return false;
}
}
@Override
public String getUploadpath() {
return uploadPath;
}
}
java实现mysql的备份和还原
最新推荐文章于 2022-11-19 17:58:09 发布