前言
这个是基于redis的一个简单的缓存工具类 自己封装的,写的不合理的地方希望大家指出,使用起来也比较简介方便,移植性也比较好,如果换了redis,替换也方便
数据准备:
1. redis框架
2.fastjosn框架
1.Cacheable接口
/**
* 缓存参数接口
* @param
*/
public interface Cacheable {
//外部实现数据回传
public T getData();
}
2.RedisCacheUtil
import com.alibaba.fastjson.JSONObject;
import com.jiuzhm.common.redis.lock.impl.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
/*
1.单个对象使用样例
String userId = "92839";
UserInfo user1 = (UserInfo)redisCacheUtil.getCacheData(userId, 1000L, UserInfo.class,new Cacheable() {
@Override
public Object getData() {
return userInfoMapper.queryUserByID("92839",1);
}
});
System.out.println("result="+ user1.getCertName());
2.数组对象使用样例
String userId = "92839";
Listlist1 = (List)redisCacheUtil.getCacheDataList(userId, 2000L, UserInfo.class,new Cacheable() {
@Override
public Object getData() {
UserInfo user = userInfoMapper.queryUserByID(userId,1);
Listlist = new ArrayList<>(2);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
return list;
}
});
System.out.println("result="+ list1.size());
for (UserInfo user1 :list1){
System.out.println("result="+ user1.getCertName());
}
*/
/**
* redis缓存帮助类
*
* @param
*/
@Service
public class RedisCacheUtil {
private final static String RedisCacheUtilKeyPre = "RedisCacheUtilKeyPre_";
private final static String RedisCacheUtilLockKeyPre = "RedisCacheUtilLockKeyPre_";
@Autowired
private RedisLock lock;
@Autowired
private RedisTemplate redisTemplate;
/**
*获取缓存数据对象
*
* @param key
* @param expire 过期时间/秒
* @param deskClass 对应的类型
* @param cacheable
* @return
*/
public T getCacheData(String key, Long expire, Class deskClass, Cacheable cacheable) {
return this.getCacheObject(key,expire,deskClass,false,cacheable);
}
/**
* 获取缓存数据对象
* @param key
* @param expire 过期时间/秒
* @param deskClass 对应的类型
* @param cacheable
* @return
*/
public T getCacheDataList(String key, Long expire, Class deskClass, Cacheable cacheable) {
return this.getCacheObject(key,expire,deskClass,true,cacheable);
}
/**
* 删除缓存
* @param key
*/
public void delCacheWith(String key){
key = this.makeRedisKey(key);
redisTemplate.delete(key);
}
/**
* 获取缓存数据 如果无缓存 将会从Cacheable中获取 Cacheable需要自己提供数据
* @param key
* @param expire 过期时间/秒
* @param deskClass 对应的类型
* @param isList 是否List对象
* @param cacheable
* @return
*/
private T getCacheObject(String key, Long expire, Class deskClass,boolean isList, Cacheable cacheable) {
key = this.makeRedisKey(key);
String lockKey = RedisCacheUtil.RedisCacheUtilLockKeyPre + key + "_";
T obj = null;
//加锁防止缓存击穿
boolean isLock = this.lock.lock(lockKey);
try {
if (isLock) {
if (isList){
obj = this.getCacheList(key, deskClass);
}else {
obj = this.getCacheObject(key, deskClass);
}
if (null == obj) {
obj = (T) cacheable.getData();
if(!(obj instanceof List) && isList){
throw new RuntimeException("当前Cacheable接口对应实现的getData返回值必须为List,不能是单个对象");
}
if(obj instanceof List && !isList){
throw new RuntimeException("当前Cacheable接口对应实现的getData返回值必须为单个对象,不能是List");
}
this.setCacheObject(key, obj, expire);
}
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
if (isLock) {
this.lock.unlock(lockKey);
}
return obj;
}
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值 对象集合等要用fastJosn转成String
* @return 缓存的对象
*/
private void setCacheObject(String key, T value, Long expire) {
key = this.makeRedisKey(key);
String redisValue = null;
if (null == value) {
return;
}
if (value instanceof String) {
redisValue = (String) value;
} else {
String objValue = JSONObject.toJSON(value).toString();
redisValue = (String) objValue;
}
ValueOperations operation = redisTemplate.opsForValue();
operation.set(key, redisValue);
if (null != expire) {
this.redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
private String getCacheObject(String key) {
key = this.makeRedisKey(key);
ValueOperations operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 获取缓存对象:对应类型
*
* @param key
* @param deskClass
* @param
* @return
*/
private T getCacheObject(String key, Class deskClass) {
key = this.makeRedisKey(key);
String redisValue = this.getCacheObject(key);
if (null == redisValue) {
return null;
}
T redisObj = (T) JSONObject.parseObject(redisValue, deskClass);
return redisObj;
}
/***
* 获取缓存数组对象:对应类型
* @param key
* @param deskClass
* @param
* @return
*/
private T getCacheList(String key, Class deskClass) {
key = this.makeRedisKey(key);
String redisValue = this.getCacheObject(key);
if (null == redisValue) {
return null;
}
T redisObj = (T) JSONObject.parseArray(redisValue,deskClass);
return redisObj;
}
/**
* 构造key
* @param key
* @return
*/
private String makeRedisKey(String key){
if (null==key){
throw new RuntimeException("key不能为空");
}
if (key.contains(RedisCacheUtil.RedisCacheUtilKeyPre)){
return key;
}else {
return RedisCacheUtil.RedisCacheUtilKeyPre+key;
}
}
}
使用:以对象数组存储为例
@Resource
RedisCacheUtil redisCacheUtil;
1.首次(看mybatis的执行日志)
@Test
public void contextLoads() {
String userId = "92839";
Listlist1 = (List)redisCacheUtil.getCacheDataList(userId, 2000L, UserInfo.class,new Cacheable() {
@Override
public Object getData() {
UserInfo user = userInfoMapper.queryUserByID(userId,1);
Listlist = new ArrayList<>(4);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
return list;
}
});
System.out.println("result="+ list1.size());
for (UserInfo user1 :list1){
System.out.println("result="+ user1.getCertName());
}
}
2.非首次且缓存未过期(没有mybatis执行日志也得到数据了)
3.手动删除缓存
this.redisCacheUtil.delCacheWith(userId);