<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java-Android-jwebee
    Java-Android-jwebee
    對IT人來說,要成為一個優秀的技術型管理者,除了需要具備扎實的技術基礎之外,還應該培養良好的人際關系能力、談判與溝通技能、客戶關系與咨詢技能、商業頭腦和財務技能以及創新意識,此外還要有巧妙的激勵技巧和化解沖突與解決突發問題的能力.
    來源:賽迪網

    任務調度是大型J2EE web應用中常見的工作。開發者希望以指定的間隔時間執行各類操作,并完成一些無需用戶輸入的任務。Java中可有無數方法來做到這一點,但是在web應用中卻并沒有這方面的統一標準。當許多開發人員參與同一個項目,并且以各自不同的方式來實現任務調度時,就可能產生很大問題。內存和同步問題就是必須首先考慮的兩件事。事實上,一些開發者試圖調用操作系統層面的任務調度機制,如Unix平臺上的cron。這種編程實踐也許并不是太壞,但它將直接導致可移植性被拋到九霄云外。

    為何需要任務調度?

    在web應用中,大多數任務是以一種"防止用戶長時間等待"的方式完成的。在Google搜索這樣的例子中,減少等待時間對用戶體驗來說至關重要。異步任務的一種解決方案是在用戶提交后生成一個線程(來處理異步任務),但這也不能解決那些需要以一定時間間隔重復運行任務、或在每天的指定時間運行任務的情況。

    讓我們從一個數據庫報表的例子來看看任務調度能如何幫助改善系統設計。報表可能是錯綜復雜的,這取決于用戶所需數據的種類,以及是否需要從一個或多個數據庫收集大量數據。用戶可能需要很長時間來運行這樣的"按需"報表。因此,我們向這個報表示例中添加任務調度機制,以便用戶可以安排在任何他們需要的時間生成報表,并以PDF或其他格式在email中發送。用戶可以讓報表在每天的凌晨2:22,系統正處于低負荷時運行;也可以選擇只在特定時間運行一次。通過在報表應用中加入任務調度,我們可以為產品添加一項有用的功能,并改善用戶體驗。

    幸運的是,有一個強大的開源解決方案可以讓我們以標準的方式在web應用(或任何Java應用)中實施任務調度。以下示例展示了在web應用中,如何使用Quartz來創建一個任務調度框架。這個示例還使用了Struts Action framework 插件,以便在web應用啟動時初始化任務調度機制。Struts是最常見的MVC框架,為大多數開發人員所熟悉。當然除此之外還有許多框架可以協助在web應用中實現MVC模式。

    啟動時初始化任務調度器

    我們首先要做的是建立一個Struts插件,讓它在容器啟動時創建我們的任務調度器。在以下例子中,我們選擇Tomcat作為web應用容器,不過這些示例在其他容器中也應當可以運行。我們要創建一個Struts插件類,并在struts-config.xml中加入幾行代碼以使之可以工作。

    這個插件有兩個可配置的初始化參數:startOnLoad指定是否要在容器啟動時立即啟動任務調度器,而 startupDelay指定啟動任務調度器之前的等待時間。啟動延時很有用,因為我們可能需要首先執行一些更重要的初始化步驟。此外還可以使用listener機制,以更復雜的方式來通知SchedulerPlugIn何時啟動Quartz Scheduler。

    <PLUG-IN className="SchedulerPlugIn">

    <SET-PROPERTY property="startOnLoad" value="false" />

    <SET-PROPERTY property="startupDelay" value="0" />

    </PLUG-IN>

    我們要創建的是一個實現Struts插件接口org.apache.struts.action.PlugIn的單子類SchedulerPlugIn。Struts會按照配置文件中出現的順序初始化各個插件。要特別注意的是init()方法中的代碼,在此我們初始化了所需的Quartz對象,并得到Scheduler。我們的任務信息就要提交到此org.quartz.Scheduler對象,后者將在隨后討論。Scheduler對象由Quartz servlet根據其配置初始化,就像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對象
    Scheduler scheduler = null;

    // Retrieve the factory from the ServletContext.
    // It will be put there by the Quartz Servlet
    // 從ServletContext取得由Quartz Servlet放置在此的factory對象。
    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尚未啟動,則啟動它
    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.
    // 在啟動之前等待指定長度的時間
    Thread delayedScheduler =
    new Thread(new DelayedSchedulerStarted (
    scheduler, m_startupDelay));
    //give the scheduler a name. All good code needs a name
    //給任務調度器命名。好的代碼總該有名字!
    delayedScheduler.setName("Delayed_Scheduler");
    //Start out scheduler
    //啟動任務調度器
    delayedScheduler.start();
    }
    } catch (Exception e){
    e.printStackTrace();
    }
    sm_scheduler = scheduler;
    }

    配置過程的第二步是在web.xml中加入用來初始化Quartz servlet(org.quartz.ee.servlet.QuartzInitializerServlet)的內容,因為需要它將SchedulerFactory添加到ServletContext中,以便在我們的Struts插件中可以訪問。SchedulerFactory就是我們在Struts插件中獲得Scheduler對象的來源。除了struts-config.xml 和web.xml之外,還要在web應用的classes目錄下放置一個quartz.properties文件。此文件的位置也可以在web.xml中作為QuartzInitializerServlet的啟動參數來指定。

    QuartzInitializer

    Quartz Initializer Servlet

    org.quartz.ee.servlet.QuartzInitializerServlet

    1

    shutdown-on-unload

    true

    start-scheduler-on-load

    false

    這里其實完全可以不使用Struts和SchedulerPlugIn,但如果將來決定要以其它的任務調度框架替換Quartz的話,額外的抽象層就很有用了。長遠看來,讓一切保持松散耦合總會使工作變得容易些。如果你使用其它MVC框架,也可以用SchedulerPlugIn.init()方法中的代碼達到同樣的效果。此外,還可以用Servlet 2.3規范中的ServletContextListener來實現同樣的初始化過程。

    到此為止web應用已配置完畢,我們可以創建一個.war文件并部署到服務器上,從控制臺觀察SchedulerPlugIn的輸出信息。然而在此之前,讓我們先看看如何向任務調度器提交一項任務。

    我們可以從web應用中的任何類訪問SchedulerPlugIn的唯一實例,并調度一些要執行的工作。首先需要一個Trigger(觸發器)對象來告訴任務何時運行、每隔多久運行一次。Quartz支持多種觸發器,在這個例子中我們使用CronTrigger。

    Trigger trigger = new CronTrigger("trigger1", "group1");

    trigger.setCronExpression("0 0 15 ? * WED");

    以上的觸發器會在每周三的下午3點執行指定任務?,F在我們只要創建一個JobDetail對象,并把它和上面的觸發器一起傳遞給SchedulerPlugIn的scheduleWork()方法。

    JobDetail jobDetail =
    new JobDetail("Hello World Job",
    "Hello World Group",
    HelloWorld.class,
    true, true, true);
    //Schedule The work
    //調度這項任務
    SchedulerPlugIn.scheduleWork(scheduledJobDetail, trigger);

    實際工作在何處?

    至此我們已決定Trigger,可以開始調度工作了??瓷先ヒ磺卸家淹瓿?,但實際上我們只是調度了一項任務,還有最重要的一步有待完成。注意HelloWorld.class作為參數傳遞給了JobDetail的構造函數。這個類就是實際完成工作的地方。HelloWorld繼承了Quartz的Job類,并覆蓋了execute()方法。當任務管理器決定運行這個任務時,execute()方法將被調用。來看代碼:

    import org.quartz.JobDataMap;
    import org.quartz.JobDetail;
    import org.quartz.JobExecutionContext;

    //extend the proper Quartz class
    //繼承適當的Quartz類
    public class HelloWorld extends Job {

    //override the execute method
    //覆蓋execute方法
    public void execute(JobExecutionContext context) {

    // Every job has it's own job detail
    //每個Job都有獨立的JobDetail
    JobDetail jobDetail = context.getJobDetail();
    // The name is defined in the job definition
    //name在Job定義中指定
    String jobName = jobDetail.getName();
    //Every job has a Job Data map for storing extra information
    //每個Job都有一個Job Data map來存放額外的信息
    JobDataMap dataMap = jobDetail.getJobDataMap();

    System.out.println("Hello World!!!");
    }
    }

    出于測試的目的,你可能希望將觸發器的頻率調的高一點,以便觀察到HelloWorld的動作。畢竟,你不想一直等到凌晨2點才能確定調度的任務確實運行了。相反,你可能需要一個每隔10秒運行的觸發器:

    Trigger trigger = new SimpleTrigger("trigger1", "group1");
    trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
    trigger.setRepeatInterval(10000L); // milliseconds毫秒

    注意,這個觸發器沒有使用類cron的語法。Quartz有大量各類的選項和配置方法,可適用于任何任務調度的需要。

    其它計時方式的配置

    Quartz提供了多種調度任務的方式。CronTrigger可能是最復雜的一種,不過還有其它的選擇。大多數觸發器可以由Quartz提供的TriggerUtils類創建。以下是一些常見的觸發器的例子。如諺語所言,條條大路通羅馬!

    每天凌晨2:22觸發的觸發器

    // 方法一:使用makeDailyTrigger
    Trigger trigger = TriggerUtils.makeDailyTrigger(2, 22);
    trigger.setName("trigger1");
    trigger.setGroup("group1");
    // 方法二:使用CronTrigger
    Trigger trigger = new CronTrigger("trigger1", "group1");
    trigger.setCronExpression("0 22 2 * * ?");


    每5秒執行一次的觸發器

    /**
    * 方法一:makeSecondlyTrigger
    * 注意以下代碼將創建一個立即啟動的觸發器。要控制啟動時間,使用
    * trigger.setStartTime(Date)方法。
    */
    Trigger trigger = TriggerUtils.makeSecondlyTrigger(5);
    trigger.setName("MyFiveSecondTrigger");
    trigger.setGroup("MyTriggerGroup");
    /** 方法二:設置SimpleTrigger的重復次數和間隔時間。
    * 注意以下代碼將創建一個立即啟動的觸發器。要控制啟動時間,使用
    * trigger.setStartTime(Date)方法。
    */
    Trigger trigger = new SimpleTrigger("trigger1", "group1");
    trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
    trigger.setRepeatInterval(5000L);
    // milliseconds按間隔時間運行任務
    Trigger trigger = new SimpleTrigger("trigger1", "group1");
    // 24 hours * 60(minutes per hour) *
    // 60(seconds per minute) * 1000(milliseconds per second)
    // 24小時 * 60(分鐘每小時) * 60(秒每分鐘)* 1000(毫秒每秒鐘)
    trigger.setRepeatInterval(24L * 60L * 60L * 1000L);

    結論在這個演示中,我們只接觸了Quartz框架的一些初級功能。記住,Java 5 和J2EE 5也有自己的任務調度機制,但是它們不像Quartz那樣靈活易用。Quartz是目前唯一的開源Java任務調度框架,它的確為開發者的錦囊中增加了很有用的內容。你可從Open Symphony下載Quartz,并得到一份很好的教程和使用說明。

    jwebee

    我的個人網站
    posted on 2007-08-16 12:16 周行 閱讀(1122) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    Java-Android-jwebee
    主站蜘蛛池模板: 亚洲avav天堂av在线不卡| 亚洲AV无码不卡在线观看下载 | 98精品全国免费观看视频| 国产亚洲精品无码专区| 国产A∨免费精品视频| 亚洲精品人成无码中文毛片| 日韩在线视频免费| 亚洲人成网站在线观看青青| 人妻18毛片a级毛片免费看| 亚洲AV无码不卡在线观看下载| 一区二区免费电影| 亚洲愉拍99热成人精品热久久| 99精品免费视品| 亚洲高清视频在线观看| 中文免费观看视频网站| 亚洲中文无码线在线观看| 欧洲黑大粗无码免费| 国产AV无码专区亚洲AV麻豆丫| 丁香亚洲综合五月天婷婷| 中文在线观看永久免费| 亚洲国产精品一区第二页| 最近中文字幕大全中文字幕免费| 亚洲欧洲视频在线观看| 日本媚薬痉挛在线观看免费| 国产亚洲视频在线观看| 亚洲AV综合色一区二区三区| 精品成在人线AV无码免费看| 亚洲精品乱码久久久久久V| 亚洲av麻豆aⅴ无码电影| 久久久久久久99精品免费观看| 亚洲人成电影网站| 亚洲第一页综合图片自拍| 免费人成在线观看网站品爱网| 国产亚洲sss在线播放| 亚洲国产成人五月综合网| 99热在线精品免费播放6| 亚洲精品第一综合99久久| 狠狠亚洲婷婷综合色香五月排名 | 2019亚洲午夜无码天堂| 亚洲日本中文字幕天堂网| 在线免费观看国产|