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

JNotify 實戰:郵件系統文件夾動態監聽與 .eml 解析完整方案

     編輯:Java 綜合教學

JNotify 實戰:郵件系統文件夾動態監聽與 .eml 解析完整方案

JNotify 是基於操作系統底層機制(Linux inotify / Windows DLL)實現的文件/文件夾動態監控庫,支持遞歸子目錄監聽。本文以郵件系統為例,展示基於 JNotify 的 .eml 文件實時檢測、解析、入庫全流程。

環境準備

  1. 引入 jnotify.jar
  2. JDK bin 目錄放入 jnotify.dll / jnotify_64bit.dll(Windows 需求)

核心架構三層設計

1. 監聽啟動器 MailWatcher

public class MailWatcher {
    private static final Logger LOG = LoggerFactory.getLogger(MailWatcher.class);
    private String path; // 郵件存儲路徑

    public MailWatcher() {
        path = Configure.getString("path");
    }

    public void start() {
        new Thread(() -> {
            try {
                int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED
                        | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
                int watchId = JNotify.addWatch(path, mask, true, new MailListener());
                LOG.info("Watcher 啟動監聽: {} [ID:{}]", path, watchId);
            } catch (Exception e) {
                LOG.error("監聽啟動失敗", e);
            }
        }).start();

        // 守護主線程
        while (true) {
            try { Thread.sleep(200); } catch (InterruptedException ignored) {}
        }
    }
}

2. 事件處理器 MailListener

實現 JNotifyListener 接口,核心邏輯在 fileCreated:

  • 過濾 .eml 後綴文件
  • 異步線程處理:初始等待 + 重試機制(最多 50 次 × 10 秒)
  • 調用 EmlFileHelper 解析為 MimeMessage
  • 發件人過濾:識別並跳過本系統發出的郵件
  • 持久化存儲 saveMsg()
public void fileCreated(int wd, String rootPath, String name) {
    if (!name.endsWith(".eml")) return;
    
    new Thread(() -> {
        File file = new File(rootPath, name);
        MimeMessage msg = null;
        
        // 初始等待文件寫入完成
        sleep(Configure.getLong("wait_first_time"));
        
        // 重試讀取
        for (int i = 0; i < Configure.getInt("wait_times"); i++) {
            try {
                msg = EmlFileHelper.getMimeFile(file);
                break;
            } catch (Exception e) {
                LOG.debug("第 {} 次讀取失敗: {}", i + 1, name);
                sleep(Configure.getLong("wait_time_interval") * 1000);
            }
        }
        
        if (msg == null) { LOG.error("重試後仍讀取失敗: {}", name); return; }
        
        // 過濾發出郵件
        if (!Configure.getBoolean("not_intercept_send_email")) {
            String receiver = name.substring(0, name.indexOf(File.separator));
            String from = MailHelper.getFrom(msg);
            if (from.startsWith(receiver + "@")) {
                LOG.info("跳過發出郵件: {}", name);
                return;
            }
        }
        
        saveMsg(msg, name);
        LOG.info("郵件保存成功: {}", name);
    }).start();
}

3. 啟動入口

public class Main {
    public static void main(String[] args) throws Exception {
        new MailWatcher().start();
    }
}

關鍵設計亮點

  1. 事件驅動替代輪詢:OS 級通知,毫秒級響應,零 CPU 空轉
  2. 健壯的重試機制:應對郵件寫入未完成導致的讀取失敗
  3. 異步非阻塞處理:事件回調線程池化,不阻塞監聽主循環
  4. 業務過濾邏輯:自動識別並排除系統自發郵件,避免重複入庫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved