
net.wicp.tams.common.redis.pool.AbsPool Maven / Gradle / Ivy
The newest version!
/*
* **********************************************************************
* Copyright (c) 2022 .
* All rights reserved.
* 项目名称:common
* 项目描述:公共的工具集
* 版权说明:本软件属andy.zhou([email protected])所有。
* ***********************************************************************
*/
package net.wicp.tams.common.redis.pool;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.pool2.impl.AbandonedConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.apiext.ReflectAssist;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.exception.ExceptAll;
import net.wicp.tams.common.exception.ProjectExceptionRuntime;
import net.wicp.tams.common.redis.RedisAssit;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.StreamEntryID;
import redis.clients.jedis.params.SetParams;
import redis.clients.jedis.params.XAddParams;
import redis.clients.jedis.params.XReadGroupParams;
import redis.clients.jedis.resps.StreamEntry;
import redis.clients.jedis.util.Pool;
@SuppressWarnings({ "rawtypes", "unchecked" })
public abstract class AbsPool {
/*****
* 把对象做为Map存放到Redis
*
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param obj 要放入的对象
* @param 对象的类型
* @param expire 超时时间,单位(秒)
*/
public static void putObjByMap(Jedis jedis, String key, T obj, Integer expire) {
Map inpumap = ReflectAssist.convertMapFromBean(obj);
jedis.hmset(key, inpumap);
if (expire != null) {
jedis.expire(key, expire);
}
}
/***
* ###############sadd动作用于汇总所有相关的key值 把对象做为Map存放到Redis,没有超时时间,永久性放入
*
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param 对象的类型
* @param obj 要放入的对象
*/
public static void putObjByMap(Jedis jedis, String key, T obj) {
putObjByMap(jedis, key, obj, null);
}
/***
* 把对象做为Map存放到Redis,并把key存到 groupkey中
*
* @param
* @param jedis
* @param key
* @param groupkey
* @param obj
*/
public static void putObjByMap(Jedis jedis, String key, String groupkey, T obj) {
jedis.sadd(groupkey, key);
putObjByMap(jedis, key, obj);
}
/***
* 把对象做为Json存放到Redis
*
* @param jedis 连接的引用,外部传入
* @param obj 要放入的对象
* @param key 要放入的key值
* @param 对象的类型
* @param expire 超时时间,单位(秒)
*/
public final static void putObjByJson(Jedis jedis, T obj, String key, Integer expire) {
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(obj);
jedis.set(key, json);
if (expire != null) {
jedis.expire(key, expire);
}
} catch (Exception e) {
throw new ProjectExceptionRuntime(ExceptAll.Project_default, e);
}
}
/****
* 把对象做为Json存放到Redis
*
* @param jedis 连接的引用,外部传入
* @param obj 要放入的对象
* @param 对象的类型
* @param key 要放入的key值
*/
public final static void putObjByJson(Jedis jedis, T obj, String key) {
putObjByJson(jedis, obj, key, null);
}
/***
* 枚举类型的map放到缓存
*
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param 对象的类型
* @param inputMap 要存放的map,它的key是一个枚举值
*/
public final static void putEnumMap(Jedis jedis, String key, Map inputMap) {
if (jedis == null || MapUtils.isEmpty(inputMap) || StringUtil.isNull(key)) {
return;
}
Map input = new HashMap<>();
for (Enum ele : inputMap.keySet()) {
input.put(ele.name(), inputMap.get(ele));
}
jedis.hmset(key, input);
}
/****
* 得到枚举类的缓存对象
*
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param clazz 枚举所对应的类
* @return 返回的枚举
*/
public final static Map getEnumMap(Jedis jedis, String key, Class clazz) {
Object[] objs = clazz.getEnumConstants();
String[] fields = new String[objs.length];
for (int i = 0; i < fields.length; i++) {
Enum tempobj = (Enum) objs[i];
fields[i] = tempobj.name();
}
List rets = jedis.hmget(key, fields);
Map retobj = new HashMap<>();
for (int i = 0; i < fields.length; i++) {
Enum curobj = null;
for (Object object : objs) {
Enum tempobj = (Enum) object;
if (fields[i].equals(tempobj.name())) {
curobj = tempobj;
break;
}
}
retobj.put((T) curobj, rets.get(i));
}
return retobj;
}
/***
* 取指定列的值
*
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param fields 要取的列名
* @return
*/
public static Map getMapByField(Jedis jedis, String key, String... fields) {
Map retobj = new HashMap();
if (jedis == null || StringUtil.isNull(key) || ArrayUtils.isEmpty(fields) || !jedis.exists(key)) {
return retobj;
}
List values = jedis.hmget(key, fields);
if (ArrayUtils.isNotEmpty(fields) && CollectionUtils.isNotEmpty(values)) {
for (int i = 0; i < fields.length; i++) {
retobj.put(fields[i], values.get(i));
}
}
return retobj;
}
/***
* Redis上的值为Map,取对象的值,没有指定字段就取全部
*
* @param clazz 要返回的对象的类
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param 对象的类型
* @param fields 要取的列名
* @return 要返回的对象
*/
public static T getObjByMapValue(Class clazz, Jedis jedis, String key, String... fields) {
if (ArrayUtils.isEmpty(fields)) {
List classfields = ReflectAssist.findGetField(clazz);
fields = classfields.toArray(new String[classfields.size()]);
}
Map retmap = getMapByField(jedis, key, fields);
T rett = (T) ReflectAssist.convertMapToBean(clazz, retmap);
return rett;
}
public static T getObjByMapValue(Class clazz, Jedis jedis, String key) {
List list = ReflectAssist.findGetField(clazz);
String[] array = list.toArray(new String[list.size()]);
return getObjByMapValue(clazz, jedis, key, array);
}
/***
* Redis上的值为Json,取对象的值
*
* @param clazz 要返回的对象的类
* @param jedis 连接的引用,外部传入
* @param key 要放入的key值
* @param 对象的类型
* @return
*/
public static T getObjByJsonValue(Class clazz, Jedis jedis, String key) {
String jsonstr = jedis.get(String.valueOf(key));
ObjectMapper objmap = new ObjectMapper();
try {
T value = objmap.readValue(jsonstr, clazz);
return value;
} catch (Exception e) {
throw new ProjectExceptionRuntime(ExceptAll.Project_default, e);
}
}
// /***
// * 释放资源
// *
// * @param jedis 要释放的连接
// */
// public static void returnResource(Jedis jedis) {
// if (jedis != null) {
// try {
// jedis.close();
// } catch (Exception e) {
//
// }
// }
// }
public abstract Jedis getResource();
public abstract void returnResource(Jedis jedis);
public abstract void returnBrokenResource(Jedis jedis);
/***
* 池废弃
*/
public abstract void destroy();
public abstract boolean isInit();
protected void doLeak(String serverName, Pool jedisPool) {
Map data = Conf
.getAllConfigValues(String.format("%s.%s", "common.redis.redisserver", serverName), true);
if (RedisAssit.getConfigInt(data, "leak.second") > 0) {
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setRemoveAbandonedOnMaintenance(true); // 在Maintenance的时候检查是否有泄漏
abandonedConfig.setRemoveAbandonedOnBorrow(true); // borrow 的时候检查泄漏
abandonedConfig.setRemoveAbandonedTimeout(RedisAssit.getConfigInt(data, "leak.second")); // 如果一个对象borrow之后默认10秒还没有返还给pool,认为是泄漏的对象
// jedis2.9时需要通过反射搞定。4.1不需要了
// @SuppressWarnings("unchecked")
// GenericObjectPool poolInner = (GenericObjectPool) ReflectAssist.getPrivateField(jedisPool,
// "internalPool");
// poolInner.setAbandonedConfig(abandonedConfig);
jedisPool.setAbandonedConfig(abandonedConfig);
}
}
///////////////////////////////////// 一些工具//////////////////////////////////////////////////////////////////
public T findByRedis(Class calssz, String key) {
Jedis jedis = getResource();
try {
T t = AbsPool.getObjByMapValue(calssz, jedis, key);
return t;
} finally {
returnResource(jedis);
}
}
public void putRedis(T saveobj, String key) {
Jedis jedis = getResource();
try {
AbsPool.putObjByMap(jedis, key, saveobj);
} finally {
returnResource(jedis);
}
}
/**
* 使用redis进行分布式加锁操作
*
* @param key 锁的key
* @param value 加锁的值
* @param expireTime 获取锁的单位毫秒
* @return
*/
public boolean tryDistributedLock(Jedis jedis, String key, String value, int expireTime) {
SetParams params = new SetParams();
String result = jedis.set(key.getBytes(), value.getBytes(), params.nx().px(expireTime));
if ("OK".equals(result)) {
return true;
} else {
return false;
}
}
/***
* 将数据传入stream,这个stream最大允许存max条记录
*
* @param jedis 连接
* @param streamkey 队列名
* @param max 队列最大值
* @param content 传入的内容
* @return
*/
public StreamEntryID putStream(Jedis jedis, String streamkey, long max, Map content) {
// new StreamEntryID().NEW_ENTR = * ,代表id由redis生成
// 也可以指定stream最多存储多少条记录。--自己查api
XAddParams params = XAddParams.xAddParams();
params.maxLen(max);
params.id(StreamEntryID.NEW_ENTRY);
return jedis.xadd(streamkey, params, content);
}
/***
* 传入二进制数据
*
* @param jedis
* @param streamkey
* @param max
* @param content
* @return
*/
public byte[] putStreamByte(Jedis jedis, String streamkey, long max, Map content) {
// new StreamEntryID().NEW_ENTR = * ,代表id由redis生成
// 也可以指定stream最多存储多少条记录。--自己查api
XAddParams params = XAddParams.xAddParams();
params.maxLen(max);
params.id(StreamEntryID.NEW_ENTRY);
return jedis.xadd(streamkey.getBytes(), params, content);
}
public StreamEntryID putStream(Jedis jedis, String streamkey, Map content) {
return putStream(jedis, streamkey, Conf.getLong("common.redis.client.stream.max"), content);
}
public byte[] putStreamByte(Jedis jedis, String streamkey, Map content) {
return putStreamByte(jedis, streamkey, Conf.getLong("common.redis.client.stream.max"), content);
}
/***
* 阻塞获取stream的最后一条记录,由于是长链接,可能会Broken,所以自己来拿连接并自己管理,
*
* @param streamkey 队列key
* @param groupname 队列group名
* @return 惟一的那条数据
*/
public Map getStreamBlockOne(String streamkey, String groupname) {
Jedis jedis = this.getResource();
try {
String xgroupCreate = jedis.xgroupCreate(streamkey, groupname, StreamEntryID.LAST_ENTRY, true);
if (!"OK".equals(xgroupCreate)) {// 创建失败?
System.out.println(xgroupCreate);
}
} catch (Throwable e) {
if (e.getMessage().contains("Group name already exists")) {
// 一般来说是group已创建异常
// e.printStackTrace();
} else {
returnResource(jedis);
throw new ProjectExceptionRuntime(ExceptAll.Project_default, "创建stream组失败", e);
}
}
try {
XReadGroupParams params = XReadGroupParams.xReadGroupParams();
params.block(Conf.getInt("common.redis.client.stream.blocktimes"));// 永久阻塞,1000表示阻塞1S
params.count(Conf.getInt("common.redis.client.stream.batchPreNum"));// 拿1条消息
Map streams = new HashMap();
// > 号表示从当前消费组的 last_delivered_id 后面开始读
streams.put(streamkey, StreamEntryID.UNRECEIVED_ENTRY);
// 元素组成: key:streamkey value:streamkey对应的值,
List>> xreadGroup = jedis.xreadGroup(groupname,
Conf.get("common.redis.client.stream.consumer"), params, streams);
StreamEntry streamEntry = xreadGroup.get(0).getValue().get(0);
Map retmap = streamEntry.getFields();
// 到此有可能此链接已超时被费掉了。
// if(jedis.isBroken()) {
// jedis.close();
// }
return retmap;
} finally {
returnResource(jedis);
}
}
// 从消息里拿到duckula消息
public Pair getStreamBlockOneDuckulaEvent(String streamkey, String groupname) {
Jedis jedis = this.getResource();
try {
// 从头开始消费
String xgroupCreate = jedis.xgroupCreate(streamkey, groupname, null, true);
if (!"OK".equals(xgroupCreate)) {// 创建失败?
System.out.println(xgroupCreate);
}
} catch (Throwable e) {
if (e.getMessage().contains("Group name already exists")) {
// 一般来说是group已创建异常
// e.printStackTrace();
} else {
returnResource(jedis);
throw new ProjectExceptionRuntime(ExceptAll.Project_default, "创建stream组失败", e);
}
}
try {
XReadGroupParams params = XReadGroupParams.xReadGroupParams();
params.block(Conf.getInt("common.redis.client.stream.blocktimes"));// 永久阻塞,1000表示阻塞1S
params.count(Conf.getInt("common.redis.client.stream.batchPreNum"));// 拿1条消息
// params.noAck();//不需要ack,表示不会进入到待处理列表
Map streams = new HashMap();
// > 号表示从当前消费组的 last_delivered_id 后面开始读
streams.put(streamkey.getBytes(), StreamEntryID.UNRECEIVED_ENTRY.toString().getBytes());
// 元素组成: key:streamkey value:streamkey对应的值,
List xreadGroup = jedis.xreadGroup(groupname.getBytes(),
Conf.get("common.redis.client.stream.consumer").getBytes(), params,
streams.entrySet().iterator().next());
if (CollectionUtils.isEmpty(xreadGroup)) {// 出错了:Unknown reply: 1
return null;
}
List all = (List) xreadGroup.get(0);
String key = new String((byte[]) all.get(0));// 例如:dim:demo:user_info:control:stream
List ele = ((List) all.get(1));
List dataHasIdList = ((List) ele.get(0));
// 队列的key
String idValue = new String((byte[]) dataHasIdList.get(0));// 例如:1655808258188-0
List datalist = ((List) dataHasIdList.get(1));
// data或time
String key1 = new String((byte[]) datalist.get(0));
// String key2= new String((byte[])datalist.get(2));
jedis.xack(streamkey.getBytes(), groupname.getBytes(), idValue.getBytes());// 手动ack
if ("data".equals(key1)) {
byte[] dataValue = (byte[]) datalist.get(1);
String time = new String((byte[]) datalist.get(3));
return Pair.of(new Long(time), dataValue);
} else {
byte[] dataValue = (byte[]) datalist.get(3);
String time = new String((byte[]) datalist.get(1));
return Pair.of(new Long(time), dataValue);
}
} catch (Throwable e) {
return null;
} finally {
returnResource(jedis);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy