首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 定時發送郵件實作指南:Timer 與 JavaMail 整合教學

     編輯:Java 相關知識

前言

在企業級應用開發中,定時發送電子郵件是常見需求,例如:定時發送報表、系統通知、生日祝福等。本文將詳細介紹如何在 Java Web 專案中,結合 java.util.Timer 與 JavaMail API,實現應用啟動時自動排程、定時發送郵件的完整方案。

核心架構設計

1. 排程機制:Timer 與 TimerTask

Java 標準庫提供的 java.util.Timer 是一個簡單的排程工具,搭配 TimerTask 即可實現週期性任務執行。其核心方法 schedule(TimerTask task, long delay, long period) 參數說明:

  • task:繼承 TimerTask 的具體任務類
  • delay:首次執行前的延遲時間(毫秒),0 表示立即執行
  • period:執行間隔週期(毫秒),例如 24*60*60*1000 代表每 24 小時執行一次

2. 生命週期管理:ServletContextListener

為確保排程器在 Web 應用啟動時自動啟動、關閉時自動銷毀,必須實作 javax.servlet.ServletContextListener 接口,並在 web.xml 中註冊。這樣排程器的生命週期將與整個 Web 應用同步。

public class EmailSchedulerListener implements ServletContextListener {
    private Timer timer = null;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        timer = new Timer(true); // daemon thread
        sce.getServletContext().log("排程器已啟動");
        // 每 24 小時執行一次發送郵件任務
        timer.schedule(new SendEmailTask(sce.getServletContext()), 0, 24 * 60 * 60 * 1000);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        if (timer != null) {
            timer.cancel();
            sce.getServletContext().log("排程器已銷毀");
        }
    }
}

3. 郵件發送任務實作

繼承 TimerTask,在 run() 方法中整合 JavaMail 發送邏輯。需準備 activation.jar 與 mail.jar 放入專案 WEB-INF/lib 目錄。

public class SendEmailTask extends TimerTask {
    private ServletContext context;

    public SendEmailTask(ServletContext context) {
        this.context = context;
    }

    @Override
    public void run() {
        try {
            Properties props = new Properties();
            props.put("mail.smtp.host", "smtp.163.com");
            props.put("mail.smtp.auth", "true");
            Session session = Session.getInstance(props);
            session.setDebug(true); // 開啟除錯輸出

            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress("your_email@163.com"));
            message.setRecipient(Message.RecipientType.TO, new InternetAddress("recipient@example.com"));
            message.setSubject("定時郵件測試");
            message.setSentDate(new Date());

            // 郵件內容支援 HTML
            MimeBodyPart bodyPart = new MimeBodyPart();
            bodyPart.setContent("<h1>這是定時發送的測試郵件</h1>", "text/html;charset=utf-8");

            MimeMultipart multipart = new MimeMultipart();
            multipart.addBodyPart(bodyPart);
            message.setContent(multipart);
            message.saveChanges();

            Transport transport = session.getTransport("smtp");
            transport.connect("smtp.163.com", "your_email@163.com", "your_password");
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();

            context.log("郵件發送成功");
        } catch (Exception e) {
            context.log("郵件發送失敗: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

部署配置

web.xml 註冊監聽器

<web-app>
    <listener>
        <listener-class>com.example.listener.EmailSchedulerListener</listener-class>
    </listener>
</web-app>

注意事項與最佳實踐

  • 安全性:生產環境切勿硬編碼帳號密碼,建議使用 JNDI 資源或配置中心管理敏感資訊。
  • 異常處理:run() 方法中必須捕獲所有異常,否則 Timer 會終止後續排程。
  • 叢集環境:多節點部署時需引入分散式排程框架(如 Quartz + 資料庫鎖)避免重複發送。
  • 郵件模板:實際專案建議使用 Velocity、Thymeleaf 等模板引擎分離內容與邏輯。

總結

本方案利用 Servlet 監聽器管理 Timer 生命週期,結合 JavaMail 實現輕量級的定時郵件發送功能,適合中小型專案快速落地。對於高可用、分散式場景,建議升級至 Quartz 或 Spring @Scheduled 搭配分散式鎖方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved