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定时器的用法。

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