ORM Redis ·

Mybatis缓存之redis实现

mybatis对于缓存的处理不是很强大,但也算是能凑合使用下,今天项目中要使用到,就打算用redis来扩展下他的接口,做一个实现

package com.tojsp.mybatis;

import java.io.UnsupportedEncodingException;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tojsp.common.env.ConfigHolder;
import com.tojsp.common.redis.JedisX;
import com.tojsp.common.redis.RedisClient;
import com.tojsp.common.redis.RedisInfoEntity;
import com.tojsp.common.redis.RedisPool;
import com.tojsp.common.util.JavaSerializer;

/**
 * Mybatis cache implements of redis
 * 
 * @author Leo.du
 * @date 2014-07-08
 */
public class RedisCache implements Cache {

    private static final String UTF_8 = "utf-8";

    /**
     * Logger
     */
    private static final Logger LOG = LoggerFactory.getLogger(RedisCache.class);

    /**
     * The ReadWriteLock.
     */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private final String COMMON_CACHE_KEY = "COM:";

    /**
     * Redis client
     */
    private static RedisClient redisClient;

    /**
     * Jedis instance
     */
    private JedisX jedisx;

    private final String id;

    /**
     * expire time, default -1, never expire
     */
    private String expire = "-1";

    private String getKey(Object key) {
        StringBuilder accum = new StringBuilder();
        accum.append(COMMON_CACHE_KEY);
        accum.append(this.id).append(":");
        accum.append(DigestUtils.md2Hex(String.valueOf(key)));

        return accum.toString();
    }

    private String getKeys() {
        return COMMON_CACHE_KEY + this.id + ":*";
    }

    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        this.id = id;
        LOG.debug(">>>> RedisCache id: " + this.id);
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public int getSize() {
        int size = 0;
        jedisx = getRedisClient().borrowJedis();
        try {
            Set<byte[]> keys = jedisx.keys(getKeys().getBytes(UTF_8));
            if (null != keys && !keys.isEmpty()) {
                size = keys.size();
            }
            LOG.debug(">>>> dbsize:" + size);
        } catch (UnsupportedEncodingException e) {
            // do nothing..
        } finally {
            jedisx.returnResource();
        }
        return size;
    }

    @Override
    public void putObject(Object key, Object value) {
        jedisx = getRedisClient().borrowMasterJedis();
        try {
            LOG.debug(">>>> put:" + key + "=" + value);
            byte[] keys = getKey(key).getBytes(UTF_8);
            jedisx.set(keys, JavaSerializer.serialize(value));

            int second = SecondTransform.get(expire);
            if (second > 0) {
                jedisx.expire(keys, second);
            }
        } catch (UnsupportedEncodingException e) {
            // do nothing..
        } finally {
            jedisx.returnResource();
        }
    }

    @Override
    public Object getObject(Object key) {
        Object value = null;
        jedisx = getRedisClient().borrowJedis();
        try {
            value = JavaSerializer.deserialize(jedisx.get(getKey(key).getBytes(UTF_8)));
            LOG.debug(">>>> get:" + key + "=" + value);
        } catch (UnsupportedEncodingException e) {
            // do nothing..
        } finally {
            jedisx.returnResource();
        }
        return value;
    }

    @Override
    public Object removeObject(Object key) {
        Object value = null;
        jedisx = getRedisClient().borrowMasterJedis();
        try {
            value = jedisx.del(getKey(key).getBytes(UTF_8));
            LOG.debug(">>>> del:" + key + "=" + value);
            return value;
        } catch (UnsupportedEncodingException e) {
            // do nothing..
        } finally {
            jedisx.returnResource();
        }
        return value;
    }

    @Override
    public void clear() {
        jedisx = getRedisClient().borrowMasterJedis();
        try {
            Set<byte[]> keys = jedisx.keys(getKeys().getBytes(UTF_8));
            for (byte[] key : keys) {
                jedisx.del(key);
                LOG.debug(">>>> clear object, key [{}]", key);
            }
            LOG.debug(">>>> clear success");
        } catch (UnsupportedEncodingException e) {
            // do nothing..
        } finally {
            jedisx.returnResource();
        }

    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }

    public synchronized RedisClient getRedisClient() {
        if (null == redisClient) {
            // 此处使用的是自己封装的redis群集配置
            // 在使用中, 请换成直接的配置方式,写上ip,端口, db名称
            RedisInfoEntity redisInfo = new RedisInfoEntity();
            redisInfo.setIp(ConfigHolder.getString("redis.ip"));
            redisInfo.setPort(ConfigHolder.getInteger("redis.port"));
            redisInfo.setAuth(ConfigHolder.getString("redis.auth"));
            redisInfo.setDbType(ConfigHolder.getString("redis.cache.database"));

            int maxActive = ConfigHolder.getInteger("redis.maxActive");
            long maxWait = ConfigHolder.getLong("redis.maxWait");
            int maxIdle = ConfigHolder.getInteger("redis.maxIdle");

            RedisPool pool = new RedisPool(maxActive, maxWait, maxIdle, redisInfo);

            redisClient = new RedisClient(pool);

            LOG.debug(">>>> master info:" + redisInfo.toString());
            LOG.debug(">>>> maxActive:" + maxActive);
            LOG.debug(">>>> maxWait:" + maxWait);
            LOG.debug(">>>> maxIdle:" + maxIdle);
        }
        return redisClient;
    }
}
package com.tojsp.mybatis;

import org.apache.ibatis.cache.decorators.LoggingCache;

/**
 * Mybatis cache implements of redis with loging information
 * 
 * @author Leo.du
 * @date 2014年7月8日
 */
public class LoggingRedisCache extends LoggingCache {

    public LoggingRedisCache(String id) {
        super(new RedisCache(id));
    }

}
package com.tojsp.mybatis;

import org.apache.commons.lang3.StringUtils;

/**
 * Transform 8s/6m/8h/8d to xxx seconds
 * 
 * @author Leo.du
 * @date 2014年7月9日
 */
public final class SecondTransform {

    private SecondTransform() {
    }

    public static int get(final String str) {
        int number = -1;
        if (StringUtils.isNotBlank(str)) {
            char ch = getLastChar(str);
            String substr = str.replace(String.valueOf(ch), "");
            try {
                number = Integer.valueOf(substr);
                if (number < 0) {
                    return -1;
                }

                switch (ch) {
                case 'm':
                    return number * 60;
                case 'h':
                    return number * 60 * 60;
                case 'd':
                    return number * 60 * 60 * 24;
                case 's':
                case '-':
                    return number;
                default:
                    return -1;
                }
            } catch (NumberFormatException e) {
                // do nothing.. use defalut
            }
        }
        return number;
    }

    private static char getLastChar(final String str) {
        int length = str.length();
        char ch = str.charAt(length - 1);

        return Character.isLetter(ch) ? Character.toLowerCase(ch) : '-';
    }
}

以上代码中的RedisClient为自己封的jedisx操作, 你可以直接替换成你自己的封装,或者直接使用原生的jedisx

参与评论