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

SSH框架電商專案實戰(十五):Timer 與 TimerTask 定時同步首頁資料

     編輯:Java 相關知識

問題背景

專案初期,首頁商品資料僅在專案啟動時由 ServletContextListener 載入至 Application 域。當後台新增商品後,必須重啟伺服器才能同步,這顯然不符合電商網站「首頁資料自動更新」的需求。

解決方案:Timer + TimerTask 定時任務

引入 java.util.Timer 與 TimerTask,建立一個守護執行緒,定期(如每小時)從資料庫抓取最新熱門分類與推薦商品,更新 Application 域中的 bigList,前台頁面透過 JSTL 讀取 Application 資料,即可呈現最新商品,無需重啟。

核心類別介紹

  • Timer:排程器,可指定任務在特定時間首次執行,之後以固定間隔重複執行。建構子 Timer(boolean isDaemon) 可設為守護執行緒(主執行緒結束時自動終止)。
  • TimerTask:實作 Runnable 的抽象類別,繼承並覆寫 run() 即可定義具體任務邏輯。

程式碼實作

1. 定時任務類:ProductTimerTask

@Component
public class ProductTimerTask extends TimerTask {

    @Resource
    private ProductService productService;

    @Resource
    private CategoryService categoryService;

    private ServletContext application;

    // 由 Listener 注入 ServletContext
    public void setApplication(ServletContext application) {
        this.application = application;
    }

    @Override
    public void run() {
        System.out.println("---- 定時同步首頁資料 ----");

        List<List<Product>> bigList = new ArrayList<>();

        // 1. 查詢熱門分類
        for (Category category : categoryService.queryByHot(true)) {
            // 2. 依分類 ID 取得推薦商品
            List<Product> list = productService.queryByCategoryId(category.getId());
            bigList.add(list);
        }

        // 3. 更新 Application 域
        if (application != null) {
            application.setAttribute("bigList", bigList);
        }
    }
}

2. 啟動排程的 Listener:InitDataListener

public class InitDataListener implements ServletContextListener {

    private ProductTimerTask productTimerTask;
    private ApplicationContext context;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        // 1. 從 Spring 容器取得 Task Bean
        context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
        productTimerTask = (ProductTimerTask) context.getBean("productTimerTask");

        // 2. 注入 ServletContext 供 Task 寫入 Application
        productTimerTask.setApplication(event.getServletContext());

        // 3. 啟動定時器:守護執行緒、立即執行、每小時 (1000*60*60 ms) 執行一次
        new Timer(true).schedule(productTimerTask, 0, 1000 * 60 * 60);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // 容器關閉時的清理工作(若有)
    }
}

3. web.xml 註冊 Listener

<listener>
    <listener-class>com.shop.listener.InitDataListener</listener-class>
</listener>

實務觀察與調整

  • 同步頻率:可依業務需求調整(如每 30 分鐘、每天凌晨),過於頻繁會增加資料庫負載。
  • 資料一致性:若首頁需「即時」呈現,可考慮引入快取中介軟體(Redis、Ehcache)搭配訊息佇列,實現資料異動即推送更新。
  • 錯誤處理:run() 內建議加上 try-catch 並記錄日誌,避免單次異常導致後續排程停止。

小結

透過 Timer + TimerTask 搭配 ServletContextListener,輕鬆實現首頁資料的定時自動同步,解決「後台異動、前台不重啟不更新」的痛點,架構簡單且符合輕量級專案需求。

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