隨筆-37  評論-3271  文章-0  trackbacks-0

          計時器和工作管理器 API (CommonJ) 編程人員指南
          ?

          本文整理自 WebLogic 10.0中文文檔。

          更多CommonJ規范的信息參考:http://www.ibm.com/developerworks/library/specification/j-commonj-sdowmt/index.html

          計時器和工作管理器 API

          此文檔概述計時器和工作管理器 API,并說明其在應用程序中的實現方法。

          ? ?

          計時器和工作管理器 API 的描述

          計時器和工作管理器 API 是按照 BEA Systems IBM 共同創建的規范進行定義的。通過此 API,可以并發編寫在 Java EE 應用程序中的 EJB Servlet 程序。此 API 經常被稱為 CommonJ

          CommonJ API 包含下列組件:

          雖然 commonj.timer commonj.work 屬于同一個 API 的一部分,但它們的功能卻各不相同。您可以根據應用程序的特定需要實現其中的一種。CommonJ 計時器 API 適用于按特定間隔調度工作的情形;例如,您知道某一項作業應在特定時間運行的情形。而 CommonJ 工作 API 適用于根據優先級處理工作的情形。例如,您不能準確預測一項特定作業的發生時間,而是希望這項作業被賦予更高或更低的優先級。

          下列部分將詳細描述 CommonJ API

          ? ?

          計時器 API 概述

          計時器 API 包含以下三個接口:

          計時器管理器提供在受管環境中創建和使用計時器的框架。計時器監聽器接收計時器通知。TimerManager.schedule() 方法用于調度 TimerListener,使其在特定時間或間隔運行。

          有關如何實現計時器的詳細描述,請參閱使用計時器 API

          TimerManager 接口

          TimerManager 接口在應用程序中提供常規調度框架。受管的環境可以支持多個 TimerManager 實例。這就是說,一個應用程序可以包含多個 TimerManager 實例。

          創建和配置計時器管理器

          可通過部署描述符在部署期間配置 TimerManagerTimerManager 定義還可以包含其他實現特定的配置信息。

          一旦在部署描述符中定義了 TimerManager,您就可以在本地 Java 環境中使用 JNDI 查找訪問它的實例。每次調用 JNDI lookup() 訪問 TimerManager 時,都將返回 TimerManager 的一個新邏輯實例。

          TimerManager 接口是線程安全的。

          有關使用 JNDI 的詳細信息,請參閱"WebLogic JNDI 編程"

          掛起 TimerManager

          可使用 suspend() resume() 方法,掛起和恢復 TimerManager。當掛起 TimerManager 時,所有待定的計時器將延遲到 TimerManager 恢復時為止。

          停止 TimerManager

          可使用 stop() 方法停止 TimerManager。在調用 stop() 方法后,所有活動的計時器都將停止,而且 TimerManager 實例將停止監視所有 TimerListener 實例。

          TimerListener 接口

          使用?commonj.timers?包的所有應用程序都需要實現 TimerListener 接口。

          Timer 接口

          當通過 TimerManager 調度計時器時,將返回 Timer 接口的實例。

          ? ?

          使用計時器 API

          此部分將簡述在應用程序中使用計時器 API 時的必需步驟。

          在部署應用程序前,確保已創建了包含計時器管理器資源引用的部署描述符。

          這樣可以通過 JNDI 訪問 TimerManager。有關 JNDI 查找的詳細信息,請參閱"WebLogic JNDI 編程"

          下面描述計時器 API 的實現過程:

          1. IntialContext inctxt = new InitialContext();

            有關 JNDI 查找的詳細信息,請參閱"WebLogic JNDI 編程"

          2. TimerManager mgr = (TimerManager)ctx.lookup(`java:comp/env/timer/MyTimer');

            在此語句中,將 JNDI 查找結果強制轉換成 TimerManager

          3. TimerListener listener = new StockQuoteTimerListener(`abc', `example');

          4. mgr.schedule(listener, 0, 1000*60)

            schedule() 方法返回計時器對象。

          5. public void timerExpired(Timer timer) {
            ?????//此方法執行
            ?????//
            業務邏輯

            }

          計時器管理器示例

          package examples.servlets;
          import java.io.IOException;
          import java.io.PrintWriter;

          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import javax.naming.InitialContext;
          import javax.naming.NamingException;

          import commonj.timers.*;

          /**
          * TimerServlet 演示了 commonj 計時器的簡單使用
          */
          public class TimerServlet extends HttpServlet {

          /**
          ??*
          非常簡單地實現服務方法
          ??*
          該實現安排了 commonj 計時器。
          ??*/
          ??public void service(HttpServletRequest req, HttpServletResponse res)
          ????throws IOException
          ??{
          ????res.setContentType("text/html");
          ????PrintWriter out = res.getWriter();
          ????try {
          ??????InitialContext ic = new InitialContext();
          ??????TimerManager tm = (TimerManager)ic.lookup
          ????????("java:comp/env/tm/default");
          ??????//
          立即開始每 10 秒執行一次計時器
          ??????tm.schedule (new MyTimerListener(), 0, 10*1000);
          ??????out.println("<h4>Timer scheduled!</h4>");
          ????} catch (NamingException ne) {
          ??????ne.printStackTrace();
          ??????out.println("<h4>Timer schedule failed!</h4>");
          ????}
          ??}

          ??private static class MyTimerListener implements TimerListener {
          ????public void timerExpired(Timer timer) {
          ??????System.out.println("timer expired called on " + timer);
          ??????//
          此處一些有用的工作...
          ??????//
          只取消計時器
          ??????System.out.println("cancelling timer ...");
          ??????timer.cancel();
          ????}
          ??}
          }

          ? ?

          使用作業調度程序

          此部分描述作業調度程序功能的用法。通過作業調度程序,您可以在群集環境中實現 commonj.timer API

          作業調度程序實際上就是可以在群集中使用的 commonj.timer API 包的實現。在此上下文,作業被定義為要提交給作業調度程序進行執行的 commonj.timers.TimerListener 實例。

          本部分包含下列主題:

          計時器的生命周期

          在應用程序中實現 commonj.timer API 時,可以為計時器配置兩種可能的生命周期。

          每一計時器有其自己的優缺點。本地計時器能以短得多的作業處理時間間隔處理作業。由于群集有持久性要求,因此作業調度程序不能如此精確地處理作業。另一方面,作業調度程序更適合于在即使創建任務的初始服務器出現故障的情況下也必須執行的任務。

          實現和配置作業調度程序

          此部分將簡述在應用程序中實現作業調度程序的基本過程以及配置 WebLogic Server 環境以利用作業調度程序的基本過程。

          數據庫配置

          為了維持持久性,并使計時器支持群集,作業調度程序需要數據庫連接。作業調度程序功能與服務器遷移支持相同的數據庫供應商和版本。

          為方便起見,可與會話持久性、服務器遷移等使用相同的數據庫。

          在數據庫中,必須基于以下模式創建一個稱為 WEBLOGIC_TIMERS 的表:

          CREATE TABLE WEBLOGIC_TIMERS (
          ??TIMER_ID VARCHAR2(100) NOT NULL,
          ??LISTENER BLOB NOT NULL,
          ??START_TIME NUMBER NOT NULL,
          ??INTERVAL NUMBER NOT NULL,
          ??TIMER_MANAGER_NAME VARCHAR2(100) NOT NULL,
          ??DOMAIN_NAME VARCHAR2(100) NOT NULL,
          ??CLUSTER_NAME VARCHAR2(100) NOT NULL,
          ??CONSTRAINT SYS_C00323062 PRIMARY KEY(TIMER_ID, CLUSTER_NAME, DOMAIN_NAME)
          )

          數據源配置

          在創建了采用所需模式的表之后,必須定義一個可在群集配置內引用的數據源。只有為 Cluster MBean DataSourceForJobScheduler 特性定義了有效數據源后,才能使用作業調度程序功能。您可以在 WebLogic Server 管理控制臺對此進行配置。

          以下的代碼摘自 config.xml,用于說明對此進行定義的方法:

          <domain>
          ...
          ?<cluster>
          ??<name>Cluster-0</name>
          ??<multicast-address>239.192.0.0</multicast-address>
          ??<multicast-port>7466</multicast-port>
          ??<data-source-for-job-scheduler>JDBC Data ????Source-0</data-source-for-job-scheduler>
          ?</cluster>
          ...
          ?<jdbc-system-resource>
          ??<name>JDBC Data Source-0</name>
          ??<target>myserver,server-0</target>
          ??<descriptor-file-name>jdbc/JDBC_Data_Source-0-3407-jdbc.xml</descriptor-????file-name>
          ?</jdbc-system-resource>
          </domain>

          作業調度程序中的 JNDI 訪問

          與常規 commonj.timer API 相比,在群集計時器中執行 JNDI 查找的過程有所不同。下面的代碼段說明如何將 JNDI 查找強制轉換成 TimerManager

          InitialContext ic = new InitialContext();
          commonj.timers.TimerManager jobScheduler =(common.timers.TimerManager)ic.lookup
          ???("weblogic.JobScheduler");
          commonj.timers.TimerListener timerListener = new MySerializableTimerListener();
          jobScheduler.schedule(timerListener, 0, 30*1000);
          // 30 秒執行一次此作業

          不支持的方法和接口

          作業調度程序環境并非支持 commonj.timer API 的所有方法和接口。不支持下列方法和接口:

          ? ?

          工作管理器 API 的描述

          工作管理器 (commonj.work) API 提供的接口允許應用程序在一個容器中并發地執行多個工作項。

          實際上,此 API 就是 java.lang.Thread API 的容器管理替代方法。java.lang.Thread API 不適用于受管 Java EE 環境中承載的應用程序。在這樣的環境中,工作管理器 API 替代方法的效果更好,因為它允許容器全面查看和控制所有執行線程。

          注意:

          工作管理器 API 不提供故障轉移和持久性機制。如果受管服務器環境出現故障或關閉,則當前所有工作都將丟失。

          工作管理器接口

          此部分概述工作管理器 API 中定義的接口。有關使用這些接口的詳細信息,請參閱?commonj.work package? javadoc

          工作管理器 API 包含下列接口:

          注意:

          WorkListener 實例總與通過 WorkManager 調度 Work 的初始線程在同一個 JVM 中執行。

          工作管理器部署

          在適當部署描述符中通過 resource-ref 在服務器級別定義工作管理器。在其他描述符中可以是?web.xml?ejb-jar.xml

          下面的部署描述符片段說明如何配置 WorkManager



          <resource-ref>
          ???<res-ref-name>wm/MyWorkManager</res-ref-name>
          ???<res-type>commonj.work.WorkManager</res-type>
          ???<res-auth>Container</res-auth>
          ???<res-sharing-scope>Shareable</res-sharing-scope>
          </resource-ref>
          ...

          注意:

          建議您為 WorkManager 對象的 JNDI 名稱空間使用前綴?java:comp/env/wm

          ? ?

          工作管理器示例

          此部分的工作代碼示例在 HTTP Servlet 中使用 CommonJ 工作管理器。

          import java.io.IOException;
          import java.io.PrintWriter;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import javax.naming.InitialContext;
          import javax.naming.NamingException;

          import weblogic.work.ExecuteThread;
          import commonj.work.WorkManager;
          import commonj.work.Work;
          import commonj.work.WorkException;

          public class HelloWorldServlet extends HttpServlet {

          ???public void service(HttpServletRequest req, HttpServletResponse res)
          ??????throws IOException
          ???{
          ??????res.setContentType("text/html");
          ??????PrintWriter out = res.getWriter();


          ??????try {
          ?????????InitialContext ic = new InitialContext();
          ?????????System.out.println("## [servlet] executing in: " +
          ????????????((ExecuteThread)Thread.currentThread()).getWorkManager()
          ????????????.getName());
          ?????????WorkManager wm = (WorkManager)ic.lookup
          ????????????("java:comp/env/foo-servlet");
          ?????????System.out.println("## got Java EE work manager !!!!");
          ?????????wm.schedule(new Work(){
          ?????????public void run() {
          ?????????ExecuteThread th = (ExecuteThread) Thread.currentThread();
          ?????????System.out.println("## [servlet] self-tuning workmanager: " +
          ???????????th.getWorkManager().getName());
          ?????????}
          ?????????public void release() {}

          ?????????public boolean isDaemon() {return false;}
          ?????????});
          }
          catch (NamingException ne) {
          ?????????ne.printStackTrace();}

          catch (WorkException e) {
          ?????????e.printStackTrace();
          }

          out.println("<h4>Hello World!</h4>");
          // 不要關閉輸出流 - 而是啟用 servlet 引擎關閉輸出流
          //
          以實現更佳性能。
          System.out.println("finished execution");}

          }

          ?

          主站蜘蛛池模板: 沂南县| 澎湖县| 高台县| 浠水县| 九龙县| 枣庄市| 吴堡县| 丰城市| 子长县| 乌拉特中旗| 邯郸市| 海盐县| 正安县| 两当县| 杂多县| 衡水市| 宣化县| 长治市| 宁德市| 寻乌县| 凌海市| 张家口市| 维西| 永清县| 鄂州市| 聊城市| 喀喇沁旗| 吐鲁番市| 彭州市| 闽侯县| 富民县| 大悟县| 浪卡子县| 双辽市| 宣恩县| 曲麻莱县| 普兰店市| 潢川县| 习水县| 合作市| 黄大仙区|