import org.apache.ibatis.cache.Cache;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.dao.DataAccessException;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.util.CollectionUtils;import java.util.Set;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * Created by zhaoyh on 2019-01-22 * MyBatis二级缓存配置 * @author zhaoyh */public class MybatisRedisCache implements Cache { private static final Logger LOG = LoggerFactory.getLogger(MybatisRedisCache.class); /** * 默认redis有效期 * 单位分钟 */ private static final int DEFAULT_REDIS_EXPIRE = 10; /** * 注入redis */ private static RedisTemplate redisTemplate = null; /** * 读写锁 */ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); /** * cache id */ private String id = null; /** * 构造函数 * @param id */ public MybatisRedisCache(final String id) { if (null == id) { throw new IllegalArgumentException("MybatisRedisCache Instance Require An Id..."); } LOG.info("MybatisRedisCache: " + id); this.id = id; } /** * @return The identifier of this cache */ @Override public String getId() { return this.id; } /** * @param key Can be any object but usually it is a {@link} * @param value The result of a select. */ @Override public void putObject(Object key, Object value) { if (null != value) { LOG.info("putObject key: " + key.toString()); // 向Redis中添加数据,默认有效时间是2小时 redisTemplate.opsForValue().set(key.toString(), value, DEFAULT_REDIS_EXPIRE, TimeUnit.MINUTES); } } /** * @param key The key * @return The object stored in the cache. */ @Override public Object getObject(Object key) { try { if (null != key) { LOG.info("getObject key: " + key.toString()); return redisTemplate.opsForValue().get(key.toString()); } } catch (Exception e) { LOG.error("getFromRedis: " + key.toString() + " failed!"); } LOG.info("getObject null..."); return null; } /** * As of 3.3.0 this method is only called during a rollback * for any previous value that was missing in the cache. * This lets any blocking cache to release the lock that * may have previously put on the key. * A blocking cache puts a lock when a value is null * and releases it when the value is back again. * This way other threads will wait for the value to be * available instead of hitting the database. * * 删除缓存中的对象 * * @param keyObject The key * @return Not used */ @Override public Object removeObject(Object keyObject) { if (null != keyObject) { redisTemplate.delete(keyObject.toString()); } return null; } /** * Clears this cache instance * 有delete、update、insert操作时执行此函数 */ @Override public void clear() { LOG.info("clear..."); try { Set keys = redisTemplate.keys("*:" + this.id + "*"); LOG.info("keys size: " + keys.size()); for (String key : keys) { LOG.info("key : " + key); } if (!CollectionUtils.isEmpty(keys)) { redisTemplate.delete(keys); } } catch (Exception e) { LOG.error("clear failed!", e); } } /** * Optional. This method is not called by the core. * * @return The number of elements stored in the cache (not its capacity). */ @Override public int getSize() { Long size = (Long) redisTemplate.execute(new RedisCallback () { @Override public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.dbSize(); } }); LOG.info("getSize: " + size.intValue()); return size.intValue(); } /** * Optional. As of 3.2.6 this method is no longer called by the core. *
* Any locking needed by the cache must be provided internally by the cache provider. * * @return A ReadWriteLock */ @Override public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } public static void setRedisTemplate(RedisTemplate