首先加入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并发送邮件

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_mysql

在spirng:后加,如下图

mail:
    host: smtp.mxhichina.com      #阿里云发送服务器地址
    port: 25                      #端口号
    username: 邮箱地址        #发送人地址
    password: 密码  #密码

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_Linux_02

配置my.ini【因为java运行备份mysql的命令,不能直接用密码】

在最后添加

[client]
host=localhost
user=用户名
password=密码

 

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_mysql_03

这里说明一下这个my.ini文件,有些是在安装mysql的目录下,有些不是在安装目录下,可以用工具Everything搜一下

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_Linux_04

备份的命令是

"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文件

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_MySQL_05

vi my.cnf打开文件【按i进入编辑状态,按Esc退出编辑,按:wq保存退出查看文件】

[client]
host=内网ip
user=用户名
password=密码

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_springboot_06

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

springboot备份mysql后发送邮件并删除备份文件,支持win和Linux_springboot_07

 

备份数据,发送邮件,删除备份文件

 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 }

 

后面测试定时备份数据和发送邮件