springboot備份mysql后發送郵件並刪除備份文件,支持win和Linux


首先加入springboot的郵箱依賴

<!--郵箱依賴-->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

 

郵件實體類

 1 package com.xiaostudy.shiro_test1.entity;
 2 
 3 import java.io.File;
 4 
 5 /**
 6  * Created with IntelliJ IDEA.
 7  * User: xiaostudy
 8  * Date: 2019/7/23
 9  * Time: 21:28
10  * Description: No Description
11  */
12 public class MailEntity {
13     /**
14      * 主題
15      */
16     private String subject;
17     /**
18      * 內容
19      */
20     private String content;
21     /**
22      * 郵箱
23      */
24     private String toAccount;
25     /**
26      * 附件
27      */
28     private File attachmentFile;
29     /**
30      * 附件文件名
31      */
32     private String attachmentFileName;
33 
34     public String getSubject() {
35         return subject;
36     }
37 
38     public void setSubject(String subject) {
39         this.subject = subject;
40     }
41 
42     public String getContent() {
43         return content;
44     }
45 
46     public void setContent(String content) {
47         this.content = content;
48     }
49 
50     public String getToAccount() {
51         return toAccount;
52     }
53 
54     public void setToAccount(String toAccount) {
55         this.toAccount = toAccount;
56     }
57 
58     public File getAttachmentFile() {
59         return attachmentFile;
60     }
61 
62     public void setAttachmentFile(File attachmentFile) {
63         this.attachmentFile = attachmentFile;
64     }
65 
66     public String getAttachmentFileName() {
67         return attachmentFileName;
68     }
69 
70     public void setAttachmentFileName(String attachmentFileName) {
71         this.attachmentFileName = attachmentFileName;
72     }
73 }

 

spring獲取bean工具類【不是service和controller層的不能注入bean】

  1 package com.xiaostudy.shiro_test1.utils;
  2 
  3 import org.springframework.beans.BeansException;
  4 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
  5 import org.springframework.context.ApplicationContext;
  6 import org.springframework.context.ApplicationContextAware;
  7 import org.springframework.stereotype.Component;
  8 
  9 import java.util.Map;
 10 
 11 /**
 12  * Spring Context 工具類:可以在其他地方通過靜態方法獲取Spring配置的Bean
 13  *
 14  */
 15 @Component
 16 public class SpringContextUtils implements ApplicationContextAware {
 17     private static ApplicationContext applicationContext;
 18 
 19     @Override
 20     public void setApplicationContext(ApplicationContext applicationContext)
 21             throws BeansException {
 22         if (SpringContextUtils.applicationContext == null) {
 23             SpringContextUtils.applicationContext = applicationContext;
 24         }
 25     }
 26 
 27     public static ApplicationContext getApplicationContext() {
 28         return applicationContext;
 29     }
 30 
 31     public static Object getBean(String name) {
 32         return applicationContext.getBean(name);
 33     }
 34 
 35     /**
 36      * 從靜態變量applicationContext中取得Bean, 自動轉型為所賦值對象的類型.
 37      */
 38     public static <T> T getBean(Class<T> requiredType) {
 39 //        assertContextInjected();
 40         if(null == applicationContext) {
 41             return null;
 42         }
 43         return applicationContext.getBean(requiredType);
 44     }
 45 
 46     /**
 47      * 從靜態變量applicationContext中取得Bean, 自動轉型為所賦值對象的類型.
 48      */
 49     public static <T> Map<String, T> getBeanOfMap(Class<T> requiredType) {
 50 //        assertContextInjected();
 51         if(null == applicationContext) {
 52             return null;
 53         }
 54         return applicationContext.getBeansOfType(requiredType);
 55     }
 56 
 57     /**
 58      * 檢查ApplicationContext不為空.
 59      */
 60     /*private static void assertContextInjected() {
 61         Validate.validState(applicationContext != null, "applicaitonContext屬性未注入, 請在applicationContext.xml中定義SpringContextHolder.");
 62     }*/
 63 
 64     /***
 65      * 類似於getBean(String name)只是在參數中提供了需要返回到的類型。
 66      *
 67      * @param name
 68      * @param requiredType
 69      * @return
 70      * @throws BeansException
 71      */
 72     public static <T> T getBean(String name, Class<T> requiredType) {
 73         return applicationContext.getBean(name, requiredType);
 74     }
 75 
 76     /**
 77      * 如果BeanFactory包含一個與所給名稱匹配的bean定義,則返回true
 78      *
 79      * @param name
 80      * @return boolean
 81      */
 82     public static boolean containsBean(String name) {
 83         return applicationContext.containsBean(name);
 84     }
 85 
 86     /**
 87      * 判斷以給定名字注冊的bean定義是一個singleton還是一個prototype。
 88      * 如果與給定名字相應的bean定義沒有被找到,將會拋出一個異常(NoSuchBeanDefinitionException)
 89      *
 90      * @param name
 91      * @return boolean
 92      * @throws NoSuchBeanDefinitionException
 93      */
 94     public static boolean isSingleton(String name) {
 95         return applicationContext.isSingleton(name);
 96     }
 97 
 98     public static Class<? extends Object> getType(String name) {
 99         return applicationContext.getType(name);
100     }
101 
102     /**
103      * 獲取Spring裝配的bean的名稱
104      */
105     public static String[] getBeanNameAll() {
106         return applicationContext.getBeanDefinitionNames();
107     }
108 
109     /***
110      * 類似於獲取同類型的BEAN
111      * @param <T>
112      * @param requiredType
113      * @return
114      * @throws BeansException
115      */
116     public static <T> Map<String, T> getBeansOfType(Class<T> requiredType) {
117         return applicationContext.getBeansOfType(requiredType);
118     }
119 }

 

發郵件工具類

 1 package com.xiaostudy.shiro_test1.utils;
 2 
 3 import com.xiaostudy.shiro_test1.entity.MailEntity;
 4 //import org.jasypt.encryption.StringEncryptor;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.autoconfigure.mail.MailProperties;
 7 import org.springframework.mail.SimpleMailMessage;
 8 import org.springframework.mail.javamail.JavaMailSender;
 9 import org.springframework.mail.javamail.MimeMessageHelper;
10 import org.springframework.stereotype.Component;
11 
12 import javax.mail.MessagingException;
13 import javax.mail.internet.MimeMessage;
14 
15 /**
16  * Created with IntelliJ IDEA.
17  * User: xiaostudy
18  * Date: 2019/7/23
19  * Time: 21:25
20  * Description: No Description
21  */
22 @Component
23 public class MailUtils {
24 
25     /**
26      * 發送郵件,里面有判斷是否發文件
27      */
28     public static void sendMail(MailEntity mailEntity) {
29         if(null != mailEntity) {
30             if(null != mailEntity.getAttachmentFile() && mailEntity.getAttachmentFile().exists()) {
31                 if(null == mailEntity.getAttachmentFileName()) {
32                     mailEntity.setAttachmentFileName(mailEntity.getAttachmentFile().getName());
33                 }
34                 sendMailAttachment(mailEntity);
35             } else {
36                 sendSimpleMail(mailEntity);
37             }
38         }
39     }
40 
41     /**
42      * 發送郵件,這里只發內容,不發文件
43      */
44     public static void sendSimpleMail(MailEntity mailEntity) {
45         SimpleMailMessage mimeMessage = new SimpleMailMessage();
46         mimeMessage.setFrom(SpringContextUtils.getBean(MailProperties.class).getUsername());
47         mimeMessage.setTo(mailEntity.getToAccount());
48         mimeMessage.setSubject(mailEntity.getSubject());
49         mimeMessage.setText(mailEntity.getContent());
50         SpringContextUtils.getBean(JavaMailSender.class).send(mimeMessage);
51     }
52 
53     /**
54      * 發送郵件-附件郵件
55      *
56      * @param mailEntity
57      */
58     public static boolean sendMailAttachment(MailEntity mailEntity) {
59         JavaMailSender javaMailSender = SpringContextUtils.getBean(JavaMailSender.class);
60         try {
61             MimeMessage mimeMessage = javaMailSender.createMimeMessage();
62             MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
63             helper.setFrom(SpringContextUtils.getBean(MailProperties.class).getUsername());
64             helper.setTo(mailEntity.getToAccount());
65             helper.setSubject(mailEntity.getSubject());
66             helper.setText(mailEntity.getContent(), true);
67             // 增加附件名稱和附件
68             helper.addAttachment(mailEntity.getAttachmentFileName(), mailEntity.getAttachmentFile());
69             javaMailSender.send(mimeMessage);
70             return true;
71         } catch (MessagingException e) {
72             e.printStackTrace();
73             return false;
74         }
75     }
76 }

 

 刪除備份文件線程類

 1 package com.xiaostudy.shiro_test1.thread;
 2 
 3 import com.xiaostudy.shiro_test1.entity.LoginLogEntity;
 4 import com.xiaostudy.shiro_test1.service.LoginLogService;
 5 import com.xiaostudy.shiro_test1.utils.DateUtils;
 6 import com.xiaostudy.shiro_test1.utils.IpUtil;
 7 import com.xiaostudy.shiro_test1.utils.MakeMD5;
 8 import com.xiaostudy.shiro_test1.utils.ShiroUtils;
 9 
10 import java.io.File;
11 
12 /**
13  * Created with IntelliJ IDEA.
14  * User: xiaostudy
15  * Date: 2019/7/22
16  * Time: 0:05
17  * Description: No Description
18  */
19 public class RemoveBackupSqlFileThread implements Runnable {
20 
21     private String filePath;
22     private Long start;
23 
24     public RemoveBackupSqlFileThread(String filePath) {
25         this.filePath = filePath;
26         this.start = System.currentTimeMillis();
27     }
28 
29     @Override
30     public void run() {
31         try {
32             // 前讓線程睡1分鍾,保證郵件已經發送
33             Thread.sleep(1000 * 60);
34         } catch (InterruptedException e) {
35             e.printStackTrace();
36         }
37         File file = new File(filePath);
38         // 30分鍾內,每1分鍾刪除備份文件,刪除文件就結束線程
39         while (System.currentTimeMillis() - this.start < 1000 * 60 * 30) {
40             if(null != file && file.exists() && file.isFile() && file.delete()) {
41                 break;
42             }
43             try {
44                 Thread.sleep(1000 * 60);
45             } catch (InterruptedException e) {
46                 e.printStackTrace();
47             }
48         }
49     }
50 }

 

1、在win下備份mysql並發送郵件

在spirng:后加,如下圖

mail:
    host: smtp.mxhichina.com      #阿里雲發送服務器地址
    port: 25                      #端口號
    username: 郵箱地址        #發送人地址
    password: 密碼  #密碼

配置my.ini【因為java運行備份mysql的命令,不能直接用密碼】

在最后添加

[client]
host=localhost
user=用戶名
password=密碼

 

這里說明一下這個my.ini文件,有些是在安裝mysql的目錄下,有些不是在安裝目錄下,可以用工具Everything搜一下

備份的命令是

"D:/Program Files/MySQL/MySQL Server 5.7/bin/mysqldump.exe" --defaults-extra-file="D:/ProgramData/MySQL/MySQL Server 5.7/my.ini" -B 數據庫名稱>C:/temp/20190725.sql

上面為什么要用雙引號呢,主要是文件夾名稱有空格,cmd識別不了,加雙引號就好了。

 

備份數據,發送郵件,刪除備份文件 

@GetMapping("backup")
@ResponseBody
public Map backup(){
    String thisDateTime = DateUtils.getDateTime("yyyyMMdd_HHmmss");
    String filePath;
    String shell;
    String[] cmd;
    // 通過獲取系統名稱是否包含windows來判斷是win還是Linux
    if(System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) {
        filePath = "C:/temp/myLog_" + thisDateTime + ".sql";
        shell = "\"D:/Program Files/MySQL/MySQL Server 5.7/bin/mysqldump.exe\" --defaults-extra-file=\"D:/ProgramData/MySQL/MySQL Server 5.7/my.ini\" -B my_log>" + filePath;
        // java運行cmd命令要多加cmd空格/c空格
        shell = "cmd /c " + shell;
    } else {
        filePath = "/home/backup/myLog_" + thisDateTime + ".sql";
        shell = "/usr/local/mysql/bin/mysqldump --defaults-extra-file=/usr/local/mysql/my.cnf -B my_log>" + filePath;
    }
    System.out.println("shell:" + shell);
    Runtime runTime = Runtime.getRuntime();
    if (runTime == null) {
        System.err.println("Create runtime false!");
    }
    try {
        if(System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) {
            runTime.exec(shell);
        } else {
            runTime.exec(new String[]{"/bin/sh", "-c", shell});
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    MailEntity mailEntity = new MailEntity();
    // 對方郵箱地址
    mailEntity.setToAccount("手機號@163.com");
    mailEntity.setSubject("備份mysql");
    mailEntity.setContent("備份mysql的my_log數據庫");
    File file = null;
    long thisTime = System.currentTimeMillis();
    // 這里是處理備份的sql文件是否寫入完成,這里是10秒
    while (System.currentTimeMillis() - thisTime < 10*1000) {
        file = new File(filePath);
        if(file.exists() && file.isFile()) {
            break;
        } else {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    mailEntity.setAttachmentFile(file);
    MailUtils.sendMail(mailEntity);
    // 刪除備份文件
    new Thread(new RemoveBackupSqlFileThread(filePath)).start();
    Map map = new HashMap();
    map.put("code", "0");
    map.put("msg", "已發送至郵箱");
    return map;
}

 

注:如果win備份mysql文件大小為0,那么可以考慮用new String[]{"cmd", "/c", shell}。參考下面Linux運行命令方法

2、Linux下備份mysql並發送郵件

配置my.cnf文件

vi my.cnf打開文件【按i進入編輯狀態,按Esc退出編輯,按:wq保存退出查看文件】

[client]
host=內網ip
user=用戶名
password=密碼

springboot的配置,阿里雲服務器封了25端口,要用465端口

 1 mail:
 2         default-encoding: UTF-8
 3         host: smtp.mxhichina.com      #阿里雲發送服務器地址
 4 #            port: 25                      #端口號
 5         username: 郵箱地址        #發送人地址
 6         password: 密碼   #密碼
 7         properties:
 8               mail:
 9                 smtp:
10                   starttls:
11                     enable: true
12                     required: true
13                   auth: true
14                   socketFactory:
15                     class: javax.net.ssl.SSLSocketFactory
16                     port: 465

 

備份數據,發送郵件,刪除備份文件

 1 @GetMapping("backup")
 2 @ResponseBody
 3 public Map backup(){
 4     String thisDateTime = DateUtils.getDateTime("yyyyMMdd_HHmmss");
 5     String filePath;
 6     String shell;
 7     // 通過獲取系統名稱是否包含windows來判斷是win還是Linux
 8     if(System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) {
 9         filePath = "C:/temp/myLog_" + thisDateTime + ".sql";
10         shell = "\"D:/Program Files/MySQL/MySQL Server 5.7/bin/mysqldump.exe\" --defaults-extra-file=\"D:/ProgramData/MySQL/MySQL Server 5.7/my.ini\" -B my_log>" + filePath;
11         shell = "cmd /c " + shell;
12     } else {
13         filePath = "/home/backup/myLog_" + thisDateTime + ".sql";
14         shell = "/usr/local/mysql/bin/mysqldump --defaults-extra-file=/usr/local/mysql/my.cnf -B my_log>" + filePath;
15     }
16     Runtime runTime = Runtime.getRuntime();
17     Map map = new HashMap();
18     if (null != runTime) {
19         try {
20             if(System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1) {
21                 runTime.exec(shell);
22             } else {
23                 // linux運行shell命令要加
24                 runTime.exec(new String[]{"/bin/sh", "-c", shell});
25             }
26         } catch (IOException e) {
27             e.printStackTrace();
28         }
29         MailEntity mailEntity = new MailEntity();
30         mailEntity.setToAccount("對方郵箱地址");
31         mailEntity.setSubject("備份mysql");
32         mailEntity.setContent("備份mysql的my_log數據庫");
33         File file = null;
34         long thisTime = System.currentTimeMillis();
35         while (System.currentTimeMillis() - thisTime < 10*1000) {
36             file = new File(filePath);
37             if(file.exists() && file.isFile()) {
38                 break;
39             } else {
40                 try {
41                     Thread.sleep(200);
42                 } catch (InterruptedException e) {
43                     e.printStackTrace();
44                 }
45             }
46         }
47         mailEntity.setAttachmentFile(file);
48         MailUtils.sendMail(mailEntity);
49         // 刪除備份文件
50         new Thread(new RemoveBackupSqlFileThread(filePath)).start();
51         map.put("code", "0");
52         map.put("msg", "已發送至郵箱");
53     } else {
54         map.put("code", "1");
55         map.put("msg", "獲取Runtime為null,不能運行命令");
56     }
57     return map;
58 }

 

后面測試定時備份數據和發送郵件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM