JSch和邮件插件
添加到项目pom文件中。Maven
com.jcraft
jsch
0.1.55
org.springframework.boot
spring-boot-starter-mail
#数据库备份配置
dbBackups:
windowsDir: E:\test\ #windows本机得备份目录
linuxDir: projectFiles/dbFile #linux本机得备份目录
linuxServe: #要传输得服务器信息
user: xxx
host: xxx
password: xxx
remoteDir: /home/ubuntu/20231127 #需要给权限测试直接给了 777
spring:
#邮件发送
mail:
host: smtp.qq.com #发送邮件服务器
username: [email protected] #QQ邮箱
password: xxxxxxxxx #客户端授权码
protocol: smtp #发送邮件协议
default-encoding: utf-8
from: [email protected] #与上面的username保持一致
properties:
mail:
smtp:
auth: true
port: 587 #端口号465或587
display:
sendmail: Javen #可以任意
sendname: Spring Boot Guide Email #可以任意
starttls:
enable: true
required: true
ssl:
enable: true
4、定时任务
import com.jcraft.jsch.*;
import com.jcraft.jsch.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import javax.mail.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 数据库备份
* 支持几个常用的特殊符号:
* *:表示任何时间触发任务
* ,:表示指定的时间触发任务
* -:表示一段时间内触发任务
* /:表示从哪一个时刻开始,每隔多长时间触发一次任务。
* ?:表示用于月中的天和周中的天两个子表达式,表示不指定值。
*
* cron表达式参数具体含义:
* 秒,取值范围:0-59,支持*、,、-、/。
* 分,取值范围:0-59,支持*、,、-、/。
* 时,取值范围:0-23,支持*、,、-、/。
* 日期,取值范围:1-31,支持*、,、-、/。比秒多了?,表示如果指定的星期触发了,则配置的日期变成无效。
* 月,取值范围:1-12,支持*、,、-、/。
* 星期,取值范围:1~7,1代表星期天,6代表星期六,其他的以此类推。支持*、,、-、/、?。比秒多了?,表示如果指定的日期触发了,则配置的星期变成无效。
*
* 常见cron表达式使用举例:
* 0 0 0 1 * ? 每月1号零点执行
* 0 0 2 * * ? 每天凌晨2点执行
* 0 0 2 * * ? 每天凌晨2点执行
* 0 0/5 11 * * ? 每天11点-11点55分,每隔5分钟执行一次
* 0 0 18 ? * WED 每周三下午6点执行
*/
@Configuration //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling // 2.开启定时任务
public class DBBackupsTask {
//读取yml配置
@Autowired
private Environment environment;
//邮件服务
@Autowired
public EmailSendImpl emailSendImpl;
//备份数据库并发送到邮箱
@Scheduled(cron = "0/10 * * * * ?")
private void dbEmailTask() {
System.out.println("执行静态定时任务备份数据库开始时间: " + LocalDateTime.now());
//通过util下的Date包实现
Date date = new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMddhhmmss");
String format = dateFormat.format(date);
String backupFileName = "backup_file_"+format + ".sql";
try {
String command = "";
String fileDir = "";
if(ZipUtils.isWindows()){
fileDir = environment.getProperty("dbBackups.windowsDir"); // E:\test\ 文件备份位置 这里配置文件读取了
command = "cmd /c mysqldump -uroot -p123456 forum_cs > " + fileDir + backupFileName;
}else{
fileDir = environment.getProperty("dbBackups.linuxDir"); // projectFiles/dbFile 文件备份位置 这里配置文件读取了
command = "mysqldump -uroot -p123456 forum_cs > " + fileDir + backupFileName;
}
Process process = Runtime.getRuntime().exec(command);
// 等待命令执行完成
int exitCode = process.waitFor();
if(exitCode != 0){
System.err.println("备份数据库失败时间: exitCode="+ exitCode +" - "+ LocalDateTime.now());
}
//成功则将数据压缩并发送给管理员邮箱
String to = "[email protected]";
String subject = "邮件通知";
String content = "数据库备份成功! 备份时间:" + format;
// 读取备份文件并压缩
String filePath = fileDir + backupFileName ;
String zipFilePath = fileDir;
String fileName = "backup_file_" + format ;
ZipUtils.fileToZip(filePath,zipFilePath,fileName);
emailSendImpl.sendAttachmentsMail(to,subject,content,zipFilePath+fileName+".zip");
System.out.println("执行静态定时任务备份数据库结束时间: " + LocalDateTime.now());
} catch (IOException | InterruptedException | MessagingException e) {
e.printStackTrace();
}
}
//备份数据库并发送到指定的服务器地址 测试每十秒
@Scheduled(cron = "0/10 * * * * ?")
private void dbServerTask() {
System.out.println("执行静态定时任务备份数据库开始时间: " + LocalDateTime.now());
//通过util下的Date包实现
Date date = new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMddhhmmss");
String format = dateFormat.format(date);
String backupFileName = "backup_file_"+format + ".sql";
try {
String command = "";
String fileDir = "";
if(ZipUtils.isWindows()){
fileDir = environment.getProperty("dbBackups.windowsDir"); // 文件备份位置 这里配置文件读取了
command = "cmd /c mysqldump -uroot -p123456 forum_cs > " + fileDir + backupFileName;
}else{
fileDir = environment.getProperty("dbBackups.linuxDir"); // 文件备份位置 这里配置文件读取了
command = "mysqldump -uroot -p123456 forum_cs > " + fileDir + backupFileName;
}
Process process = Runtime.getRuntime().exec(command);
// 等待命令执行完成
int exitCode = process.waitFor();
if(exitCode != 0){
System.err.println("备份数据库失败时间: exitCode="+ exitCode +" - "+ LocalDateTime.now());
}
// 读取备份文件并压缩
String filePath = fileDir + backupFileName ;
String zipFilePath = fileDir;
String fileName = "backup_file_" + format ;
ZipUtils.fileToZip(filePath,zipFilePath,fileName);
//向指定服务器发送文件备份
this.fileTransfer(zipFilePath + fileName + ".zip" );
System.out.println("执行静态定时任务备份数据库结束时间: " + LocalDateTime.now());
} catch (IOException | InterruptedException | JSchException e) {
e.printStackTrace();
}
}
/**
* 向指定服务器发送文件备份
* @throws IOException
* @throws JSchException
*/
public void fileTransfer(String localFile) throws IOException, JSchException {
String user = environment.getProperty("dbBackups.linuxServe.user"); //"ubuntu"; // 你的Linux用户名
String host = environment.getProperty("dbBackups.linuxServe.host"); //"192.168.137.155"; // 你的Linux服务器主机名或IP
int port = 22; // SSH运行的端口
String password = environment.getProperty("dbBackups.linuxServe.password"); //"ubuntu"; // 你的Linux密码
String remoteDir = environment.getProperty("dbBackups.linuxServe.remoteDir"); //"/home/ubuntu/20231127"; // 你在Linux服务器上的远程目录路径 需要给权限
JSch jsch = new JSch();
Session session = null;
try {
// 建立SSH会话
session = jsch.getSession(user, host, port);
// 连接认证
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
// 打开一个SFTP通道
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
// 进行文件传输
sftp.put(new FileInputStream(localFile), remoteDir + "/" + localFile.substring(localFile.lastIndexOf("\\") + 1));
// 关闭连接
channel.disconnect();
session.disconnect();
} catch (JSchException | SftpException | IOException e) {
e.printStackTrace();
}
}
}
import javax.mail.MessagingException;
public interface EmailSend {
/**
* 发送文本邮件
* @param to
* @param subject
* @param content
*/
public void sendSimpleMail(String to, String subject, String content);
public void sendSimpleMail(String to, String subject, String content, String... cc);
/**
* 发送HTML邮件
* @param to
* @param subject
* @param content
* @throws MessagingException
*/
public void sendHtmlMail(String to, String subject, String content) throws MessagingException;
public void sendHtmlMail(String to, String subject, String content, String... cc);
/**
* 发送带附件的邮件
* @param to
* @param subject
* @param content
* @param filePath
* @throws MessagingException
*/
public void sendAttachmentsMail(String to, String subject, String content, String filePath) throws MessagingException;
public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc);
/**
* 发送正文中有静态资源的邮件
* @param to
* @param subject
* @param content
* @param rscPath
* @param rscId
* @throws MessagingException
*/
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId) throws MessagingException;
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc);
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import java.io.File;
@Component
public class EmailSendImpl implements EmailSend {
@Autowired
public JavaMailSender mailSender;
@Value("${spring.mail.from}")
public String from;
/**
* 发送文本邮件
*
* @param to
* @param subject
* @param content
*/
@Override
public void sendSimpleMail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
@Override
public void sendSimpleMail(String to, String subject, String content, String... cc) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setCc(cc);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
/**
* 发送HTML邮件
* @param to
* @param subject
* @param content
*/
@Override
public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
//true表示需要创建一个multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(message);
}
/**
* 获取邮件的正文
* @return
*/
public String getContent(Integer number){
String str = "\n"
+ " \n" + "";
return str;
}
@Override
public void sendHtmlMail(String to, String subject, String content, String... cc) {
}
/**
* 发送带附件的邮件
* @param to
* @param subject
* @param content
* @param filePath
*/
public void sendAttachmentsMail(String to, String subject, String content, String filePath) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
FileSystemResource file = new FileSystemResource(new File(filePath));
String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
helper.addAttachment(fileName, file);
mailSender.send(message);
}
@Override
public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) {
}
/**
* 发送正文中有静态资源(图片)的邮件
*
* @param to
* @param subject
* @param content
* @param rscPath
* @param rscId
*/
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
FileSystemResource res = new FileSystemResource(new File(rscPath));
helper.addInline(rscId, res);
mailSender.send(message);
}
@Override
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) {
}
}
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* zip工具类
*
* @author cdj
* @date 2018年8月24日 上午10:03:15
*/
@Component
public class ZipUtils {
/**
* 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下
*
* @param sourceFilePath
* :待压缩的文件路径
* @param zipFilePath
* :压缩后存放路径
* @param fileName
* :压缩后文件的名称
* @return
*/
public static boolean folderToZip(String sourceFilePath, String zipFilePath, String fileName) {
boolean flag = false;
File sourceFile = new File(sourceFilePath);
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
if (sourceFile.exists() == false) {
System.out.println("待压缩的文件目录:" + sourceFilePath + "不存在.");
} else {
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
if (zipFile.exists()) {
System.out.println(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
} else {
File[] sourceFiles = sourceFile.listFiles();
if (null == sourceFiles || sourceFiles.length < 1) {
System.out.println("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩.");
} else {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(new BufferedOutputStream(fos));
byte[] bufs = new byte[1024 * 10];
for (int i = 0; i < sourceFiles.length; i++) {
// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());
zos.putNextEntry(zipEntry);
// 读取待压缩的文件并写进压缩包里
fis = new FileInputStream(sourceFiles[i]);
bis = new BufferedInputStream(fis, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
}
flag = true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
// 关闭流
try {
if (null != bis)
bis.close();
if (null != zos)
zos.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
return flag;
}
/**
* 将sourceFilePath文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下
*
* @param sourceFilePath
* :待压缩的文件路径
* @param zipFilePath
* :压缩后存放路径
* @param fileName
* :压缩后文件的名称
* @return
*/
public static boolean fileToZip(String sourceFilePath, String zipFilePath, String fileName) {
boolean flag = false;
File sourceFile = new File(sourceFilePath);
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
if (sourceFile.exists() == false) {
System.out.println("待压缩的文件:" + sourceFilePath + "不存在.");
} else {
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
if (zipFile.exists()) {
System.out.println(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
} else {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(new BufferedOutputStream(fos));
byte[] bufs = new byte[1024 * 10];
// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(sourceFile.getName());
zos.putNextEntry(zipEntry);
// 读取待压缩的文件并写进压缩包里
fis = new FileInputStream(sourceFile);
bis = new BufferedInputStream(fis, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
flag = true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
// 关闭流
try {
if (null != bis)
bis.close();
if (null != zos)
zos.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
return flag;
}
/**
* 将流的内容打包成fileName名称的zip文件,并存放到zipFilePath路径下
* @param fis
* @param streamfilename
* @param zipFilePath 压缩后存放路径
* @param fileName 压缩后文件的名称
* @return
*/
public static boolean streamToZip(InputStream fis, String streamfilename, String zipFilePath, String fileName) {
boolean flag = false;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
if (zipFile.exists()) {
System.out.println(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
} else {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(new BufferedOutputStream(fos));
byte[] bufs = new byte[1024 * 10];
// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(streamfilename);
zos.putNextEntry(zipEntry);
// 读取待压缩的文件并写进压缩包里
bis = new BufferedInputStream(fis, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
flag = true;
}
zos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
// 关闭流
try {
if (null != bis)
bis.close();
if (null != zos)
zos.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return flag;
}
/**
* 将流转成zip文件输出
* @param inputstream
* 文件流
* @param streamfilename
* 流文件的名称
* @param fileName zip包的名称
* @param response
* @return
*/
public static boolean streamToZipStream(InputStream inputstream, String streamfilename, String fileName,
HttpServletResponse response) {
boolean flag = false;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
OutputStream out = null;
try {
out = response.getOutputStream();
response.reset();
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(fileName.getBytes("GB2312"), "ISO-8859-1"));
response.setContentType("application/octet-stream; charset=utf-8");
response.setCharacterEncoding("UTF-8");
zos = new ZipOutputStream(out);
byte[] bufs = new byte[1024 * 10];
// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(streamfilename);
zos.putNextEntry(zipEntry);
// 读取待压缩的文件并写进压缩包里
bis = new BufferedInputStream(inputstream, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
flag = true;
zos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
// 关闭流
try {
if (null != bis)
bis.close();
if (null != zos)
zos.close();
if (null != out)
out.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return flag;
}
/**
* 将多个流转成zip文件输出
* @param listStream
* 文件流实体类对象
* @param fileName zip包的名称
* @param response
* @return
*/
public static boolean listStreamToZipStream(List listStream, String fileName, HttpServletResponse response) {
boolean flag = false;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
OutputStream out = null;
try {
out = response.getOutputStream();
response.reset();
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(fileName.getBytes("GB2312"), "ISO-8859-1"));
response.setContentType("application/octet-stream; charset=utf-8");
response.setCharacterEncoding("UTF-8");
zos = new ZipOutputStream(out);
byte[] bufs = new byte[1024 * 10];
for (ZipStreamEntity zipstream : listStream) {
String streamfilename = zipstream.getName();
// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(streamfilename);
zos.putNextEntry(zipEntry);
// 读取待压缩的文件并写进压缩包里
bis = new BufferedInputStream(zipstream.getInputstream(), 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
}
flag = true;
zos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
// 关闭流
try {
if (null != bis)
bis.close();
if (null != zos)
zos.close();
if (null != out)
out.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return flag;
}
/**
* 判断当前系统是否为windows
* @return
*/
public static boolean isWindows() {
return System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1;
}
}
7、zip流文件实体类
/**
* zip相关 流文件实体类
*/
public class ZipStreamEntity {
public String name;
public InputStream inputstream;
public ZipStreamEntity() {
super();
// TODO Auto-generated constructor stub
}
public ZipStreamEntity(String name, InputStream inputstream) {
super();
this.name = name;
this.inputstream = inputstream;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public InputStream getInputstream() {
return inputstream;
}
public void setInputstream(InputStream inputstream) {
this.inputstream = inputstream;
}
}