【此为原创文章,转载必须先征得本人同意且注明出处。】
参考:Redis教程
参考:Spring中使用RedisTemplate操作Redis
假设我需要存储用户的真实信息,并且对认证次数有限制:最多可认证3次,3次还未通过时,该账号不可再进行实名认证操作。
于是我需要用到redis来存储此用户认证失败的次数,并且需要一个状态标志来分别存储认证失败时的value认证次数以及认证成功时的value真实信息,并且在用户在规定次数限制内认证成功时移除掉用户认证失败的Cache(如果有的话)
以uid与verifyState为key
单独建一个用来存储key的类RedisConstant
public static final String REDIS_KEY_REAL_INFO_VERIFY = "user:%s:verify_state:%s";
private String genRealInfoVerifyKey(Long uid, Byte verifyState) {
return String.format(RedisConstant.REDIS_KEY_REAL_INFO_VERIFY, uid, verifyState);
}
认证失败,则值为0的verifyState与uid一起作为key。
认证成功,则值为1的verifyState与uid一起作为key。
//认证成功
addRealInfoVerifyCache(uid, RealInfoVerifyStateEnum.Verify_Success.value(), realInfo, null);
//认证失败
Integer verifiedNum = 0;
addRealInfoVerifyCache(uid, RealInfoVerifyStateEnum.Verify_Failure.value(), null, verifiedNum);
String key = genRealInfoVerifyKey(uid, verifyState);
redisCache.incr(key, 1);//将verifiedNum增1
private void addRealInfoVerifyCache(Long uid, Byte verifyState, RealInfo realInfo, Integer verifiedNum){
if (RealInfoVerifyStateEnum.Verify_Success.equals(verifyState)){
redisCache.putCache(genRealInfoVerifyKey(uid, verifyState), realInfo);
}else if (RealInfoVerifyStateEnum.Verify_Failure.equals(verifyState)){
redisCache.set(genRealInfoVerifyKey(uid, verifyState), verifiedNum.toString());
}
}
认证失败,则verifiedNum(失败次数)为value。verifiedNum为整数。
认证成功,则realInfo(真实信息)为value。realInfo为实体类。
set操作与putCache操作的不同
set
适用于value为字符串的情况
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
putCache
适用于value为实体类的情况,对类进行序列化操作来进行存储
public <T> boolean putCache(String key, T obj) {
final byte[] bKey = key.getBytes();
final byte[] bValue = ProtoStuffSerializerUtil.serialize(obj);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bKey, bValue);
}
});
return result;
}
普通字符串
//获取认证失败的次数
String key = genRealInfoVerifyKey(uid, RealInfoVerifyStateEnum.Verify_Failure.value());
String verifiedNumStr = redisCache.get(key);
利用反序列化取类
//获取用户真实信息
String key = genRealInfoVerifyKey(uid, RealInfoVerifyStateEnum.Verify_Success.value());
RealInfo realInfo = redisCache.getCache(key, RealInfo.class);
redisCache.getCache
public <T> T getCache(final String key, Class<T> targetClass) {
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return ProtoStuffSerializerUtil.deserialize(result, targetClass);
}
removeRealInfoVerifyCache(uid, RealInfoVerifyStateEnum.Verify_Failure.value());
removeRealInfoVerifyCache(uid, RealInfoVerifyStateEnum.Verify_Success.value());
private void removeRealInfoVerifyCache(Long uid, Byte verifyState){
redisCache.deleteCache(genRealInfoVerifyKey(uid, verifyState));
}
package com.component.cache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qumitech.douqu.component.util.ProtoStuffSerializerUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redis缓存
*
* @author yingjun
*/
@Component("RedisCache")
public class RedisCache {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void zAdd(String key, String value, double score) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
zset.add(key, value, score);
}
public Set<String> zRangeByScore(String key, double min, double max) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, min, max);
}
public Double zIncrBy(String key, String value, double score) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.incrementScore(key, value, score);
}
public Long zCard(String key) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.zCard(key);
}
public void zRemRange(String key, long l1, long l2) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
zset.removeRange(key, l1, l2);
}
public Set<ZSetOperations.TypedTuple<String>> reverseRangeWithScores(String key, Long min, Long max) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.reverseRangeWithScores(key, min, max);
}
public Set<String> zRange(String key, Long min, Long max) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.range(key, min, max);
}
public Set<String> zReverseRange(String key, Long min, Long max) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.reverseRange(key, min, max);
}
public Set<ZSetOperations.TypedTuple<String>> zRangeWithScores(String key, Long min, Long max) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
return zset.rangeWithScores(key, min, max);
}
public void zRem(String key) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
//test:Zrem需要制定分数段查询范围
Long i = zset.removeRangeByScore(key, 0, 99999999999999999L);
}
public void zRem(String key, String member) {
ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
//test:Zrem需要制定分数段查询范围
Long i = zset.remove(key, member);
}
public <T> boolean putCache(String key, T obj) {
final byte[] bKey = key.getBytes();
final byte[] bValue = ProtoStuffSerializerUtil.serialize(obj);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bKey, bValue);
}
});
return result;
}
/**
* @param key
* @param obj
* @param expireTime 单位: s
* @param
*/
public <T> void putCacheWithExpireTime(String key, T obj, final long expireTime) {
final byte[] bKey = key.getBytes();
final byte[] bValue = ProtoStuffSerializerUtil.serialize(obj);
redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(bKey, expireTime, bValue);
return true;
}
});
}
public <T> boolean putListCache(String key, List<T> objList) {
final byte[] bKey = key.getBytes();
final byte[] bValue = ProtoStuffSerializerUtil.serializeList(objList);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bKey, bValue);
}
});
return result;
}
public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
final byte[] bKey = key.getBytes();
final byte[] bValue = ProtoStuffSerializerUtil.serializeList(objList);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(bKey, expireTime, bValue);
return true;
}
});
return result;
}
public <T> T getCache(final String key, Class<T> targetClass) {
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return ProtoStuffSerializerUtil.deserialize(result, targetClass);
}
public <T> List<T> getListCache(final String key, Class<T> targetClass) {
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
}
/**
* 精确删除key
*
* @param key
*/
public void deleteCache(String key) {
redisTemplate.delete(key);
}
/**
* 模糊删除key
*
* @param pattern
*/
public void deleteCacheWithPattern(String pattern) {
Set<String> keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
/**
* 递增
*
* @param key 键
* @param delta 需要增加几
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
/**
* 获取字符串值
*
* @param key
* @return
*/
public String getString(String key, String defaultValue) {
String value = redisTemplate.opsForValue().get(key);
if (StringUtils.isEmpty(value)) {
value = defaultValue;
}
return value;
}
public String getSet(String key, String value) {
String valueOld = redisTemplate.opsForValue().getAndSet(key, value);
;
if (StringUtils.isEmpty(valueOld)) {
valueOld = "0";
}
return valueOld;
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
public <T> List<T> getList(String key, Class<T> targetClass) {
String value = get(key);
return JSONObject.parseArray(value, targetClass);
}
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public void setList(String key, List<?> objList) {
String value = JSON.toJSONString(objList);
set(key, value);
}
public boolean setnx(String key, String value) {
return redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
return redisConnection.setNX(key.getBytes(), value.getBytes());
}
});
}
public boolean setnxWithExpire(String key, String value, Integer expire) {
return redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
boolean result = false;
if (redisConnection.setNX(key.getBytes(), value.getBytes())) {
result = redisConnection.expire(key.getBytes(), expire);
}
return result;
}
});
}
public void setExString(String key, String value, long l) {
redisTemplate.opsForValue().set(key, value, l, TimeUnit.SECONDS);
}
/**
* 设置缓存失效时间
*/
public boolean expire(String key, Long time) {
try {
if (time != null && time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 往队列里添加数据
*
* @param key
* @param value
*/
public void lpush(String key, String value) {
redisTemplate.opsForList().leftPush(key, value);
}
public String rpop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
public void lrem(String key, String val) {
redisTemplate.opsForList().remove(key, 1, val);
}
public List<String> lrange(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
public long lsize(String key) {
return redisTemplate.opsForList().size(key);
}
public void sadd(String key, String... var2) {
redisTemplate.opsForSet().add(key, var2);
}
public Set<String> smembers(String key) {
return redisTemplate.<String>opsForSet().members(key);
}
public void hset(String key, String field, String value) {
redisTemplate.opsForHash().put(key, field, value);
}
public String hget(String key, String field) {
return redisTemplate.<String, String>opsForHash().get(key, field);
}
public Double zscore(String redisKey, String member) {
return redisTemplate.<String, String>opsForZSet().score(redisKey, member);
}
public void zincrby(RedisKey redisKey, String member, double score) {
String key = redisKey.getKeyStr();
expire(key, redisKey.getExpireTime());
redisTemplate.<String, String>opsForZSet().incrementScore(key, member, score);
}
public Set<String> getKeysByPattern(String pattern) {
return redisTemplate.keys(pattern);
}
public Long getZsetReverseRank(String key, String member) {
return redisTemplate.opsForZSet().reverseRank(key, member);
}
public Double getZsetScoreByMember(String key, String member) {
return redisTemplate.opsForZSet().score(key, member);
}
public void rename(String oldKey, String newKey) {
redisTemplate.rename(oldKey, newKey);
}
public Set<String> zRevrangeByScore(String key, Long minScore, Long maxScore) {
return redisTemplate.opsForZSet().reverseRangeByScore(key, minScore, maxScore);
}
}
package com.component.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
/**
* 序列话工具
*/
public class ProtoStuffSerializerUtil {
/**
* 序列化对象
* @param obj
* @return
*/
public static <T> byte[] serialize(T obj) {
if (obj == null) {
throw new RuntimeException("序列化对象(" + obj + ")!");
}
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(obj.getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
byte[] protostuff = null;
try {
protostuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
throw new RuntimeException("序列化(" + obj.getClass() + ")对象(" + obj + ")发生异常!", e);
} finally {
buffer.clear();
}
return protostuff;
}
/**
* 反序列化对象
* @param paramArrayOfByte
* @param targetClass
* @return
*/
public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
}
T instance = null;
try {
instance = targetClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("反序列化过程中依据类型创建对象失败!", e);
}
Schema<T> schema = RuntimeSchema.getSchema(targetClass);
ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
return instance;
}
/**
* 序列化列表
* @param objList
* @return
*/
public static <T> byte[] serializeList(List<T> objList) {
if (objList == null || objList.isEmpty()) {
throw new RuntimeException("序列化对象列表(" + objList + ")参数异常!");
}
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
byte[] protostuff = null;
ByteArrayOutputStream bos = null;
try {
bos = new ByteArrayOutputStream();
ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
protostuff = bos.toByteArray();
} catch (Exception e) {
throw new RuntimeException("序列化对象列表(" + objList + ")发生异常!", e);
} finally {
buffer.clear();
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return protostuff;
}
/**
* 反序列化列表
* @param paramArrayOfByte
* @param targetClass
* @return
*/
public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class<T> targetClass) {
if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
}
Schema<T> schema = RuntimeSchema.getSchema(targetClass);
List<T> result = null;
try {
result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);
} catch (IOException e) {
throw new RuntimeException("反序列化对象列表发生异常!", e);
}
return result;
}
}