Redis的java客戶端的封裝
因為再使用redis的過程中,開發A設定了 name-"zhaojun" 開發B設定了name-"zk",這就造成了A,B
一個人的資料丟失,會存在key 的衝突,衝突了又只有在獲取的時候才知道,這種問題還再排查一遍.為了避免這種情況,我們在key的前面就上兩層的字串,避免key的重複,同時對key的存在時間進行一層封裝.具體看程式碼:
1.介面的封裝
public interface KeyPrefix {
int expireSeconds();
String getPrefix();
}
2.抽象類的封裝
/**
* 為了防止 redis的key 的重複,我們在前面設定一個字首,防止重複...
* 兩級的控制....
*/
public abstract class BasePrefix implements KeyPrefix{
private int expireSeconds;
private String prefix;
public BasePrefix(String prefix){
this(0,prefix);
}
public BasePrefix(int expireSeconds, String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
/**
* 0 代表永遠不過期
* @return
*/
@Override
public int expireSeconds() {
return expireSeconds;
}
@Override
public String getPrefix() {
String simpleName = getClass().getSimpleName();
StringBuffer sb = new StringBuffer(simpleName);
sb.append(":");
sb.append(prefix);
sb.append(":");
return sb.toString();
}
}
3.RedisService 的封裝
@Service
public class RedisService {
@Autowired
private JedisPool jedisPool;
/**
* 獲取物件
* @param keyPrefix
* @param key
* @param clazz
* @param <T>
* @return
*/
public <T> T get(KeyPrefix keyPrefix,String key, Class<T> clazz) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上字首
String s = jedis.get(keyPrefix.getPrefix()+key);
T t = stringToBean(s,clazz);
return t;
} finally {
returnToPool(jedis);
}
}
/**
* 設定物件
* @param keyPrefix
* @param key
* @param value
* @param <T>
*/
public <T> void set(KeyPrefix keyPrefix,String key, T value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String s = beanToString(value);
if (s == null) {
return;
}
//拼接上字首
int seconds = keyPrefix.expireSeconds();
String realKey = keyPrefix.getPrefix() + key;
if(seconds>0){
jedis.setex(realKey,seconds,s);
}else {
jedis.set(realKey, s);
}
} finally {
returnToPool(jedis);
}
}
/**
* 鍵是否存在
* @param keyPrefix
* @param key
* @return
*/
public boolean exist(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上字首
return jedis.exists(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
/**
* delete 方法
* @param keyPrefix
* @param key
* @return
*/
public boolean delete(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上字首
Long del = jedis.del(keyPrefix.getPrefix() + key);
return del>1;
} finally {
returnToPool(jedis);
}
}
/**
* +1
* @param keyPrefix
* @param key
* @return
*/
public Long incr(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上字首
return jedis.incr(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
/**
* -1
* @param keyPrefix
* @param key
* @return
*/
public Long decr(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上字首
return jedis.decr(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
public static <T> String beanToString(T value) {
if (value == null) {
return null;
}
Class<?> aClass = value.getClass();
if (aClass == int.class || aClass == Integer.class) {
return String.valueOf(value);
} else if (aClass == String.class) {
return String.valueOf(value);
} else if (aClass == long.class || aClass == Long.class) {
return String.valueOf(value);
} else {
return JSON.toJSONString(value);
}
}
public static <T> T stringToBean(String s, Class<T> aClass) {
if(s==null || s.length()<=0){
return null;
}
if (aClass == int.class || aClass == Integer.class) {
return (T)Integer.decode(s);
} else if (aClass == String.class) {
return (T)s;
} else if (aClass == long.class || aClass == Long.class) {
return (T)Long.decode(s);
} else {
return JSON.parseObject(s,aClass);
}
}
/**
* 返回到連線池中去
*
* @param jedis
*/
private void returnToPool(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
public boolean delete(KeyPrefix prefix) {
if(prefix == null) {
return false;
}
List<String> keys = scanKeys(prefix.getPrefix());
if(keys==null || keys.size() <= 0) {
return true;
}
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(keys.toArray(new String[0]));
return true;
} catch (final Exception e) {
e.printStackTrace();
return false;
} finally {
if(jedis != null) {
jedis.close();
}
}
}
public List<String> scanKeys(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
List<String> keys = new ArrayList<String>();
String cursor = "0";
ScanParams sp = new ScanParams();
sp.match("*"+key+"*");
sp.count(100);
do{
ScanResult<String> ret = jedis.scan(cursor, sp);
List<String> result = ret.getResult();
if(result!=null && result.size() > 0){
keys.addAll(result);
}
//再處理cursor
cursor = ret.getStringCursor();
}while(!cursor.equals("0"));
return keys;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
4.字首的封裝示例
public class MiaoshaKey extends BasePrefix{
private MiaoshaKey(int expireSeconds, String prefix) {
super(expireSeconds,prefix);
}
public static MiaoshaKey isGoodsOver=new MiaoshaKey(0,"go");
public static MiaoshaKey miaoshaPath=new MiaoshaKey(60,"mp");
public static MiaoshaKey getMiaoshaVerifyCode=new MiaoshaKey(300,"vs");
}
public class OrderKey extends BasePrefix{
private OrderKey(String prefix) {
super(prefix);
}
public static OrderKey getOrderByUserIdGoodsId=new OrderKey("id");
}
為什麼沒有使用列舉,因為這裡涉及到了 key 的有效期,有的是一直有效的,有的有過期時間,所以直接使用class進行更加靈活的封裝了.
5.使用示例
public boolean getGoodsOver(long goodsId) {
return redisService.exist(MiaoshaKey.isGoodsOver,goodsId+"");
}
public void setGoodsOver(long goodsId) {
//假設這裡的goodsId是1
redisService.set(MiaoshaKey.isGoodsOver,goodsId+"",true);
}
這樣設定到的key就是 miaoshaKey:go:1 值是true
這樣就能夠良好的避免key 的衝突
這個是看了慕課網上的視訊,有感,得到的結果.
Java Framework,歡迎各位前來交流java相關
QQ群:965125360
推薦JVM的視訊:
深入理解Java虛擬機器(jvm效能調優+記憶體模型+虛擬機器原理)
https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.c9e51deb8seTn4&id=583526620411