正常来说,redisTemplate是无法操作对象的,但是我们可以通过对其做序列化和反序列化作到对象的存储对象
不废话直接上代码
1,pom引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.7.2</version>
</dependency>
2,对protostuff封装
/**
* Description: protostuff 序列化工具.
*/
public class ProtostuffSerializeUtil {
private static Logger logger = LoggerFactory.getLogger(ProtostuffSerializeUtil.class);
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
private static <T> Schema<T> getSchema(Class<T> clazz) {
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
if (schema == null) {
schema = RuntimeSchema.getSchema(clazz);
if (schema != null) {
cachedSchema.put(clazz, schema);
}
}
return schema;
}
/**
* 序列化.
*
* @param obj 需要序列化的obj
*/
public static <T> byte[] serialize(T obj) {
if (obj == null) {
return null;
}
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(clazz);
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
//logger.error(e.getMessage(), e);
return null;
} finally {
buffer.clear();
}
}
/**
* 反序列化.
*
* @param data 需要反序列化的数据
* @param clazz 结果class
*/
public static <T> T deserialize(byte[] data, Class<T> clazz) {
if (data == null || data.length < 1) {
logger.error("ProtostuffSerializeUtil.deserialize --> 反序列化对象,byte序列为空");
return null;
}
try {
T obj = clazz.newInstance();
Schema<T> schema = getSchema(clazz);
ProtostuffIOUtil.mergeFrom(data, obj, schema);
return obj;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
/**
* 原生protobuf序列化.
*
* @param obj 需要序列化的obj
*/
public static <T> byte[] serializeProtoBuf(T obj) {
if (obj == null) {
logger.error("ProtostuffSerializeUtil.serializeProtoBuf --> 序列化对象为空!");
return null;
}
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(clazz);
return ProtobufIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
} finally {
buffer.clear();
}
}
/**
* 原生protobuf反序列化.
*
* @param data 需要反序列化的数据
* @param clazz 结果class
*/
public static <T> T deserializeProtoBuf(byte[] data, Class<T> clazz) {
if (data == null || data.length < 1) {
logger.error("ProtostuffSerializeUtil.deserializeProtoBuf --> 反序列化对象,byte序列为空");
return null;
}
try {
T obj = clazz.newInstance();
Schema<T> schema = getSchema(clazz);
ProtobufIOUtil.mergeFrom(data, obj, schema);
return obj;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
/**
* 序列化map.
*
* @param objMap 需要序列化的map
* @return byte[]
*/
public static byte[] serializeMap(Map<Object, Object> objMap) {
if (objMap == null || objMap.isEmpty()) {
logger.error("ProtostuffSerializeUtil.serializeMap --> 序列化map为空");
return null;
}
MapWrapper wrapper = new MapWrapper(objMap);
return serialize(wrapper);
}
/**
* 反序列化map.
*
* @param data 需要反序列化的数据
* @return map
*/
public static Map<Object, Object> deserializeMap(byte[] data) {
if (data == null || data.length < 1) {
logger.error("ProtostuffSerializeUtil.deserialize --> 反序列化map,byte序列为空");
return null;
}
MapWrapper wrapper = deserialize(data, MapWrapper.class);
if (wrapper != null) {
return wrapper.getMap();
}
return null;
}
/**
* 序列化列表.
*
* @param objList 需要序列化的列表
* @return 返回结果
*/
public static <T> byte[] serializeList(List<T> objList) {
if (objList == null || objList.isEmpty()) {
logger.error("ProtostuffSerializeUtil.serializeList --> 序列化列表为空");
return null;
}
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
ByteArrayOutputStream bos = null;
try {
bos = new ByteArrayOutputStream();
ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
return bos.toByteArray();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
} finally {
buffer.clear();
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 反序列化列表.
*
* @param data 需要反序列化的数据
* @param targetClass Class
* @return targetClass的列表
*/
public static <T> List<T> deserializeList(byte[] data, Class<T> targetClass) {
if (data == null || data.length == 0) {
logger.error("ProtostuffSerializeUtil.deserializeList --> 序列化列表,byte序列为空");
return null;
}
Schema<T> schema = RuntimeSchema.getSchema(targetClass);
try {
return ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(data), schema);
} catch (IOException e) {
logger.error(e.getMessage(), e);
return null;
}
}
}
3,结合RedisTemplate做封装
@Service("cacheService")
public class RedisCacheServiceImpl extends BaseLogger implements CacheService {
@Resource
private RedisTemplate<String, byte[]> redisTemplate;
@Override
public <V> void put(String key, V value) {
doPut(key, serialize(value), null);
}
@Override
public <V> void put(String key, V value, long expireTime) {
doPut(key, serialize(value), expireTime);
}
@Override
public <V> void putList(String key, List<V> value) {
doPut(key, ProtostuffSerializeUtil.serializeList(value), null);
}
private void doPut(final String key, final byte[] value, final Long expireSec) {
final byte[] keyBytes = serializeString(key);
redisTemplate.execute(new RedisCallback<Object>() {
public String doInRedis(final RedisConnection connection)
throws DataAccessException {
connection.set(keyBytes, value);
if (expireSec != null) {
connection.expire(keyBytes, expireSec);
}
return null;
}
});
}
@Override
public void del(String key) {
redisTemplate.delete(key);
}
@Override
public <V> V get(String key, Class<V> clazz) {
return deserialize(doGet(key), clazz);
}
@Override
public <V> List<V> getList(String key, Class<V> clazz) {
return ProtostuffSerializeUtil.deserializeList(doGet(key), clazz);
}
private byte[] doGet(final String key) {
return redisTemplate.execute(new RedisCallback<byte[]>() {
public byte[] doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.get(serializeString(key));
}
});
}
@Override
public <V> void hPut(String key, String hKey, V value) {
final byte[] keyBytes = serializeString(key);
final byte[] hKeyBytes = serializeString(hKey);
final byte[] valBytes = serialize(value);
redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.hSet(keyBytes, hKeyBytes, valBytes);
}
});
}
@Override
public void hDel(String key, String hKey) {
redisTemplate.opsForHash().delete(key, hKey);
}
@Override
public <V> V hGet(String key, String hKey, final Class<V> clazz) {
final byte[] keyBytes = serializeString(key);
final byte[] hkeyBytes = serializeString(hKey);
return redisTemplate.execute(new RedisCallback<V>() {
public V doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] data = connection.hGet(keyBytes, hkeyBytes);
return deserialize(data, clazz);
}
});
}
@Override
public <V> Map<String, V> hGetAll(String key, Class<V> clazz) {
final byte[] keyBytes = serializeString(key);
Map<byte[], byte[]> entries = redisTemplate.execute(new RedisCallback<Map<byte[], byte[]>>() {
public Map<byte[], byte[]> doInRedis(RedisConnection connection) {
return connection.hGetAll(keyBytes);
}
}, true);
return deserializeMap(entries, clazz);
}
@Override
public <V> List<V> hGetValues(String key, final Class<V> clazz) {
final byte[] keyBytes = serializeString(key);
return redisTemplate.execute(new RedisCallback<List<V>>() {
public List<V> doInRedis(RedisConnection connection) {
List<byte[]> valBytes = connection.hVals(keyBytes);
List<V> val = new ArrayList<>();
for (byte[] valByte : valBytes) {
val.add(ProtostuffSerializeUtil.deserialize(valByte, clazz));
}
return val;
}
}, true);
}
private <V> Map<String, V> deserializeMap(Map<byte[], byte[]> entries, Class<V> clazz) {
if (entries == null) {
return null;
}
Map<String, V> map = new LinkedHashMap<>(entries.size());
for (Map.Entry<byte[], byte[]> entry : entries.entrySet()) {
map.put(entry.getKey() == null ? null : new String(entry.getKey()), deserialize(entry.getValue(), clazz));
}
return map;
}
@Override
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
private byte[] serializeString(String value) {
return value == null ? null : value.getBytes(Charset.forName("UTF8"));
}
@SuppressWarnings("unchecked")
private <V> byte[] serialize(V value) {
if (value instanceof Map) {
return ProtostuffSerializeUtil.serializeMap((Map<Object, Object>) value);
} else {
return ProtostuffSerializeUtil.serialize(value);
}
}
@SuppressWarnings("unchecked")
private <V> V deserialize(byte[] data, Class<V> clazz) {
if (clazz.getName().equals(Map.class.getName())) {
return (V) ProtostuffSerializeUtil.deserializeMap(data);
} else {
return ProtostuffSerializeUtil.deserialize(data, clazz);
}
}
}
完结,撒花