兩種方式實現java定時器,使用quartz定時器框架和java自帶Timer定時器,編寫定時任務

    開啓定時任務的方式有幾種:包括quartz定時框架和java自帶Timer定時器,區別在於,quartz定時任務在程序報錯後能不斷執行,而在Timer定時任務中,程序一旦報錯,定時任務即不再執行,可根據需求選用。

    前兩天工作需求,需要寫個定時任務去跑一些數據,我首先選擇的就是quartz定時器,不過後來因爲環境問題而改用了Timer定時器,下面簡單介紹一下兩種定時器的書寫。

    1,quaetz定時器,需要在applicationContext.xml中進行一些配置,代碼如下:

    <!-- 實現定時器任務-要調度的對象 -->  
   <bean id="jobBean" class="com.mer.listener.job.TimerJob" />
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
        <property name="targetObject" ref="jobBean" />  
        <property name="targetMethod" value="execute" />  
        <!-- 將併發設置爲false -->  
        <property name="concurrent" value="false" />  
    </bean>  
 
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
        <property name="jobDetail" ref="jobDetail" />  
       <!--  定時任務,每天凌晨2點執行一次   -->
      <!--   <property name="cronExpression" value="0 0 2 * * ?"  />   -->
        <property name="cronExpression" value="0/5 * * * * ?"  />  
    </bean>  
  
     <!-- 總管理類如果將lazy-init='false'那麼容器啓動就會執行調度程序     -->
    <bean id="startQuertz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" >  
        <property name="triggers">  
            <list>  
               <!--  作業調度器,list下可加入其他的調度器   -->
                <ref bean="trigger" />  
            </list>  
        </property>  
    </bean>  

<!-- 注入工具類,普通類中能夠調用server層方法 -->
<!-- <bean id="springContextUtil" class="com.mer.util.SpringContextUtil"></bean> -->

<bean id="springBeanFactoryUtils" class="com.mer.util.SpringBeanFactoryUtils"/>

       配置完成後,只需在TimerJob中完成相關邏輯代碼即可,execute方法即爲定時任務執行方法,我的TimerJob類如下:

package com.mer.listener.job;

import org.springframework.context.ApplicationContext;
import com.mer.service.BaseService;
import com.mer.service.cailanzidb.TranddelService;
import com.mer.util.LogUtil;
import com.mer.util.SpringBeanFactoryUtils;
import com.mer.util.SpringContextUtil;

public class TimerJob{

        //使用工具類獲取bean,在普通類中調用service

BaseService baseService = (BaseService)SpringBeanFactoryUtils.getBean("baseServiceImpl");
LogUtil log = new LogUtil();
        public void execute(){  
        try {
    //菜市場 市區 查看數據功能    每天定時錄入交易數據到彙總表
        System.out.println("定時器-----定時錄入交易彙總表");
        baseService.insert("transInsertGM");
        baseService.insert("transInsertFJ");
        baseService.insert("transInsertDM");
} catch (Exception e) {
log.errinfoe("執行定時器導入菜市場數據報錯", e);
e.printStackTrace();
}
            }  
    }

}

    上面的quartz定時器就寫好了,最後別忘了導入quartz定時器的相關jar包哦,下面說一下我遇到的一個坑,這裏不屬於定時器編寫範圍。

        因爲業務需求,定時器裏要調用service層的相關方法跑數據,但是因爲此類爲普通類,不能直接通過註解直接注入service,如果直接使用的花,會報錯baseService空指針。因此需要另外寫一個工具類,工具類代碼如下:

package com.mer.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 普通類調用Spring註解方式的Service層bean
 * Created by HZC on 2015/10/21.
 */
public class SpringBeanFactoryUtils implements ApplicationContextAware {
    private static ApplicationContext appCtx;

    /**
     * 此方法可以把ApplicationContext對象inject到當前類中作爲一個靜態成員變量。
     *
     * @param applicationContext ApplicationContext 對象.
     * @throws BeansException
     * @author hzc
     */

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        appCtx = applicationContext;
    }

    /**
     * 獲取ApplicationContext
     *
     * @return
     * @author hzc
     */
    public static ApplicationContext getApplicationContext() {
        return appCtx;
    }

    /**
     * 這是一個便利的方法,幫助我們快速得到一個BEAN
     *
     * @param beanName bean的名字
     * @return 返回一個bean對象
     * @author hzc
     */
    public static Object getBean(String beanName) {
        return appCtx.getBean(beanName);
    }

}

    此工具類需要在applicationContext.xml配置裏添加一行配置,如下:

        <!-- 注入工具類,普通類中能夠調用server層方法 -->
<bean id="springBeanFactoryUtils" class="com.mer.util.SpringBeanFactoryUtils"/>

    如果有遇到相同問題的小夥伴,可以借鑑一下這個工具類,親測可用。

2,好了,上面是使用quartz定時框架寫定時任務,下面講一下怎麼用java自帶的Timer定時器寫定時任務,

    Timer定時器用到的是litener監聽器,所以需要在web.xml中將需要監聽的定時任務加入定時器,配置如下:

  <listener>
    <listener-class>com.mer.conn.InitServletListener</listener-class>
  </listener>

    然後在監聽類InitServletListener中完成相關代碼,如下:

package com.mer.conn;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.mer.service.cailanzidb.TranddelService;
import com.mer.util.LogUtil;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
 * 
 *********************************************************.<br>
 * [類名] InitServletListener <br>
 * [描述] 項目初始化監聽器 <br>
 * [作者] gw <br>
 * [時間] 2016-1-9 下午9:48:07 <br>
 *********************************************************.<br>
 */
public class InitServletListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
}

public void contextInitialized(ServletContextEvent sce) {
//獲取service
WebApplicationContext applicationContext =  WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());  
final TranddelService tranddelService= (TranddelService) applicationContext.getBean("tranddelService");
LogUtil log = new LogUtil();
try {
//設置TimerTask
TimerTask task = new TimerTask() {
@SuppressWarnings("static-access")
@Override
public void run() {
    //菜市場 市區 查看數據功能    每天定時錄入交易數據到彙總表
            System.out.println("定時器-----定時錄入交易彙總表");
            tranddelService.insert("transInsertGM");
            tranddelService.insert("transInsertFJ");
            tranddelService.insert("transInsertDM");
}
};
int dateSpan=24*60*60*1000;
//設置執行時間
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH)+1;//每天
//定製每天定時執行一次
calendar.set(year, month, day, 17,59,00);    //時間設置 後三位是時分秒
Date date = calendar.getTime();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));
Timer timer = new Timer();
//每天的date時刻執行task, 僅執行一次
timer.schedule(task, date,dateSpan);
Thread.sleep(1000);      //延遲一秒執行
} catch (Exception e) {
log.errinfoe("執行定時器導入菜市場數據報錯", e);
e.printStackTrace();
}
}
}

    項目啓動初始化監聽器之後,即進行了任務監聽。

    後語:假如你跟我一樣有業務需求,要通過普通類調用service層或dao層方法,建議使用Timer定時器,因爲Timer和quartz的管理容器不同,所以在進行bean注入時,使用quartz會出現一些框架知識方面的坑,對此方面理解不太深的小夥伴,還是選擇Timer比較保險,比如我哈。


發佈了28 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章