1. 程式人生 > >quartz執行兩次

quartz執行兩次

在現在的專案中發現Quartz執行了兩次,在網上找到下列解決方案,我是用的第一種,灰常感謝這位哥們,轉自:http://my.oschina.net/EugeneQiu/blog/265040?p=1
很多人在使用spring的Quartz配置定時任務時,會發現每次定時時間到達後,指定的定時方法同時執行了兩次。

解決quartz定時任務被觸發兩次的問題:
其中告訴tomcat,在啟動的時候載入webapps下的所有專案工程檔案,又讓tomcat再載入了一遍(一般情況下配置,主要是由於想域名訪問時將工程名去掉的原因配置),這種情況下會導致工程中的quartz定時被兩次觸發,執行兩次。
‘’裡面的改成 autoDeploy=”false” deployOnStartup=”false” 這樣就可以避免tomcat伺服器中自啟動導致quartz定時任務被觸發兩次。(當然還可以按需求修改,畢竟每個專案的需求都不盡相同。)
1.autodeploy屬性值設定為false,如果此項設為true,表示Tomcat服務處於執行狀態時,能夠監測appBase下的檔案,如果有新有web應用加入進來,會自運釋出這個WEB應用,設成false就不會。
2.增加deployOnStartup=”false”,表示Tomcat伺服器啟動時, 不會自動釋出appBase目錄下所有的Web應用。
這樣的話,在tomcat啟動時,不會自動釋出appBase下的應用,啟動後也不會自動發步appBase下的應用。

<Host name="localhost"  appBase="webapps"  unpackWARs="true" autoDeploy="false" deployOnStartup="false">

    <Context path="" docBase="/eugeneqiu_test" debug="0" reloadable="true"/>
</Host>

當然網路上也有另外一種配置方法:
就是在Context裡面修改 docBase加上“/webapps”路徑,當然專案訪問路徑就變為http://localhost/eugeneqiu_test

了,看見專案名實在是難受,我就沒用這方法了。

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

    <Context path="" docBase="/webapps/eugeneqiu_test" debug="0" reloadable="true"/>

      </Host>

解決quartz定時任務被觸發兩次的問題
方法1.通過改TOMCAT的配置檔案server.xml配置
方法2.先把quartz配置資訊提取出來,單獨存成一個檔案,比如applicationContext-quartz.xml 然後修改web.xml,讓web容器啟動時,可以載入該檔案 。(此文沒對此方法進行深入探究)
附帶:quartz的測試用例

java測試用例程式碼1:

package com.eugeneqiu_test.test;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
/**
 * 每5秒自動執行
 * @author EugeneQiu
 */
public class Every5s{
    public static void orderEveryhour(String[] args) throws SchedulerException {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        JobDetail jobDetail = JobBuilder.newJob()
                .ofType(Test.class)
                .usingJobData("Test1","Quartz")
                .withIdentity("Test1","Group1")
                .build();//通過JobBuilder構建JobDetailImpl 例項,也可以直接new JobDetailImpl
        Trigger trigger = TriggerBuilder.newTrigger()                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))  //還有更多時間格式,詳情可以百度一下
                .forJob("Test1","Group1")//Trigger找到對應的名稱為Test1組為Group1的Job,如果不存在則會在執行scheduler.scheduleJob(jobDetail,trigger);報錯
                .build();//通過TriggerBuilder構建CronTriggerImpl例項,也可以直接new CronTriggerImpl
        scheduler.scheduleJob(jobDetail,trigger);//任務每5秒觸發一次
        scheduler.start();
    }
}
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {      
         System.out.println("Hello 要開始自動執行嘍~~~~~~" );
         //testSomething(); //這裡可以寫一下想定時執行的方法
         System.out.println("Hello 自動執行結束~~~~~");
    }

第二種解決方案另外一位哥們寫得更好些,如下轉自:http://blog.csdn.net/tengdazhang770960436/article/details/46909845
最近用Spring的quartz定時器的時候,發現到時間後,任務總是重複執行兩次,在tomcat或jboss下都如此。
打印出他們的hashcode,發現是不一樣的,也就是說,在web容器啟動的時候,重複啟了兩個quartz執行緒。
研究下來發現quartz確實會載入兩次:
第一次:web容器啟動的時候,讀取applicationContext.xml檔案時,會載入一次。
第二次:Spring本身會載入applicationContext.xml一次。
而我的quartz配置就是寫在applicationContext.xml檔案裡的。
解決辦法很簡單
先把quartz配置資訊提取出來,單獨存成一個檔案,比如applicationContext-quartz.xml
然後修改web.xml,讓web容器啟動時,可以載入該檔案
這樣quartz只會在web容器啟動時載入一次,Spring不會再載入了。

web.xml配置如下:

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/applicationContext.xml,/WEB-INF/classes/applicationContext-timertask.xml</param-value>
  </context-param>
  <!-- 開啟監聽 -->
  <listener>
      <listener-class>
          org.springframework.web.context.ContextLoaderListener
      </listener-class>
  </listener>

把定時器的配置單獨寫成一個配置檔案,在web容器啟動的時候只加載一次
本人嘗試了第一種方法和第二種方法,第一種方法起效,但是第二種方法沒有解決,所以建議使用第一種