Spring+TimerTask定時器的用法實例

Spring支持jdk內置的Timer類和Quartz Scheduler,以下先介紹jdk內置的TimerTask用法。我將在下一次的博客中介紹Quartz Scheduler的用法。

在tomcat服務啓動,spring定時器容器加載時會執行定時器裏的任務,可設置時間間隔和延遲執行時間。本例子以定時加載數據庫中的數據字典爲例。

功能描述:

在數據庫中有如下結構的一張數據字典表,用來存儲公共的且數據量不大的一些基本信息。

具體做法如下:

一、定時器java代碼:

1、定義數據字典的實體類,並給get和set方法:

public class Dictionary {

    private String dictype; // 字典類型

    private String dictype_desc;// DIC_TYPE_DESC

    private String diccode;// 字典代碼

    private String dicvalue;// DIC_VALUE

    public String getDictype() {
        return dictype;
    }

    public void setDictype(String dictype) {
        this.dictype = dictype;
    }

    public String getDictype_desc() {
        return dictype_desc;
    }

    public void setDictype_desc(String dictype_desc) {
        this.dictype_desc = dictype_desc;
    }

    public String getDiccode() {
        return diccode;
    }

    public void setDiccode(String diccode) {
        this.diccode = diccode;
    }

    public String getDicvalue() {
        return dicvalue;
    }

    public void setDicvalue(String dicvalue) {
        this.dicvalue = dicvalue;
    }

    public void Dictionary() {
    }
}

2、定義數據的存取格式:將通過select * from ris_dic_tab 得到的list轉換成map型數據

public class GroupByList
{

    private static Logger logger = Logger.getLogger(GroupByList.class);

    /**
     * 將list 裝換爲 map,map的key爲需要按照分組的值。
     * @param <T> 泛型對象
     * @param objList 泛型集合
     * @param key 按照對象中,某個字段分組
     * @return
     */
    public static <T> Map<String, List<T>> convertMapGroupByList(
            List<T> objList, String key)
    {
        Map<String, List<T>> map = new HashMap<String, List<T>>();
        if (null == objList || 0 == objList.size())
        {
            return null;
        }

        List<T> list = null;
        for (Iterator<T> it = objList.iterator(); it.hasNext();)
        {
            T obj = (T) it.next();
            String mapKey = getInvokeValue(obj, key);
            if (map.containsKey(mapKey))
            { // 存在相同KEY
                list = map.get(mapKey);
                list.add(obj);
                map.put(mapKey, list);
            }
            else
            {
                list = new ArrayList<T>(); // 重新聲明一個list
                list.add(obj);
                map.put(mapKey, list);
            }
        }
        return map;
    }

    private static <T> String getInvokeValue(T obj, String key)
    {
        String returnValue = "";
        key = ("get" + key).toUpperCase();
        try
        {
            Method[] ms = obj.getClass().getDeclaredMethods();

            for (Method method : ms)
            {
                if (key.equals(method.getName().toUpperCase()))
                {
                    Object value = method.invoke(obj, new Object[] {});
                    returnValue = String.valueOf(value);
                }
            }
        }
        catch (Exception e)
        {
            logger.error("將字符串映射成方法時出錯,", e);
        }
        return returnValue;
    }
}


3、定義數據類型的實體類

public final class DictionaryCacheMap
{
    private static Logger logger = Logger.getLogger(DictionaryCacheMap.class);
    
    private Map<String, List<Dictionary>> mulMap = new Hashtable<String, List<Dictionary>>();

    public Map<String, Dictionary> sigleMap = new Hashtable<String, Dictionary>();

    private List<Dictionary> dictionaryList;

    public synchronized void reset(List<Dictionary> dictionaryList)
    {
        try
        {
            this.dictionaryList = dictionaryList;
            mulMap.clear();
            mulMap = GroupByList.convertMapGroupByList(dictionaryList,
                    "dictype");
        }
        catch (Throwable e)
        {
            logger.error(e.getMessage(), e);
        }
    }

    public synchronized Dictionary getDictionary(String key)
    {
        if (null != this.dictionaryList)
        {
            for (Dictionary dic : this.dictionaryList)
            {
                sigleMap.put(dic.getDictype().concat(dic.getDiccode()), dic);
            }
        }
        return sigleMap.get(key);
    }

    public synchronized List<Dictionary> getDictionaryList(String type)
    {
        return mulMap.get(type);
    }
}

4、定義TimerTask類,並重寫啓動run方法(因爲我是使用SSI框架,所以直接在此注入配置的SqlMapDao,有框架基礎的應該都能看明白哦)

public class DictionaryTimerTask extends TimerTask
{
    private final Log log = LogFactory.getLog(this.getClass());
    
    public static DictionaryCacheMap tmepCacheMap = new DictionaryCacheMap();
    
    private SqlMapDao dao;
    
    @Override
    public void run() //這個方法是TimerTask的核心
    {
        try {
            if (log.isDebugEnabled()) {
                log.debug("開始加載數據字典數據");
            }
            // 加載指令信息內容至緩存
            List<Dictionary> dicList = (List<Dictionary>) dao.getObjects("User.getDictionaryInfo",
                    null);

            tmepCacheMap.reset(dicList);
            
            if (log.isDebugEnabled()) {
                log.debug("總共:" + dicList.size() + "條數據");
                log.debug("結束加載數據字典數據");
            }
        } catch (Throwable e) {
            log.error("刷新數據字典內容出錯:", e);
        }
    }
    public SqlMapDao getDao()
    {
        return dao;
    }
    public void setDao(SqlMapDao dao)
    {
        this.dao = dao;
    }
}

二、配置定時器的spring

1、配置timerTask的bean,並將配置好的dao注入到其中(第三個java類中用到了)

<bean id="timerTask" class="com.neusoft.integrated.commont.task.DictionaryTimerTask" scope="prototype">
        <property name="dao" ref="dao" />
</bean>

2、配置好調度相關的參數

<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
	<property name="timerTask" ref="timerTask" /><!-- 指定調度任務 -->
	<property name="delay" value="1000" /><!-- 延遲時間,單位爲毫秒 -->
	<property name="period" value="300000" /><!-- 週期時間,單位爲毫秒 -->
</bean>

3、將設置好的相關參數託管給spring
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
	<property name="scheduledTimerTasks">
		<list>
		        <ref bean="scheduledTask" />
		</list>
	</property>
</bean>


三、通過以上步驟,在web啓動成功後,聲明一個DictionaryCacheMap的變量,就能獲取到一個map型的數據數據結果集,如果更新表後將會在5分鐘後直接更新。

通過以下獲取map中的值:

1、聲明變量DictionaryCacheMap:private DictionaryCacheMap map = DictionaryTimerTask.tmepCacheMap;

2、聲明用來存儲想要結果的變量:private List<Dictionary> bwayList;

3、直接通過map的取值方式獲取相應的結果:bwayList = map.getDictionaryList("040");

如此就能獲取到key是040的結果集。

敬請期待下一次博客:Quartz Scheduler定時器的用法。

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