Quartz 定时邮件发送多个备份文件 - 黑壳网 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kzyuan
V2EX    Java

Quartz 定时邮件发送多个备份文件 - 黑壳网

  •  
  •   kzyuan
    ykz200 2017-07-27 17:34:04 +08:00 3139 次点击
    这是一个创建于 3073 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文由黑壳网发布
    本文来源Quartz 定时邮件发送备份文件 - 黑壳网 http://www.bhusk.com/articles/2017/07/27/1501146724360.html

    壳叔搞笑一刻

    熊孩子也有自己的梦想

    正文

    之前由于黑壳网的博客数据库,一直没有做定期备份的处理,虽然现在不一定会出问题,但起码数据备份意识上还是要有的。

    之前有考虑过用七牛云等第三方服务,但是最后由于种种原因,暂时不考虑用第三方服务。 所以自己手写了一个定时备份程序,简单的思路↓

    到达指定时间,将数据库备份文件发送利用邮箱,发送至指定邮箱,达到定期备份的目的。

    特别提示:如果文件对安全性要求很高的话,不推荐

    程序采用 Java 语言和maven 强大的依赖体系+流行的 spring,为什么要用 Java,只是写着好玩不要太较真了。

    项目代码

    pom.xml 文件 Quartz 的包是整个项目不可缺少的

     <properties> <!-- Spring 的版本 --> <springframework.version>4.0.6.RELEASE</springframework.version> <!-- Quartz 的版本 --> <quartz.version>2.2.1</quartz.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> </dependencies> 

    MyJob.java 继承 QuartzJobBean 然后 Override 有钻研精神的可以一点一点扒代码看 QuartzJobBean。

    import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.quartz.QuartzJobBean; import java.util.Date; /** * kzyuan Job 参考 * @description black husk * @description http://www.bhusk.com */ public class MyJob extends QuartzJobBean { private static Logger logger = LoggerFactory.getLogger(DatabaseBackupJob.class); @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("执行时间:"+new Date()); } } 

    application.xml 可以理解为 quartz 配置文件 注释很齐全

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:cOntext="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 定义任务 bean --> <bean name="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <!-- 指定具体的 job 类 --> <property name="jobClass" value="com.bhusk.quartz.Job.MyJob"/> <!-- 指定 job 的名称 --> <property name="name" value="myJob"/> <!-- 指定 job 的分组 --> <property name="group" value="jobs"/> <!-- 必须设置为 true,如果为 false,当没有活动的触发器与之关联时会在调度器中删除该任务 --> <property name="durability" value="true"/> <!-- 指定 spring 容器的 key,如果不设定在 job 中的 jobmap 中是获取不到 spring 容器的 --> <property name="applicationContextJobDataKey" value="applicationContext"/> </bean> <!-- 定义触发器 --> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="myJobDetail"/> <!--执行时间 --> <property name="cronExpression" value="0 0 3 * * ?"/> </bean> <!-- 定义触发器 --> <!--演示:一个 job 可以有多个 trigger ; --> <!--<bean id="cronTrigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">--> <!--<property name="jobDetail" ref="myJobDetail2" />--> <!--每一分钟执行一次--> <!-- <property name="cronExpression" value="0 0 3 * * ?"/> --> <!--</bean>--> <!-- 定义调度器 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger"/> <!-- <ref bean="cronTrigger2"/> --> </list> </property> </bean> </beans> 

    JavaMail 发送邮件工具类 java 实现邮件的发送, 抄送及多附件 这个工具类来源网络,具体精准位置也不清楚了

    import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; import java.io.UnsupportedEncodingException; import java.util.Properties; /** * 邮件管理器 * java 实现邮件的发送, 抄送及多附件 */ public class EmailManager { public static String username = "[email protected]"; // 服务邮箱(from 邮箱) public static String password = ""; // 邮箱密码 public static String senderNick = "黑壳网的壳叔"; // 发件人昵称 private Properties props; // 系统属性 private Session session; // 邮件会话对象 private MimeMessage mimeMsg; // MIME 邮件对象 private Multipart mp; // Multipart 对象,邮件内容,标题,附件等内容均添加到其中后再生成 MimeMessage 对象 private static EmailManager instance = null; public EmailManager() { props = System.getProperties(); props.put("mail.smtp.auth", "true"); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.host", "smtp.163.com"); props.put("mail.smtp.port", "25"); props.put("username", username); props.put("password", password); // 建立会话 session = Session.getDefaultInstance(props); session.setDebug(false); } public static EmailManager getInstance() { if (instance == null) { instance = new EmailManager(); } return instance; } /** * 发送邮件 * * @param from 发件人 * @param to 收件人 * @param copyto 抄送 * @param subject 主题 * @param content 内容 * @param fileList 附件列表 * @return */ public boolean sendMail(String from, String[] to, String[] copyto, String subject, String content, String[] fileList) { boolean success = true; try { mimeMsg = new MimeMessage(session); mp = new MimeMultipart(); // 自定义发件人昵称 String nick = ""; try { nick = javax.mail.internet.MimeUtility.encodeText(senderNick); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 设置发件人 // mimeMsg.setFrom(new InternetAddress(from)); mimeMsg.setFrom(new InternetAddress(from, nick)); // 设置收件人 if (to != null && to.length > 0) { String toListStr = getMailList(to); mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toListStr)); } // 设置抄送人 if (copyto != null && copyto.length > 0) { String ccListStr = getMailList(copyto); mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccListStr)); } // 设置主题 mimeMsg.setSubject(subject); // 设置正文 BodyPart bp = new MimeBodyPart(); bp.setContent(content, "text/html;charset="); mp.addBodyPart(bp); // 设置附件 if (fileList != null && fileList.length > 0) { for (int i = 0; i < fileList.length; i++) { bp = new MimeBodyPart(); FileDataSource fds = new FileDataSource(fileList[i]); bp.setDataHandler(new DataHandler(fds)); bp.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B")); mp.addBodyPart(bp); } } mimeMsg.setContent(mp); mimeMsg.saveChanges(); // 发送邮件 if (props.get("mail.smtp.auth").equals("true")) { Transport transport = session.getTransport("smtp"); transport.connect((String) props.get("mail.smtp.host"), (String) props.get("username"), (String) props.get("password")); // transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO)); // transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.CC)); transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients()); transport.close(); } else { Transport.send(mimeMsg); } System.out.println("邮件发送成功"); } catch (MessagingException e) { e.printStackTrace(); success = false; } catch (UnsupportedEncodingException e) { e.printStackTrace(); success = false; } return success; } /** * 发送邮件 * * @param from 发件人 * @param to 收件人, 多个 Email 以英文逗号分隔 * @param cc 抄送, 多个 Email 以英文逗号分隔 * @param subject 主题 * @param content 内容 * @param fileList 附件列表 * @return */ public boolean sendMail(String from, String to, String cc, String subject, String content, String[] fileList) { boolean success = true; try { mimeMsg = new MimeMessage(session); mp = new MimeMultipart(); // 自定义发件人昵称 String nick = ""; try { nick = javax.mail.internet.MimeUtility.encodeText(senderNick); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 设置发件人 // mimeMsg.setFrom(new InternetAddress(from)); mimeMsg.setFrom(new InternetAddress(from, nick)); // 设置收件人 if (to != null && to.length() > 0) { mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); } // 设置抄送人 if (cc != null && cc.length() > 0) { mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc)); } // 设置主题 mimeMsg.setSubject(subject); // 设置正文 BodyPart bp = new MimeBodyPart(); bp.setContent(content, "text/html;charset="); mp.addBodyPart(bp); // 设置附件 if (fileList != null && fileList.length > 0) { for (int i = 0; i < fileList.length; i++) { bp = new MimeBodyPart(); FileDataSource fds = new FileDataSource(fileList[i]); bp.setDataHandler(new DataHandler(fds)); bp.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B")); mp.addBodyPart(bp); } } mimeMsg.setContent(mp); mimeMsg.saveChanges(); // 发送邮件 if (props.get("mail.smtp.auth").equals("true")) { Transport transport = session.getTransport("smtp"); transport.connect((String) props.get("mail.smtp.host"), (String) props.get("username"), (String) props.get("password")); transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients()); transport.close(); } else { Transport.send(mimeMsg); } System.out.println("邮件发送成功"); } catch (MessagingException e) { e.printStackTrace(); success = false; } catch (UnsupportedEncodingException e) { e.printStackTrace(); success = false; } return success; } public String getMailList(String[] mailArray) { StringBuffer toList = new StringBuffer(); int length = mailArray.length; if (mailArray != null && length < 2) { toList.append(mailArray[0]); } else { for (int i = 0; i < length; i++) { toList.append(mailArray[i]); if (i != (length - 1)) { toList.append(","); } } } return toList.toString(); } public static void main(String[] args) { String from = username; String[] to = {"[email protected]", "[email protected]"}; String[] copyto = {"[email protected]"}; String subject = "黑壳网数据库备份"; String cOntent= "没有数据就没有一切,数据库备份就是一种防范灾难于未然的强力手段,没有了数据,应用再花哨也是镜中花水中月。"; String[] fileList = new String[2]; fileList[0] = "~/solo_h2/db.mv.db"; fileList[1] = "~/solo_h2/db.trace.db"; EmailManager.getInstance().sendMail(from, to, copyto, subject, content, fileList); } } 

    参考项目 GitHub

    参考项目 GitHub:https://github.com/ykz200/Quartz_DatabaseBackup

    junbaor
        1
    junbaor  
       2017-07-28 10:27:19 +08:00
    既然引用 spring 了,一个 @Scheduled 注解就搞定了,没必要配置繁琐的 Quartz
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5148 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 07:33 PVG 15:33 LAX 23:33 JFK 02:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86