spring 和 redis的集成(使用註解方式)
1.原因
原因很簡單,某些數據會被頻繁的進行調用,之前是進行查詢數據庫,爲了避免對數據庫的壓力,使用redis進行緩存,在調用接口的時候,先訪問一下redis中是否存在,存在的話就在redis中進行取到,沒有則進行查詢數據庫,並且在將查到的數據存到redis緩存中去。這讓我想到了spring通過切面去定義的Cache不是可以完美的解決這個問題麼。廢話少說。
2.配置文件
需要配置spring的cache管理裏面去,redis在spring的配置不用說了,主要是在SimpleCacheManager中進行註冊,因爲使用了另外的緩存機制。
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="XXX.XXXX.XX.RedisCache">
<property name="name" value="redis"/>
<property name="redisTemplate" ref="redisTemplate"/>
<property name="liveTime" value="${redis.car.liveTime}"/><!-- 設置過期時間 -->
</bean>
</set>
</property>
</bean>
3.redisCache
主要是實現了spring 的Cache接口,這樣就可以Cache了。
@Data
@Component
public class RedisCache implements Cache {
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
/**
* 區分名稱
*/
private String name;
/**
* redisTemplate
*/
private RedisTemplate<String, Object> redisTemplate;
/**
* 過期時間
*/
private Long liveTime;
@Override
public String getName() {
return this.name;
}
@Override
public Object getNativeCache() {
return this.redisTemplate;
}
/**
* 得到數據
*
* @param key
* @return
*/
@Override
public ValueWrapper get(Object key) {
logger.info("get cache, key:{}", key);
final String keyf = (String) key;
Object object = null;
object = redisTemplate.execute((RedisConnection connection) -> {
byte[] keyb = keyf.getBytes();
byte[] value = connection.get(keyb);
if (value == null) {
return null;
}
return toObject(value);
});
return (object != null ? new SimpleValueWrapper(object) : null);
}
/**
* 反序列化
*
* @param bytes
* @return
*/
private Object toObject(byte[] bytes) {
Object obj = null;
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis)) {
obj = ois.readObject();
} catch (IOException ex) {
logger.error("IOException", ex);
} catch (ClassNotFoundException ex) {
logger.error("ClassNotFoundException", ex);
}
return obj;
}
@Override
public <T> T get(Object o, Class<T> aClass) {
return null;
}
/**
* key-value 的形式放入緩存
*
* @param key
* @param value
*/
@Override
public void put(Object key, Object value) {
logger.info("put cache, key:{}", key);
final String keyf = (String) key;
final Object valuef = value;
redisTemplate.execute((RedisConnection connection) -> {
byte[] keyb = keyf.getBytes();
byte[] valueb = toByteArray(valuef);
connection.set(keyb, valueb);
if (liveTime > 0L) {
connection.expire(keyb, liveTime);
}
return 1L;
});
}
/**
* 序列化成二進制
*
* @param obj
* @return
*/
private byte[] toByteArray(Object obj) {
byte[] bytes = null;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
} catch (IOException ex) {
logger.error("IOException", ex);
}
return bytes;
}
@Override
public ValueWrapper putIfAbsent(Object o, Object o1) {
return null;
}
/**
* 通過對應的key 進行刪除緩存
*
* @param key
*/
@Override
public void evict(Object key) {
logger.info("delete cache ,key:{}", key);
final String keyf = (String) key;
redisTemplate.execute((RedisConnection connection) -> {
return connection.del(keyf.getBytes());
});
}
/**
* 清除緩存
*/
@Override
public void clear() {
redisTemplate.execute((RedisConnection connection) -> {
connection.flushDb();
return "success";
});
}
}
4. @Cacheable @CacheEvint
Cacheable註解是進入該方法的時候,去查看緩存中是否存在,如果存在的話,直接從緩存中去拿到數據,不進入方法。如果緩存中不存在,則進入該方法將方法的返回值按照一定的規則,進行保存到緩存中去。
CacheEvint註解則是清除緩存,返回類型可以爲void,註解是通過傳過來的參數和註解上的key定義的規則,進行刪除緩存中對應的值。