zoukankan      html  css  js  c++  java
  • SpringBoot+SpringCloud+vue+Element开发项目——数据备份还原

    一、新建工程

        新建jansens-backup工程,这是一个独立运行于admin的服务模块,可以分开独立部署

    二、添加依赖

        在pom.xml文件中添加web、swagger、common依赖包。

     <dependencies>
            <!-- spring boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- swagger -->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.9.2</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.9.2</version>
            </dependency>
            <dependency>
                <groupId>com.read</groupId>
                <artifactId>jansens-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>

    三、添加配置

    application.yml

    # tomcat
    server:
      port: 8002
    spring:
      application:
        name: jansens-backup
    # backup datasource
    jansens:
      backup:
        datasource:
          host: localhost
          userName: root
          password: 123456
          database: jansens

    四、自定义Banner文件

    在resources目录下添加一个自定义banner.txt文件

    ////////////////////////////////////////////////////////////////////  
    //                          _ooOoo_                               //  
    //                         o8888888o                              //  
    //                         88" . "88                              //  
    //                         (| ^_^ |)                              //  
    //                         O  =  /O                              //  
    //                      ____/`---'\____                           //  
    //                    .'  \|     |//  `.                         //  
    //                   /  \|||  :  |||//                          //  
    //                  /  _||||| -:- |||||-                         //  
    //                  |   | \  -  /// |   |                       //  
    //                  | \_|  ''---/''  |   |                       //  
    //                    .-\__  `-`  ___/-. /                       //  
    //                ___`. .'  /--.--  `. . ___                     //  
    //              ."" '<  `.___\_<|>_/___.'  >'"".                  //  
    //            | | :  `- \`.;` _ /`;.`/ - ` : | |                 //  
    //               `-.   \_ __ /__ _/   .-` /  /                 //  
    //      ========`-.____`-.___\_____/___.-`____.-'========         //  
    //                           `=---='                              //  
    //      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //  
    //            佛祖保佑       上海研发     永无BUG                     //
    ////////////////////////////////////////////////////////////////////

    五、修改启动类

    修改启动类为JansensBackupApplication,指定扫描路径为com.louis.jansens

    JansensBackupApplication.java

    @SpringBootApplication(scanBasePackages={"com.louis.jansens"})
    @EnableSwagger2
    public class JansensBackupApplication {
        public static void main(String[] args) {
            SpringApplication.run(JansensBackupApplication.class, args);
        }
    }

     六、跨域配置

    在config包添加跨域配置类

    CorsConfig.java

    @Configuration
    public class CorsConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")    // 允许跨域访问的路径
                    .allowedOrigins("*")    // 允许跨域访问的源
                    .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")    // 允许请求方法
                    .maxAge(168000)    // 预检间隔时间
                    .allowedHeaders("*")  // 允许头部设置
                    .allowCredentials(true);    // 是否发送cookie
        }
    }

    七、Swagger配置

    在config包添加swagger配置类

    SwaggerConfig.java

    /**
     * Swagger配置
     */
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2).select()
                    .apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();
        }
        
    }

     八、数据源属性

    BackupDataSourceProperties.java

    /**
     * 数据源
     */
    @Component  
    @ConfigurationProperties(prefix = "jansens.backup.datasource")
    public class BackupDataSourceProperties {
        
        private String host;
        private String userName;
        private String password;
        private String database;
        public String getHost() {
            return host;
        }
        public void setHost(String host) {
            this.host = host;
        }
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public String getDatabase() {
            return database;
        }
        public void setDatabase(String database) {
            this.database = database;
        }
        
    }  

    九、备份还原接口

    在service包下添加MysqlBackupService接口

    MysqlBackupService.java

    /**
     * MySql命令行备份恢复服务
     */
    public interface MysqlBackupService {
    
        /**
         * 备份数据库
         * @param host host地址,可以是本机也可以是远程
         * @param userName 数据库的用户名
         * @param password 数据库的密码
         * @param savePath 备份的路径
         * @param fileName 备份的文件名
         * @param databaseName 需要备份的数据库的名称
         * @return
         * @throws IOException 
         */
        boolean backup(String host, String userName, String password, String backupFolderPath, String fileName, String database) throws Exception;
    
        /**
         * 恢复数据库
         * @param restoreFilePath 数据库备份的脚本路径
         * @param host IP地址
         * @param database 数据库名称
         * @param userName 用户名
         * @param password 密码
         * @return
         */
        boolean restore(String restoreFilePath, String host, String userName, String password, String database) throws Exception;
    
    }

    十、备份还原实现

    在service.impl包下添加MysqlBackupServiceImpl实现类

    MysqlBackupServiceImpl.java

    @Service
    public class MysqlBackupServiceImpl implements MysqlBackupService {
    
        @Override
        public boolean backup(String host, String userName, String password, String backupFolderPath, String fileName,
                String database) throws Exception {
            return MySqlBackupRestoreUtils.backup(host, userName, password, backupFolderPath, fileName, database);
        }
    
        @Override
        public boolean restore(String restoreFilePath, String host, String userName, String password, String database)
                throws Exception {
            return MySqlBackupRestoreUtils.restore(restoreFilePath, host, userName, password, database);
        }
    
    }

    十一、备份还原逻辑

    在util包下创建一个备份还原工具类

    MySqlBackupRestoreUtils.java

    /**
     * MySQL备份还原工具类
     */
    public class MySqlBackupRestoreUtils {
    
        /**
         * 备份数据库
         * @param host host地址,可以是本机也可以是远程
         * @param userName 数据库的用户名
         * @param password 数据库的密码
         * @param savePath 备份的路径
         * @param fileName 备份的文件名
         * @param databaseName 需要备份的数据库的名称
         * @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;
            }
            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);
            try {
                Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
                if (process.waitFor() == 0) {
                    System.out.println("数据已从 " + restoreFilePath + " 导入到数据库中");
                }
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        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;
        }
    
        public static void main(String[] args) throws Exception {
            String host = "localhost";
            String userName = "root";
            String password = "123456";
            String database = "jansens";
            
            System.out.println("开始备份");
            String backupFolderPath = "d:/dev/";
            String fileName = "mdh";
            backup(host, userName, password, backupFolderPath, fileName, database);
            System.out.println("备份成功");
            
            /*System.out.println("开始还原");
            String restoreFilePath = "d:/dev/mdh.sql";
            restore(restoreFilePath, host, userName, password, database);
            System.out.println("还原成功");*/
    
        }
    
    }

    在util包HTTP结果封装类

    HttpResult.java

    /**
     * HTTP结果封装
     */
    public class HttpResult {
    
        private int code = 200;
        private String msg;
        private Object data;
        
        public static HttpResult error() {
            return error(500, "未知异常,请联系管理员");
        }
        
        public static HttpResult error(String msg) {
            return error(500, msg);
        }
        
        public static HttpResult error(int code, String msg) {
            HttpResult r = new HttpResult();
            r.setCode(code);
            r.setMsg(msg);
            return r;
        }
    
        public static HttpResult ok(String msg) {
            HttpResult r = new HttpResult();
            r.setMsg(msg);
            return r;
        }
        
        public static HttpResult ok(Object data) {
            HttpResult r = new HttpResult();
            r.setData(data);
            return r;
        }
        
        public static HttpResult ok() {
            return new HttpResult();
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public Object getData() {
            return data;
        }
    
        public void setData(Object data) {
            this.data = data;
        }
        
    }

    在constants包新建一个BackupConstants常量类

    /**
     * 常量类
     */
    public interface BackupConstants {
        
        /** 备份目录名称 */
        public static final String BACKUP_FOLDER_NAME = "_jansens_backup";
        /** 备份目录 */
        public static final String BACKUP_FOLDER = System.getProperty("user.home") + File.separator + BACKUP_FOLDER_NAME + File.separator;
        /** 还原目录,默认就是备份目录 */
        public static final String RESTORE_FOLDER = BACKUP_FOLDER;
        /** 日期格式 */
        public static final String DATE_FORMAT = "yyyy-MM-dd_HHmmss";
        /** SQL拓展名 */
        public static final String SQL_EXT = ".sql";
        /** 默认备份文件名 */
        public static final String BACKUP_FILE_NAME = "jansens" + SQL_EXT;
        /** 默认备份还原目录名称 */
        public static final String DEFAULT_BACKUP_NAME = "backup";
        /** 默认备份还原文件 */
        public static final String DEFAULT_RESTORE_FILE = BACKUP_FOLDER + DEFAULT_BACKUP_NAME + File.separator + BACKUP_FILE_NAME;
        
    }

    十二、备份还原控制器

    在controller包新建MySqlBackupController控制器

    MySqlBackupController.java

    /**
     * 系统数据备份还原
     */
    @RestController
    @RequestMapping("/backup")
    public class MySqlBackupController {
    
        @Autowired
        MysqlBackupService mysqlBackupService;
        @Autowired
        BackupDataSourceProperties properties;
    
        @GetMapping("/backup")
        public HttpResult backup() {
            String backupFodlerName = BackupConstants.DEFAULT_BACKUP_NAME + "_" + (new SimpleDateFormat(BackupConstants.DATE_FORMAT)).format(new Date());
            return backup(backupFodlerName);
        }
    
        private HttpResult backup(String backupFodlerName) {
            String host = properties.getHost();
            String userName = properties.getUserName();
            String password = properties.getPassword();
            String database = properties.getDatabase();
            String backupFolderPath = BackupConstants.BACKUP_FOLDER + backupFodlerName + File.separator;
            String fileName = BackupConstants.BACKUP_FILE_NAME;
            try {
                boolean success = mysqlBackupService.backup(host, userName, password, backupFolderPath, fileName, database);
                if(!success) {
                    HttpResult.error("数据备份失败");
                }
            } catch (Exception e) {
                return HttpResult.error(500, e.getMessage());
            }
            return HttpResult.ok();
        }
        
        @GetMapping("/restore")
        public HttpResult restore(@RequestParam String name) throws IOException {
            String host = properties.getHost();
            String userName = properties.getUserName();
            String password = properties.getPassword();
            String database = properties.getDatabase();
            String restoreFilePath = BackupConstants.RESTORE_FOLDER + name;
            try {
                mysqlBackupService.restore(restoreFilePath, host, userName, password, database);
            } catch (Exception e) {
                return HttpResult.error(500, e.getMessage());
            }
            return HttpResult.ok();
        }
        
        @GetMapping("/findRecords")
        public HttpResult findBackupRecords() {
            if(!new File(BackupConstants.DEFAULT_RESTORE_FILE).exists()) {
                // 初始默认备份文件
                backup(BackupConstants.DEFAULT_BACKUP_NAME);
            }
            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("name", file.getName());
                    backup.put("title", file.getName());
                    if(BackupConstants.DEFAULT_BACKUP_NAME.equalsIgnoreCase(file.getName())) {
                        backup.put("title", "系统默认备份");
                    }
                    backupRecords.add(backup);
                }
            }
            // 排序,默认备份最前,然后按时间戳排序,新备份在前面
            backupRecords.sort((o1, o2) -> BackupConstants.DEFAULT_BACKUP_NAME.equalsIgnoreCase(o1.get("name")) ? -1
                    : BackupConstants.DEFAULT_BACKUP_NAME.equalsIgnoreCase(o2.get("name")) ? 1 : o2.get("name").compareTo(o1.get("name")));
            return HttpResult.ok(backupRecords);
        }
        
        @GetMapping("/delete")
        public HttpResult deleteBackupRecord(@RequestParam String name) {
            if(BackupConstants.DEFAULT_BACKUP_NAME.equals(name)) {
                return HttpResult.error("系统默认备份无法删除!");
            }
            String restoreFilePath = BackupConstants.BACKUP_FOLDER + name;
            try {
                FileUtils.deleteFile(new File(restoreFilePath));
            } catch (Exception e) {
                return HttpResult.error(500, e.getMessage());
            }
            return HttpResult.ok();
        }
    
    }
  • 相关阅读:
    Dynamics AX 2012 R2 配置E-Mail模板
    Dynamics AX 2012 R2 设置E-Mail
    Dynamics AX 2012 R2 为运行失败的批处理任务设置预警
    Dynamics AX 2012 R2 耗尽用户
    Dynamics AX 2012 R2 创建一个专用的批处理服务器
    Dynamics AX 2012 R2 创建一个带有负载均衡的服务器集群
    Dynamics AX 2012 R2 安装额外的AOS
    Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录
    Dynamics AX 2012 R2 从代码中调用SSRS Report
    Dynamics AX 2012 R2 IIS WebSite Unauthorized 401
  • 原文地址:https://www.cnblogs.com/Jansens520/p/13335238.html
Copyright © 2011-2022 走看看