zoukankan      html  css  js  c++  java
  • 用泛型写Redis缓存与数据库操作工具类

      功能描述: 先从缓存获取数据,如果缓存没有,就从数据库获取数据,并设置到缓存中,返回数据。

            如果数据库中没有数据,需要设置一个缓存标记flagKey,防止暴击访问数据库,用缓存保护数据库。

            当删除缓存key时,需要同时删除flagKey,保证数据库可被访问。

      关于java泛型的知识点,这里就跳过了。不理解的就自己去百度一下。

      直接上代码:

    1.先定义泛型接口,用于写从数据库获取数据的方法。

    /**
     * 普通数据获取器
     * 
     */
    public interface DataGeter<T> {
    
        /**
         * 获取数据接口
         * @return
         */
        public T getData();
    }

    2.工具类。有一些方法需要自己写,看注释。

    public class DataUtil {
    
        /**json转换工具*/
        private static Gson gson = new Gson();
        
        /**一天的过期秒数*/
        private static final int ONE_DAY_EXPIRE_SECONDS = 1 * 24 * 60 * 60;
    
        /**
         * 获取redis中获取指定data,如果redis中不存在,则从DataGeter接口中获取,并且写入redis<br/>
         * 注:该方法会自动创建一个cacheKey + "_flag"的缓存key,作为标记flagKey
         * @param cacheKey-缓存key
         * @param clazz-获取目标类型
         * @param dataGeter-数据获取器,原始数据源
         * @param expireSeconds-缓存失效时间
         * @return
         */
        public static <T> T getDataFromRedisOrDataGeter(String cacheKey, Class<T> clazz, DataGeter<T> dataGeter,int expireSeconds) {
            
            T val = RedisClient.getValue(cacheKey, clazz);
            if (val != null) {
                //让热数据一直热下去 <单个key/value>,设置缓存有效期。
                haveChanceToSetKeyExpireTime( cacheKey, expireSeconds) ;
                return val;
            }
            if (RedisClient.existsKey(RedisClient.getFlagKey(cacheKey))) {
                return null;
            }
            
            try {
            //本地锁 Object lockObject
    = LockObjectUtil.getLockObject(cacheKey); synchronized (lockObject) {// 为提升性能 这里不使用分布式锁 // 标记key,防止集合为空时还不停从数据库中读取数据 T data = null; try { data = dataGeter.getData(); } catch (DBException e) { e.printStackTrace(); throw e; } if (data != null) { // 这里最后才设置flag,以免分布式环境下dataGeter.getData();获取慢,导致后续请求从缓存中取不到数据 //有值不设置flag RedisClient.setValue(cacheKey, data, expireSeconds <= 0 ? RedisDataSource.DEFAULT_EXPIRE_SECONDS : expireSeconds, false); } else { // 不存在数据则往缓存中插入一个flag,过期时间为一天 RedisClient.setValue(RedisClient.getFlagKey(cacheKey), true, ONE_DAY_EXPIRE_SECONDS); } return data; } } finally { //释放锁 LockObjectUtil.disposeLock(cacheKey); } } }

    当调用工具类的方法时,写匿名内部类,去实现从数据库获取数据的逻辑。

  • 相关阅读:
    Java SE (3) 之 事件监听
    Java SE (2)之 Graphics 画图工具
    Java SE (1)之 JFrame 组件 GridLayout布局
    解决IIS7中出现An error occurred on the server when processing the URL错误提示的方法
    VS2010中配置C#Project不生成.vhost.exe和.pdb文件的方法
    IIS7和IIS7.5备份和还原的方法
    C# 读取IE缓存文件(2)
    C# 读取IE缓存文件(1)
    raywenderlich的Swift编程风格指南
    Swift和C#的基本语法对比
  • 原文地址:https://www.cnblogs.com/itbac/p/11210414.html
Copyright © 2011-2022 走看看