2.4 Java Web應(yīng)用中的任務(wù)調(diào)度
為何需要任務(wù)調(diào)度?
在web應(yīng)用中,大多數(shù)任務(wù)是以一種"防止用戶長(zhǎng)時(shí)間等待"的方式完成的。在Google搜索這樣的例子中,減少等待時(shí)間對(duì)用戶體驗(yàn)來說至關(guān)重要。異步任務(wù)的一種解決方案是在用戶提交后生成一個(gè)線程(來處理異步任務(wù)),但這也不能解決那些需要以一定時(shí)間間隔重復(fù)運(yùn)行任務(wù)、或在每天的指定時(shí)間運(yùn)行任務(wù)的情況。
讓我們從一個(gè)數(shù)據(jù)庫報(bào)表的例子來看看任務(wù)調(diào)度能如何幫助改善系統(tǒng)設(shè)計(jì)。報(bào)表可能是錯(cuò)綜復(fù)雜的,這取決于用戶所需數(shù)據(jù)的種類,以及是否需要從一個(gè)或多個(gè)數(shù)據(jù)庫收集大量數(shù)據(jù)。用戶可能需要很長(zhǎng)時(shí)間來運(yùn)行這樣的"按需"報(bào)表。因此,我們向這個(gè)報(bào)表示例中添加任務(wù)調(diào)度機(jī)制,以便用戶可以安排在任何他們需要的時(shí)間生成報(bào)表,并以PDF或其他格式在email中發(fā)送。用戶可以讓報(bào)表在每天的凌晨2:22,系統(tǒng)正處于低負(fù)荷時(shí)運(yùn)行;也可以選擇只在特定時(shí)間運(yùn)行一次。通過在報(bào)表應(yīng)用中加入任務(wù)調(diào)度,我們可以為產(chǎn)品添加一項(xiàng)有用的功能,并改善用戶體驗(yàn)。
幸運(yùn)的是,有一個(gè)強(qiáng)大的開源解決方案可以讓我們以標(biāo)準(zhǔn)的方式在web應(yīng)用(或任何Java應(yīng)用)中實(shí)施任務(wù)調(diào)度。以下示例展示了在web應(yīng)用中,如何使用Quartz來創(chuàng)建一個(gè)任務(wù)調(diào)度框架。這個(gè)示例還使用了Struts Action framework 插件,以便在web應(yīng)用啟動(dòng)時(shí)初始化任務(wù)調(diào)度機(jī)制。Struts是最常見的MVC框架,為大多數(shù)開發(fā)人員所熟悉。當(dāng)然除此之外還有許多框架可以協(xié)助在web應(yīng)用中實(shí)現(xiàn)MVC模式。
啟動(dòng)時(shí)初始化任務(wù)調(diào)度器
我們首先要做的是建立一個(gè)Struts插件,讓它在容器啟動(dòng)時(shí)創(chuàng)建我們的任務(wù)調(diào)度器。在以下例子中,我們選擇Tomcat作為web應(yīng)用容器,不過這些示例在其他容器中也應(yīng)當(dāng)可以運(yùn)行。我們要?jiǎng)?chuàng)建一個(gè)Struts插件類,并在struts-config.xml中加入幾行代碼以使之可以工作。
這個(gè)插件有兩個(gè)可配置的初始化參數(shù):startOnLoad指定是否要在容器啟動(dòng)時(shí)立即啟動(dòng)任務(wù)調(diào)度器,而 startupDelay指定啟動(dòng)任務(wù)調(diào)度器之前的等待時(shí)間。啟動(dòng)延時(shí)很有用,因?yàn)槲覀兛赡苄枰紫葓?zhí)行一些更重要的初始化步驟。此外還可以使用listener機(jī)制,以更復(fù)雜的方式來通知SchedulerPlugIn何時(shí)啟動(dòng)Quartz Scheduler。
我們要?jiǎng)?chuàng)建的是一個(gè)實(shí)現(xiàn)Struts插件接口org.apache.struts.action.PlugIn的單子類SchedulerPlugIn。Struts會(huì)按照配置文件中出現(xiàn)的順序初始化各個(gè)插件。要特別注意的是init()方法中的代碼,在此我們初始化了所需的Quartz對(duì)象,并得到Scheduler。我們的任務(wù)信息就要提交到此org.quartz.Scheduler對(duì)象,后者將在隨后討論。Scheduler對(duì)象由Quartz servlet根據(jù)其配置初始化,就像Struts初始化它的ActionServlet類一樣。讓我們來看init()方法:
public void init(ActionServlet actionServlet,
ModuleConfig moduleConfig) {
System.out.println("Initializing Scheduler PlugIn for Jobs!");
// Retrieve the ServletContext
// 獲取ServletContext
ServletContext ctx = actionServlet.getServletContext();
// The Quartz Scheduler
// Quartz Scheduler對(duì)象
Scheduler scheduler = null;
// Retrieve the factory from the ServletContext.
// It will be put there by the Quartz Servlet
// 從ServletContext取得由Quartz Servlet放置在此的factory對(duì)象。
StdSchedulerFactory factory = (StdSchedulerFactory)
ctx.getAttribute(QuartzInitializerServlet.QUARTZ_FACTORY_KEY);
try{
// Retrieve the scheduler from the factory
// 從factory取得scheduler
scheduler = factory.getScheduler();
// Start the scheduler in case, it isn't started yet
// 如果scheduler尚未啟動(dòng),則啟動(dòng)它
if (m_startOnLoad != null &&
m_startOnLoad.equals(Boolean.TRUE.toString())){
System.out.println("Scheduler Will start in " +
m_startupDelayString + " milliseconds!");
//wait the specified amount of time before
// starting the process.
相關(guān)推薦:計(jì)算機(jī)等級(jí)考試二級(jí)Java經(jīng)典算法大全匯總
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |