我目前正在實施ServletContextListener
並使用contextDestroyed()
在我的web應用程序關閉之前運行清理任務。不過,我一直在閱讀如何Runtime.addShutdownHook(Thread)
可用於相同的目的。contextDestroyed()vs addShutdownHook()
在取消部署之前,這兩種運行清理的方法是否有區別?就功能性,效率和可維護性而言,哪種方式更適合Web應用程序?
我目前正在實施ServletContextListener
並使用contextDestroyed()
在我的web應用程序關閉之前運行清理任務。不過,我一直在閱讀如何Runtime.addShutdownHook(Thread)
可用於相同的目的。contextDestroyed()vs addShutdownHook()
在取消部署之前,這兩種運行清理的方法是否有區別?就功能性,效率和可維護性而言,哪種方式更適合Web應用程序?
我認爲ServletContextListener更適合於Web應用程序,因爲您爲每個會話清理資源。
關閉掛鉤在JVM關閉時執行。這將是當你停止你的容器,這是一次性事件。
許多servlet容器都支持在不關閉JVM進程的情況下動態刪除和/或重新加載WAR的操作。因此,如果你將自己的清理例程寫成ServletContextListener,它可能會在容器的生命週期中運行多次。 (例如,如果在容器進程仍處於運行狀態時多次修改WAR並重新加載WAR)
但是,如果使用Runtime.addShutdownHook實現清理,它將只運行一次:當容器的JVM整體關閉。
ServletContextListener可能是您的正確答案,因爲它將您的清理例程與Web應用程序的生命相結合,而不是託管它的容器過程的生命。
使用addShutdownHook()的危險是您可能會遇到類加載程序泄漏,這會在您多次重新部署應用程序時變得明顯。
因爲關閉鉤子類(您的web應用程序中的Thread子類或Runnable實現)來自Web應用程序的類加載器,即使您的web應用程序被容器取消部署後,關閉鉤子仍將在系統中註冊。這意味着整個webapp的類加載器不能被垃圾收集。
我肯定會推薦ServletContextListener。
我們正在談論的泄漏只有在我們進行熱點/部署時纔會發生。但是,如果在每次部署更改後重新啓動服務器,則掛鉤應該可以正常工作,且不會泄漏內存 另外,控制泄漏的另一個因素是您試圖通過偵聽器/鉤子控制的資源清理類型。
這是對以前的答案的評論,而不是本身的答案。 –
爲什麼不這樣做?雖然ServletContextListener更適合webapp,但我發現在開發期間服務器通常會突然停止,然後contextDestroyed()永遠不會被調用,因此您可以使用兩種機制來確保始終正常關閉:
在ContextInitialized調用addShutdownHook()和contextDestroyed調用removeShutdownHook()的地方實現一個ServletContextListener。 hook和contextDestroyed都可以委託給一些內部方法來實際進行清理。
這樣,如果聽者正確調用然後鉤被添加和刪除(但不是調用),並沒有泄漏,但如果服務器死亡,沒有上下文被破壞,關機鉤清除的東西了。
+1感謝我現在的區別現在 –