進階學習Jcrontab

初學Jcrontab感覺非常好,用它來做一個定時程序非常容易,而且方便。有關Jcrontab的介紹和它的定時文件的格式,在前面的那篇文章已經介紹過了,這裏再來講解一下它在程序中的具體應用。在這裏,我們先約定數據源這個概念,“數據源”(我暫且這樣稱呼),它主要是用來由Jcrontab按照定時規則要處理的類和程序,這可以是多個,也可以是一個,我按照Jcrontab提供的方法通常是將它寫到文件中,XML文件或數據庫中。這樣,按照Jcrontab的規則,提供給Jcrontab這些數據源就可以使用Jcrotab的定時功能了。

      根據Jcrontab存儲的不同的數據源,我們可以分成以下幾個:

  • 普通文件來存儲
  • 數據庫存儲
  • XML文件存儲
      在程序中也可以添加要執行的數據源,比如執行本地的應用程序等。下面分別介紹一下。在這之前,先介紹一下有關Jcrontab用到的配置文件:
  • jcrontab.properties配置文件,這是用來啓動Jcrontab的必需文件。在Jcrontab的發佈包中已經有一個完整格式的jcrontab.properties文件了,裏面有它的樣例,我們只需要根據我們自己的應用需要,來使用具體的配置屬性,來構造自己的jcrontab.properties。
  • 還有一個配置文件就是我們自己的定時配置文件。(若我們採用的數據源是文件的話,就需要這個了)這個文件是用來寫負責處理定時程序的,裏面按照規定好的時間來處理規定好的類或類的方法。
  • 若我們採用數據庫存儲數據源的話,那麼,我們就需要配置一個數據庫的信息,在jcrontab.properties文件中已經有一個例子了,我們可以改成我們需要的數據庫配置信息,這個很容易。
  • 若要採用的是XML形式的文件,那麼我們要指定數據源是XML的,同時指定處理XML的解析器,這裏用的是Apache的Xerces。
  • 在程序中隨時可以添加數據源,通過Crontab中的newTask方法,就可以隨時添加。

 

  1. 通過文件記錄數據源
    下面通過例子,我們來講解一個具體的Jcrontab程序,看它是如何定時處理程序的。
    運行程序的JCrontabApp類:
    JCrontabApp類

     import org.jcrontab.Crontab;
    import org.jcrontab.NativeExec;
    import org.jcrontab.SendMail;
    import org.jcrontab.data.CrontabParser;
    import org.jcrontab.data.CrontabEntryBean;
    import org.jcrontab.data.CrontabEntryDAO;
    import java.io.File;

    public class JCrontabApp {
        private static Crontab cron = null;
        private String JcrontabFile = null;

        public JCrontabApp() {
        }

        public String getJcrontabFile() {
            return JcrontabFile;
        }

        public void setJcrontabFile(String jcrontabFile) {
            JcrontabFile = jcrontabFile;
        }

        /**
         * 初始化Jcrontab,通過指定的jcrontab.properties來執行具體的操作
         * 啓動Jcrontab
         */
        protected void init() {
            cron = Crontab.getInstance();
            try {
                ShutdownHook();
                cron.setDaemon(false);
                if (null == JcrontabFile)
                    cron.init();
                cron.init(JcrontabFile);
                System.out.println("Start Jcrontab...");
            } catch (java.lang.Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * 關閉Jcrontab的執行
         * @throws Exception
         */
        protected void ShutdownHook() throws Exception {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    System.out.println("Shutting down...");
                    cron.uninit(200);
                    System.out.println("Stoped Jcrontab!");
                }
            });
        }

        /**
         * 判斷是否是Holiday
         * @return
         * @throws Exception
         */
        public boolean isHoliday()throws Exception{
            return cron.isHoliday();
        }

        /**
         * 根據不同的參數執行不同的定時程序,可選參數可從main方法中查看
         * @param args
         * @throws Exception
         */
        public void exectue(String[] args) throws Exception {
            if (args.length < 2) {
                return;
            }
            this.setJcrontabFile(args[0]);
            init();
            if ("database".equals(args[1]))
                executeDatabase();
            else if ("appliction".equals(args[1])) {
                String[] parameters = new String[args.length-2];
                System.arraycopy(args,2,parameters,0,args.length-2);
                cron.newTask("org.jcrontab.NativeExec","main",parameters);
            } else if ("javamail".equals(args[1]))
                executeJavaMail(args[2]);
        }

        /**
         * 執行數據庫的操作
         * @throws Exception
         */
        protected void executeDatabase() throws Exception {
            CrontabParser cp = new CrontabParser();
            CrontabEntryBean[] ceb = new CrontabEntryBean[2];
            ceb[0] = cp.marshall("* * * * * com.aweb.test.NumTest 123");
            ceb[0].setYears("*");
            ceb[0].setSeconds("0");
            ceb[0].setBusinessDays(true);
            ceb[0].setId(0);

            ceb[1] = cp.marshall("* * * * * com.aweb.test.LetterTest 234");
            ceb[1].setYears("*");
            ceb[1].setSeconds("0");
            ceb[1].setBusinessDays(true);
            ceb[1].setId(1);
            CrontabEntryDAO.getInstance().store(ceb);
        }

        /**
         * 執行本地的應用程序的操作
         * @param parameters
         */
        protected void executeAppliction(String[] parameters) {
            NativeExec.main(parameters);
        }

        /**
         * 將執行的文件發送爲email
         * @param sendFilename
         * @throws Exception
         */
        protected void executeJavaMail(String sendFilename) throws Exception {
            File sendFile = new File(sendFilename);
            SendMail sm = new SendMail();
            sm.send(sendFile);
        }

        /**
         * 主要通過main方法來實現Jcrontab的實現
         * @param args
         * @throws Exception
         */
        public static void main(String args[]) throws Exception {
            if (args.length < 2) {
                System.out.println("Usage:The values of args:<jcrontabfile> <-type> [<parameters>]");
                System.out.println("********************************************************");
                System.out.println("Optional Parameters of type:");
                System.out.println("-filedata:doing file operating.");
                System.out.println("-database:doing database operating.");
                System.out.println("-appliction <command>:doing native application execute.");
                System.out.println("-javamail <sendFile>:doing javamail operating.");
                System.out.println("********************************************************");
                System.exit(1);
            }
            JCrontabApp jp = new JCrontabApp();
            jp.exectue(args);
            System.out.println(jp.isHoliday());
        }
    }


    帶測試運行的NumTest類和LetterTest類:
    NumTest類
     public class NumTest {
        public static void main(String args[]){
            for(int i=0;i<10;i++){
                System.out.println("Time:"+System.currentTimeMillis()+" i= "+i);
            }
        }
    }

     

    LetterTest類
     public class LetterTest {
        public static void main(String args[]) {
            System.out.println("Time: " + System.currentTimeMillis() + " Letter: " + "hello World!");
        }
    }

    配置文件Jcrontab.properties:
    Jcrontab.properties文件 

     ##
    #Mon May 24 19:12:24 CEST 2004
    org.jcrontab.version=2.0.RC1

    org.jcrontab.log.Logger=org.jcrontab.log.Log4JLogger
    org.jcrontab.log.log4J.Properties=log4j.properties

    org.jcrontab.data.file = crontab
    org.jcrontab.data.datasource = org.jcrontab.data.FileSource
    org.jcrontab.Crontab.refreshFrequency = 3

    處理定時程序的crontab文件:
    crontab文件 
    * * * * * com.aweb.test.NumTest
    * * * * * com.aweb.test.LetterTest

    然後,我們在命令行輸入jcrontab.properties文件的位置,和要處理的類型,這裏,我們選filedata,接着運行該類,我們就可以看到它的執行結果:

     [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.log.log4J.Properties : log4j.properties
    [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.version : 2.0.RC1
    [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.Crontab.refreshFrequency : 3
    [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.data.file : crontab.properties
    [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.data.datasource : org.jcrontab.data.FileSource
    [2004-10-19 16:10:20,296 LV:DEBUG CL:jcrontab] org.jcrontab.log.Logger : org.jcrontab.log.Log4JLogger
    Start Jcrontab...

    [2004-10-19 16:10:20,500 LV:DEBUG CL:jcrontab] Interval to sleep : 39984
    [2004-10-19 16:11:00,484 LV: INFO CL:jcrontab] com.aweb.test.NumTest#
    [2004-10-19 16:11:00,484 LV: INFO CL:jcrontab] com.aweb.test.LetterTest#
    [2004-10-19 16:11:00,484 LV:DEBUG CL:jcrontab] Interval to sleep : 60000
    Time:1098173460484 i= 0
    Time:1098173460484 i= 1
    Time:1098173460484 i= 2
    Time:1098173460484 i= 3
    Time:1098173460484 i= 4
    Time:1098173460484 i= 5
    Time:1098173460484 i= 6
    Time:1098173460500 i= 7
    Time:1098173460500 i= 8
    Time:1098173460500 i= 9
    Time: 1098173460515 Letter: hello World!

    這樣每隔一分鐘,就會運行一次NumTest類和LetterTest類
  2. 通過數據庫記錄數據源
    在進行數據庫的操作前,你需要在數據庫中建一張表,這個表在Jcrontab中有它的SQL語句,events表,它的表結構,可以參考Jcrontab提供的SQL語句。我們只需要將crontab文件中的屬性做一下修改就可以了
    修改後的crontab文件:
     crontab文件

    增加下面的屬性:

    org.jcrontab.data.GenericSQLSource.driver = org.gjt.mm.mysql.Driver
    org.jcrontab.data.GenericSQLSource.url = jdbc:mysql://127.0.0.1/netbook
    org.jcrontab.data.GenericSQLSource.username = root
    org.jcrontab.data.GenericSQLSource.password =
    org.jcrontab.data.datasource = org.jcrontab.data.GenericSQLSource

    這樣,我們再在命令行下輸入jcrontab.properties文件的位置,和要處理的類型,這裏,我們選database,就可以執行我們寫好的兩個類了。運行時,它是先將這兩個待處理的類的數據源,按照規定好的數據庫中的字段,一一存入數據庫中,然後再從數據庫中讀取events表中的每一行(這每一行就是待處理的數據源),它就根據這些行定時處理。執行的結果同上。
  3. 通過XML來存儲數據源
    其實和文件存儲差不多,主要這裏要用到XML的解析器,這裏用的是Apache Xerces來處理的,其它的都一樣。
    修改後的crontab文件:
     crontab文件

    去掉原來的crontab文件中的信息,加上下面的屬性

    org.jcrontab.data.file = crontab.xml
    org.xml.sax.driver=org.apache.xerces.parsers.SAXParser
    org.jcrontab.data.datasource=org.jcrontab.data.XMLSource

    同樣在命令行下輸入jcrontab.properties文件的位置,和要處理的類型,這裏和文件的一樣選filedata,來運行該類,執行結果同上。
  4. 定時處理程序,還可以用來處理本地的應用程序
    根據系統的不同,可以處理不同的應用程序,比如:執行ping的命令,那麼你就可以調用Jcrontab中已經寫好的NativeExec類來執行即可。它主要負責處理本地系統上的應用程序。我們在XML文件中添加一條記錄,就可以實現了。
    修改後的crontab文件:
     crontab.xml文件
     <?xml version="1.0" encoding="GB2312"?>
    <!DOCTYPE crontab SYSTEM "crontab.dtd">
    <crontab>
    <crontabentry id="0">
     <seconds>0</seconds>
     <minutes>*</minutes>
     <hours>*</hours>
     <daysofmonth>*</daysofmonth>
     <months>*</months>
     <daysofweek>*</daysofweek>
     <years>*</years>
     <bussinesdays>true</bussinesdays>
     <startDate>null</startDate>
     <endDate>null</endDate>
     <class>com.aweb.test.NumTest</class>
     <method>main</method>
     <description>null</description>
    </crontabentry>
    <crontabentry id="1">
     <seconds>0</seconds>
     <minutes>*</minutes>
     <hours>*</hours>
     <daysofmonth>*</daysofmonth>
     <months>*</months>
     <daysofweek>*</daysofweek>
     <years>*</years>
     <bussinesdays>true</bussinesdays>
     <startDate>null</startDate>
     <endDate>null</endDate>
     <class>com.aweb.test.LetterTest</class>
     <method>main</method>
     <description>null</description>
    </crontabentry>
    <crontabentry id="2">
     <seconds>0</seconds>
     <minutes>*</minutes>
     <hours>*</hours>
     <daysofmonth>*</daysofmonth>
     <months>*</months>
     <daysofweek>*</daysofweek>
     <years>*</years>
     <bussinesdays>true</bussinesdays>
     <startDate>null</startDate>
     <endDate>null</endDate>
     <class>org.jcrontab.NativeExec</class>
     <method>main</method>
     <parameters>net send 192.168.0.109 "你好!每一分鐘出現一次!呵呵"</parameters>
     <description>null</description>
    </crontabentry>
    </crontab>
    這樣執行的結果就是每隔一分鐘就會執行一次net send命令(是不是裝了個定時炸彈呀!呵呵,不過是在服務器端才運行的喲!)。
  5. 通過Email來發送執行的數據源
    在Jcrontab中提供了JavaMail的功能,你可以用JavaMail來實現上面同樣的功能。你只需要修改一下配置文件
    修改後的crontab文件:
     crontab文件

    增加下面的屬性

    [email protected]
    [email protected]
    org.jcrontab.SendMail.smtp.host=smtp.sohu.com
    org.jcrontab.SendMail.smtp.username= yourname
    org.jcrontab.SendMail.smtp.password=password

    這樣它就會將執行的數據源發送到你的郵箱中。不過,目前這個我沒有測試成功,我認爲主要是由於郵件服務器的原因吧,它總是出現JavaMail的運行異常。程序方面應該不會有問題,這需要我在以後的學習中繼續來完成,也希望大家幫我實現這個功能!

總結:Jcrontab提供的定時處理程序的功能不單單是這些,還可以定時處理EJB等高級的組件,在應用服務器中也可以採用Servlet的方式來定時處理(個人感覺:它提供的用Servlet來定時處理程序的功能不太好!大家去慢慢體會吧!)。還有一些其它方面的功能,還需要繼續的學習和探索!

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章