Merge remote-tracking branch 'origin/后台运营yy' into 后台运营yy

后台运营yy
yangyang 8 months ago
commit b3680db247

@ -11,34 +11,46 @@ import redis.clients.jedis.ShardedJedis;
/** /**
* *
* * Redis Redis 便使
*/ */
@Service("cacheService") @Service("cacheService")
public class CacheService { public class CacheService {
// 定义一个常量作为 Redis 中键的前缀,用于区分不同项目或者模块在 Redis 中的数据,统一添加前缀便于管理和识别。
private final static String REDIS_PRE_KEY = "TAMGUO:"; private final static String REDIS_PRE_KEY = "TAMGUO:";
// 创建一个用于对象序列化和反序列化的工具类实例,用于处理需要存入 Redis 的对象,使其能以合适的格式在 Redis 中存储和读取。
private SerializeTranscoder objectSerialize = new ObjectUtil(); private SerializeTranscoder objectSerialize = new ObjectUtil();
// 通过 Spring 的依赖注入,自动装配 RedisXMLConfigure 实例,该实例可能用于配置 Redis 连接相关信息以及获取和关闭连接等操作。
@Autowired @Autowired
private RedisXMLConfigure redisXMLConfigure; private RedisXMLConfigure redisXMLConfigure;
/** /**
* Redis null
* *
* @Title: get @Description: @param @return String @throws * @param key REDIS_PRE_KEY
* @return Redis null
*/ */
public String get(String key) { public String get(String key) {
// 给传入的键添加前缀,使其符合项目在 Redis 中键的规范格式。
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
// 通过 RedisXMLConfigure 获取 Redis 连接对象ShardedJedis 通常用于在 Redis 集群等场景下获取连接进行操作。
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 使用获取到的连接对象,调用 get 方法从 Redis 中获取对应键的值。
return conn.get(key); return conn.get(key);
} finally { } finally {
// 无论是否成功获取到值,都需要关闭 Redis 连接,通过 RedisXMLConfigure 提供的方法来关闭连接,释放资源。
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
/** /**
* Redis
* *
* @Title: set @Description: @param @return void @throws * @param key
* @param value
*/ */
public void set(String key, String value) { public void set(String key, String value) {
key = getPreKey(key); key = getPreKey(key);
@ -52,16 +64,12 @@ public class CacheService {
} }
/** /**
*
* set * set
* Redis Redis
* *
* @param key * @param key
* @param value * @param value
* @param time * @param time Redis
*
* @description
* @exception @since
* 1.0.0
*/ */
public void set(String key, String value, int time) { public void set(String key, String value, int time) {
key = getPreKey(key); key = getPreKey(key);
@ -69,6 +77,7 @@ public class CacheService {
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
conn.set(key, value); conn.set(key, value);
// 在设置完键值对后,调用 expire 方法设置对应键的过期时间。
conn.expire(key, time); conn.expire(key, time);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
@ -77,17 +86,21 @@ public class CacheService {
/** /**
* redis * redis
* Redis SerializeTranscoder 便 Redis
* *
* @param key key * @param key Redis
* @param value * @param value Redis
*/ */
public void setObject(String key, Object value) { public void setObject(String key, Object value) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 将键转换为字节数组形式(因为 Redis 的底层存储很多操作是基于字节数组的),
// 并使用 objectSerialize 工具类将对象序列化后存入 Redis。
conn.set(key.getBytes(), objectSerialize.serialize(value)); conn.set(key.getBytes(), objectSerialize.serialize(value));
} catch (Exception ex) { } catch (Exception ex) {
// 如果在序列化或者存入过程中出现异常,打印异常堆栈信息,方便排查问题。
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
@ -96,22 +109,26 @@ public class CacheService {
/** /**
* *
* Redis Redis
* *
* @param key key * @param key
* @param value * @param value
* @param time * @param time Redis
*/ */
public void setObject(String key, Object value, int time) { public void setObject(String key, Object value, int time) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 使用 setex 方法,它可以在设置对象值的同时直接指定过期时间,一次性完成存储和过期时间设置操作,
// 先将键转换为字节数组,再将序列化后的对象存入 Redis并设置过期时间。
conn.setex(key.getBytes(), time, objectSerialize.serialize(value)); conn.setex(key.getBytes(), time, objectSerialize.serialize(value));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
}
} }
/** /**
@ -120,18 +137,26 @@ public class CacheService {
* @param key key * @param key key
* @return * @return
*/ */
// 根据给定的键从Redis中获取对应的对象。先对键添加前缀处理然后通过Redis连接获取对象数据若获取到数据则进行反序列化后返回若出现异常或未获取到数据则返回null。
public Object getObject(String key) { public Object getObject(String key) {
// 给传入的键添加前缀使其符合项目在Redis中键的规范格式便于统一管理和准确获取对应的数据。
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
// 通过RedisXMLConfigure获取Redis连接对象ShardedJedis用于在Redis集群等场景下进行操作以便后续与Redis进行交互。
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 从Redis中获取以字节数组形式存储的对象数据因为Redis底层很多操作基于字节数组来处理数据存储和读取。
byte[] obj = conn.get(key.getBytes()); byte[] obj = conn.get(key.getBytes());
// 如果获取到的字节数组为null说明Redis中不存在对应键的数据直接返回null。
if (null == obj) if (null == obj)
return null; return null;
// 使用objectSerialize工具类对获取到的字节数组进行反序列化操作将其转换为原始的对象形式并返回。
return objectSerialize.deserialize(obj); return objectSerialize.deserialize(obj);
} catch (Exception ex) { } catch (Exception ex) {
// 如果在获取数据或者反序列化过程中出现异常,打印异常堆栈信息,方便排查问题所在。
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
// 无论是否成功获取到对象都需要关闭Redis连接通过RedisXMLConfigure提供的方法来关闭连接释放相关资源。
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
return null; return null;
@ -139,15 +164,19 @@ public class CacheService {
/** /**
* *
* RedisRedis
* 1truefalse
* *
* @param key key * @param key keyRedis
* @return * @return truefalse
*/ */
public boolean deleteObject(String key) { public boolean deleteObject(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用Redis连接对象的del方法传入要删除的对象键的字节数组形式尝试删除对应的数据。
// 该方法返回被删除键的数量若返回值等于1L表示成功删除了1个键即对应要删除的对象键则返回true否则返回false。
return conn.del(key.getBytes()) == 1L; return conn.del(key.getBytes()) == 1L;
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -158,15 +187,21 @@ public class CacheService {
} }
/** /**
* key
* 使Redis
* truefalse
* *
* @Title: isExist @Description: key @param @return boolean * @Title: isExist
* @throws * @Description: key
* @param key
* @return Redistruefalse
*/ */
public boolean isExist(String key) { public boolean isExist(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用Redis连接对象的exists方法传入要检查的键该方法会在Redis中查询该键是否存在存在则返回true不存在返回false。
return conn.exists(key); return conn.exists(key);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -176,15 +211,19 @@ public class CacheService {
return false; return false;
} }
// 对isExist方法的结果取反用于判断给定的键在Redis中是否不存在返回值为true表示键不存在false表示键存在。
public boolean notExist(String key) { public boolean notExist(String key) {
return!isExist(key); return!isExist(key);
} }
// 从Redis中删除指定的键及其对应的数据先对键添加前缀处理然后通过Redis连接执行删除操作
// 如果删除操作成功即返回值表示删除的键数量为1则返回true若出现异常或删除失败则返回false。
public boolean delete(String key) { public boolean delete(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用Redis连接对象的del方法传入要删除的键该方法返回被删除键的数量若返回值等于1表示成功删除了1个键即对应要删除的键则返回true否则返回false。
return conn.del(key) == 1; return conn.del(key) == 1;
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -201,47 +240,59 @@ public class CacheService {
* @param value * @param value
* @return * @return
*/ */
// 将指定的值插入到以给定键标识的列表List的末尾并返回插入操作后列表的长度。
// 先对键添加前缀进行规范处理,然后通过获取的 Redis 连接执行插入操作,最后返回列表长度。
public long putToListEnd(String key, String value) { public long putToListEnd(String key, String value) {
// 给传入的键添加前缀,使其符合项目在 Redis 中键的规范格式,便于准确操作对应的列表数据。
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
// 通过 RedisXMLConfigure 获取 Redis 连接对象,用于后续与 Redis 进行交互操作。
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 rpush 方法,将指定的值插入到键对应的列表末尾,
// 该方法会返回操作后列表的长度,即元素个数,然后将此长度返回给调用者。
long length = conn.rpush(key, value); long length = conn.rpush(key, value);
return length; return length;
} finally { } finally {
// 无论插入操作是否成功,都需要关闭 Redis 连接,通过 RedisXMLConfigure 提供的方法来关闭连接,释放资源。
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
/** /**
* valuekey, * valuekey,
* Sorted Set
* addToSortedSet
* *
* @author zhangxin * @author zhangxin
* @param key * @param key Redis
* @param value * @param value
* @param seconds * @param seconds Redis
* @param score * @param score score
* @return long * @return long addToSortedSet
*/ */
public long addToSortedSetAndExpire(String key, String value, int seconds, double score) { public long addToSortedSetAndExpire(String key, String value, int seconds, double score) {
return addToSortedSet(key, value, seconds, true, score); return addToSortedSet(key, value, seconds, true, score);
} }
/** /**
* valuekey valuescore * valuekey valuescore
* Sorted Setscore
* Redis Redis
* *
* @author zhangxin * @author zhangxin
* @param key * @param key Redis
* @param value * @param value
* @param score * @param score
* @return long * @return long Redis zincrby
*/ */
public double addToSortedSetScore(String key, String value, double score) { public double addToSortedSetScore(String key, String value, double score) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zincrby 方法将指定的值插入到键对应的有序集合中并按照给定的分数增量score增加其分数
// 该方法返回更新后的分数值(以 Double 类型表示),然后将此分数值返回给调用者。
Double zincrby = conn.zincrby(key, score, value); Double zincrby = conn.zincrby(key, score, value);
return zincrby; return zincrby;
} finally { } finally {
@ -251,15 +302,20 @@ public class CacheService {
/** /**
* memberScore * memberScore
* @param key * member key score
* @param value * 0
* @return *
* @param key Redis
* @param value
* @return 0 Redis zscore
*/ */
public Double getMemberScore(String key, String member) { public Double getMemberScore(String key, String member) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zscore 方法,尝试获取指定成员在键对应的有序集合中的分数值,
// 该方法返回的分数值可能为 null表示成员不存在若为 null 则返回默认值 0否则返回实际的分数值。
Double zscore = conn.zscore(key, member); Double zscore = conn.zscore(key, member);
return zscore == null? 0 : zscore; return zscore == null? 0 : zscore;
} finally { } finally {
@ -267,31 +323,36 @@ public class CacheService {
} }
} }
/** /**
* valuekey, * valuekey,
* Sorted Set
* addToSortedSet
* *
* @author zhangxin * @author zhangxin
* @param key * @param key Redis
* @param value * @param value
* @param score * @param score score
* @return long * @return long addToSortedSet
*/ */
public long addToSortedSet(String key, String value, double score) { public long addToSortedSet(String key, String value, double score) {
return addToSortedSet(key, value, -1, false, score); return addToSortedSet(key, value, -1, false, score);
} }
/** /**
* member * member
* member key rank
* null true false
* *
* @return isExist true * @return isExist true false
*/ */
public boolean isExistSortedSet(String key, String member) { public boolean isExistSortedSet(String key, String member) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zrank 方法,获取指定成员在键对应的有序集合中的排名,
// 如果成员存在于集合中该方法返回其排名Long 类型),若不存在则返回 null
// 根据返回值是否为 null 来判断成员是否存在,并返回相应的布尔值结果。
Long zrank = conn.zrank(key, member); Long zrank = conn.zrank(key, member);
return zrank!= null; return zrank!= null;
} finally { } finally {
@ -304,30 +365,45 @@ public class CacheService {
* *
* @return isExist true * @return isExist true
*/ */
// 从指定的有序集合Sorted Set中删除给定的成员member并根据删除操作的结果返回一个布尔值表示是否删除成功。
// 成功删除至少一个成员时返回 true否则返回 false。先对键添加前缀规范处理再通过 Redis 连接执行删除操作并判断结果。
public boolean delSortedSetMember(String key, String[] member) { public boolean delSortedSetMember(String key, String[] member) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zrem 方法,传入有序集合的键和要删除的成员数组,尝试从有序集合中删除这些成员。
// 该方法返回被成功删除的成员数量Long 类型),通过判断返回值是否大于等于 1 来确定是否至少成功删除了一个成员,进而返回相应的布尔值结果。
Long zrem = conn.zrem(key, member); Long zrem = conn.zrem(key, member);
return zrem >= 1; return zrem >= 1;
} finally { } finally {
// 无论删除操作是否成功,都要关闭 Redis 连接,通过 RedisXMLConfigure 提供的方法来释放资源。
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
/** /**
* valuekey, setExpirefalse, seconds * valuekey, setExpirefalse, seconds
* Sorted Set
*
* *
* @return * @param key Redis
* @param value
* @param seconds setExpire true
* @param setExpire true false
* @param score score
* @return long Redis zadd
*/ */
private long addToSortedSet(String key, String value, int seconds, boolean setExpire, double score) { private long addToSortedSet(String key, String value, int seconds, boolean setExpire, double score) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zadd 方法将指定的值按照给定的分数score插入到键对应的有序集合中
// 该方法返回成功添加的新成员数量(不包含已存在被更新的成员情况),将此数量赋值给 addNum 变量。
long addNum = conn.zadd(key, score, value); long addNum = conn.zadd(key, score, value);
if (setExpire) { if (setExpire) {
// 如果 setExpire 参数为 true调用 Redis 连接对象的 expire 方法,为有序集合设置过期时间(以 seconds 参数指定的秒数为准)。
conn.expire(key, seconds); conn.expire(key, seconds);
} }
return addNum; return addNum;
@ -338,28 +414,34 @@ public class CacheService {
/** /**
* score * score
* scoreSet<String>
* *
* @author zhangxin * @author zhangxin
* @param key * @param key Redis
* @param pageNo * @param pageNo 1 1 1
* 1 * @param pageSize 1 1
* @param pageSize * @return Set<String> null
* @return Set<String>
*/ */
public Set<String> getSortedSetByPage(String key, int pageNo, int pageSize) { public Set<String> getSortedSetByPage(String key, int pageNo, int pageSize) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
// 对传入的页码进行合法性校验,如果小于 1则将其修正为 1确保页码从 1 开始计数。
if (pageNo < 1) { if (pageNo < 1) {
pageNo = 1; pageNo = 1;
} }
// 对传入的每页记录数量进行合法性校验,如果小于 1则将其修正为 1确保每页至少有 1 条记录。
if (pageSize < 1) { if (pageSize < 1) {
pageSize = 1; pageSize = 1;
} }
// 根据页码和每页记录数量计算出在有序集合中查询的起始索引位置,用于分页获取数据。
int start = (pageNo - 1) * pageSize; int start = (pageNo - 1) * pageSize;
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 zrevrange 方法,按照分数降序的顺序,从指定的有序集合中获取从起始索引到结束索引(通过计算得出)范围内的成员内容,
// 并将结果以集合形式返回,集合中的元素为有序集合的成员(以字符串形式表示)。
return conn.zrevrange(key, start, start + pageSize - 1); return conn.zrevrange(key, start, start + pageSize - 1);
} catch (Exception ex) { } catch (Exception ex) {
// 如果在获取数据过程中出现异常,打印异常堆栈信息,方便排查问题,然后返回 null。
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
@ -367,13 +449,17 @@ public class CacheService {
return null; return null;
} }
// 从以给定键标识的列表List头部获取元素返回获取到的元素列表List<String>),如果列表为空或者获取操作出现异常则返回 null。
public List<String> getListHead(String key) { public List<String> getListHead(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 blpop 方法,尝试从列表头部获取元素,传入超时时间(这里是 1000 毫秒)和列表键,
// 该方法会阻塞等待元素出现,直到超时或者获取到元素,返回获取到的元素列表(可能包含一个或多个元素,以 List<String> 形式表示)。
List<String> result = conn.blpop(1000, key); List<String> result = conn.blpop(1000, key);
// 如果获取到的结果为 null 或者结果列表大小为 0即没有获取到元素则返回 null表示列表为空或获取失败。
if (null == result || result.size() == 0) if (null == result || result.size() == 0)
return null; return null;
return result; return result;
@ -384,59 +470,77 @@ public class CacheService {
/** /**
* map * map
* Redis Hashkeyfield
* 0 1
* *
* @param key * @param key Redis
* @param field map field * @param field map field
* @param value map value * @param value map value
* @return if filed exist return 0 else return 1 * @return if filed exist return 0 else return 1 0 1 Redis hset
*/ */
public Long hset(String key, String field, String value) { public Long hset(String key, String field, String value) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 hset 方法将指定的键key、字段field和值value存储到 Redis 的哈希数据结构中,
// 该方法会根据字段是否已存在返回相应的结果(已存在返回 0不存在返回 1将此结果返回给调用者。
return conn.hset(key, field, value); return conn.hset(key, field, value);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
// 存储map
// 此方法用于将整个映射Map存储到 Redis 的哈希Hash数据结构中以给定的键key作为哈希表的标识一次性存储多个键值对。
// 返回值为存储操作后的结果信息(具体含义可能取决于 Redis 底层实现对应的返回值情况)。
public String hset(String key, Map<String, String> values) { public String hset(String key, Map<String, String> values) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 hmset 方法,将给定的映射(包含多个键值对的 Map存储到指定键对应的哈希数据结构中
// 该方法会执行批量存储操作,并返回相应的结果信息(通常用于表示操作是否成功等情况),将此结果返回给调用者。
return conn.hmset(key, values); return conn.hmset(key, values);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
// 将给定的映射Map存储到 Redis 的哈希Hash数据结构中并为该哈希数据结构设置过期时间。
// 先获取 Redis 连接,执行存储操作后设置过期时间,最后返回存储操作的结果信息。
public String hset(String key, Map<String, String> values, int time) { public String hset(String key, Map<String, String> values, int time) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 hmset 方法将包含多个键值对的映射values存储到以 key 为标识的哈希数据结构中,
// 该方法执行存储操作后会返回相应的结果信息(通常用于表示操作是否成功等情况),将此结果暂存到 hmset 变量中。
String hmset = conn.hmset(key, values); String hmset = conn.hmset(key, values);
// 调用 Redis 连接对象的 expire 方法,为以 key 为标识的哈希数据结构设置过期时间,单位为秒,由 time 参数指定。
conn.expire(key, time); conn.expire(key, time);
return hmset; return hmset;
} finally { } finally {
// 无论存储和设置过期时间操作是否成功,都要关闭 Redis 连接,通过 RedisXMLConfigure 提供的方法来释放资源。
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
/** /**
* mapfield * mapfield
* Redis Hashkeyfield
* *
* @param key * @param key Redis
* @param field map field * @param field map field
* @return * @return null Redis hget
*/ */
public String hget(String key, String field) { public String hget(String key, String field) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 hget 方法,从以 key 为标识的哈希数据结构中获取指定字段field对应的字符串值
// 并将获取到的值直接返回给调用者。
return conn.hget(key, field); return conn.hget(key, field);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
@ -445,15 +549,18 @@ public class CacheService {
/** /**
* keystring1 * keystring1
* Redis key 1 Long
* *
* @param key * @param key 1 Redis
* @return * @return 1 Long Redis 0 1
*/ */
public Long decr(String key) { public Long decr(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 decr 方法,对以 key 为标识的字符串值执行减 1 操作,
// 该方法会自动将字符串值转换为数字类型(如果能转换成功)进行减 1 操作,并返回操作后的结果(以 Long 类型表示),将此结果返回给调用者。
return conn.decr(key); return conn.decr(key);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
@ -462,21 +569,26 @@ public class CacheService {
/** /**
* keystring1 * keystring1
* Redis key 1 Long
* *
* @param key * @param key 1 Redis
* @return * @return 1 Long Redis 0 1
*/ */
public Long incr(String key) { public Long incr(String key) {
key = getPreKey(key); key = getPreKey(key);
ShardedJedis conn = null; ShardedJedis conn = null;
try { try {
conn = redisXMLConfigure.getConnection(); conn = redisXMLConfigure.getConnection();
// 调用 Redis 连接对象的 incr 方法,对以 key 为标识的字符串值执行加 1 操作,
// 该方法会自动将字符串值转换为数字类型(如果能转换成功)进行加 1 操作,并返回操作后的结果(以 Long 类型表示),将此结果返回给调用者。
return conn.incr(key); return conn.incr(key);
} finally { } finally {
redisXMLConfigure.closeConnection(conn); redisXMLConfigure.closeConnection(conn);
} }
} }
// 获取处理后的键,用于在 Redis 操作前统一添加前缀,使键符合项目在 Redis 中的命名规范。
// 如果通过 redisXMLConfigure 获取到的前缀为空则使用类中定义的默认前缀REDIS_PRE_KEY与传入的键拼接否则使用获取到的前缀与键拼接。
private String getPreKey(String key) { private String getPreKey(String key) {
String temp_pre = redisXMLConfigure.getPreKey(); String temp_pre = redisXMLConfigure.getPreKey();
if (null == temp_pre) { if (null == temp_pre) {
@ -484,5 +596,3 @@ public class CacheService {
} }
return temp_pre + key; return temp_pre + key;
} }
}

@ -6,9 +6,13 @@ import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
// ObjectUtil类继承自SerializeTranscoder主要用于实现对象的序列化、反序列化以及提供对象相等性比较的功能。
public class ObjectUtil extends SerializeTranscoder { public class ObjectUtil extends SerializeTranscoder {
// 重写父类的serialize方法用于将给定的对象进行序列化操作即将对象转换为字节数组的形式以便在某些场景下如存储到Redis中进行传输或持久化存储。
@Override @Override
public byte[] serialize(Object value) { public byte[] serialize(Object value) {
// 如果传入要序列化的对象为null则抛出空指针异常因为无法对null对象进行序列化操作。
if (value == null) { if (value == null) {
throw new NullPointerException("Can't serialize null"); throw new NullPointerException("Can't serialize null");
} }
@ -16,54 +20,76 @@ public class ObjectUtil extends SerializeTranscoder {
ByteArrayOutputStream bos = null; ByteArrayOutputStream bos = null;
ObjectOutputStream os = null; ObjectOutputStream os = null;
try { try {
// 创建一个ByteArrayOutputStream它用于在内存中缓冲要序列化的对象数据最终可以转换为字节数组形式。
bos = new ByteArrayOutputStream(); bos = new ByteArrayOutputStream();
// 创建一个ObjectOutputStream它基于ByteArrayOutputStream用于将对象以Java的序列化机制写入到输出流中。
os = new ObjectOutputStream(bos); os = new ObjectOutputStream(bos);
// 使用ObjectOutputStream将传入的对象写入到输出流中进行实际的序列化操作。
os.writeObject(value); os.writeObject(value);
// 关闭ObjectOutputStream释放相关资源一般在写入完成后进行关闭操作确保数据正确写入到输出流中。
os.close(); os.close();
// 关闭ByteArrayOutputStream释放其占用的内存资源此时内部缓冲的数据已经准备好可以转换为字节数组了。
bos.close(); bos.close();
// 将ByteArrayOutputStream中缓冲的数据转换为字节数组这就是最终序列化后的结果赋值给result变量以便返回。
result = bos.toByteArray(); result = bos.toByteArray();
} catch (IOException e) { } catch (IOException e) {
// 如果在序列化过程中出现IO异常比如对象不支持序列化、流操作出现问题等
// 则抛出一个非法参数异常并将原始的IO异常作为原因附带上方便排查问题表明传入的对象可能无法进行序列化操作。
throw new IllegalArgumentException("Non-serializable object", e); throw new IllegalArgumentException("Non-serializable object", e);
} finally { } finally {
// 无论是否成功完成序列化操作都要关闭ObjectOutputStream和ByteArrayOutputStream释放资源避免内存泄漏等问题。
close(os); close(os);
close(bos); close(bos);
} }
return result; return result;
} }
// 重写父类的deserialize方法用于将给定的字节数组进行反序列化操作即将字节数组转换回原始的对象形式通常用于从存储如Redis中读取数据后还原对象。
@Override @Override
public Object deserialize(byte[] in) { public Object deserialize(byte[] in) {
Object result = null; Object result = null;
ByteArrayInputStream bis = null; ByteArrayInputStream bis = null;
ObjectInputStream is = null; ObjectInputStream is = null;
try { try {
// 首先判断传入的字节数组是否为null如果为null则不进行后续的反序列化操作直接返回null。
if (in!= null) { if (in!= null) {
// 创建一个ByteArrayInputStream它以传入的字节数组作为数据源用于后续通过输入流读取数据进行反序列化操作。
bis = new ByteArrayInputStream(in); bis = new ByteArrayInputStream(in);
// 创建一个ObjectInputStream它基于ByteArrayInputStream用于按照Java的序列化机制从输入流中读取数据并还原为对象。
is = new ObjectInputStream(bis); is = new ObjectInputStream(bis);
// 使用ObjectInputStream从输入流中读取数据并还原为对象这是实际的反序列化操作将还原后的对象赋值给result变量。
result = is.readObject(); result = is.readObject();
// 关闭ObjectInputStream释放相关资源确保反序列化操作完成后资源正确释放。
is.close(); is.close();
// 关闭ByteArrayInputStream释放其占用的内存资源。
bis.close(); bis.close();
} }
} catch (IOException e) { } catch (IOException e) {
// 如果在反序列化过程中出现IO异常比如读取流出现问题、数据格式不正确等打印异常堆栈信息方便排查问题。
e.printStackTrace(); e.printStackTrace();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// 如果在反序列化过程中出现找不到对应类的异常(比如还原对象时找不到对象对应的类定义),同样打印异常堆栈信息,便于查找问题所在。
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
// 无论是否成功完成反序列化操作都要关闭ObjectInputStream和ByteArrayInputStream释放资源避免内存泄漏等问题。
close(is); close(is);
close(bis); close(bis);
} }
return result; return result;
} }
// 定义一个静态方法equals用于比较两个对象是否相等遵循Java中对象相等性比较的常规规则。
public static boolean equals(Object o1, Object o2) { public static boolean equals(Object o1, Object o2) {
// 如果两个对象引用完全相同即指向同一个内存地址则直接返回true表示它们相等。
if (o1 == o2) { if (o1 == o2) {
return true; return true;
} else if (o1 == null || o2 == null) { } else if (o1 == null || o2 == null) {
// 如果其中一个对象为null而另一个不为null则返回false表示它们不相等。
return false; return false;
} else { } else {
// 如果两个对象都不为null调用对象的equals方法一般需要重写该方法来定义具体的相等性逻辑来比较它们是否相等并返回相应的结果。
return o1.equals(o2); return o1.equals(o2);
} }
} }
} }

@ -1,13 +1,20 @@
package com.tamguo.config.redis; package com.tamguo.config.redis;
// PoolConfigBean类用于封装与连接池相关的配置参数通过定义相应的属性、构造方法以及访问器getter和setter方法方便对这些配置信息进行设置和获取操作同时重写了toString方法用于方便地输出配置信息的字符串表示形式。
public class PoolConfigBean { public class PoolConfigBean {
// 表示连接池中允许的最大活动连接数,即同一时刻能够同时从连接池中获取并使用的最大连接数量。
private int max_active; private int max_active;
// 表示连接池中允许的最大空闲连接数,即连接池中可以闲置的最大连接数量,当空闲连接数超过这个值时,多余的空闲连接可能会被回收。
private int max_idle; private int max_idle;
// 表示从连接池中获取连接时,最长的等待时间(单位通常为毫秒),如果在这个时间内无法获取到可用连接,则可能会抛出相应的异常,提示获取连接超时。
private long max_wait; private long max_wait;
// 默认的无参构造方法用于创建PoolConfigBean类的实例在没有传入初始参数时可以使用后续可以通过对应的setter方法来设置各个属性的值。
public PoolConfigBean() { public PoolConfigBean() {
} }
// 带参数的构造方法用于在创建PoolConfigBean类实例时同时初始化各个配置属性的值方便一次性设置好相关的连接池配置信息。
public PoolConfigBean(int max_active, int max_idle, long max_wait) { public PoolConfigBean(int max_active, int max_idle, long max_wait) {
super(); super();
this.max_active = max_active; this.max_active = max_active;
@ -15,33 +22,39 @@ public class PoolConfigBean {
this.max_wait = max_wait; this.max_wait = max_wait;
} }
// 获取max_active属性值的方法外部代码可以通过调用这个方法获取连接池中允许的最大活动连接数。
public int getMax_active() { public int getMax_active() {
return max_active; return max_active;
} }
// 设置max_active属性值的方法外部代码可以通过调用这个方法来设置连接池中允许的最大活动连接数。
public void setMax_active(int max_active) { public void setMax_active(int max_active) {
this.max_active = max_active; this.max_active = max_active;
} }
// 获取max_idle属性值的方法外部代码可以通过调用这个方法获取连接池中允许的最大空闲连接数。
public int getMax_idle() { public int getMax_idle() {
return max_idle; return max_idle;
} }
// 设置max_idle属性值的方法外部代码可以通过调用这个方法来设置连接池中允许的最大空闲连接数。
public void setMax_idle(int max_idle) { public void setMax_idle(int max_idle) {
this.max_idle = max_idle; this.max_idle = max_idle;
} }
// 获取max_wait属性值的方法外部代码可以通过调用这个方法获取从连接池中获取连接时的最长等待时间。
public long getMax_wait() { public long getMax_wait() {
return max_wait; return max_wait;
} }
// 设置max_wait属性值的方法外部代码可以通过调用这个方法来设置从连接池中获取连接时的最长等待时间。
public void setMax_wait(long max_wait) { public void setMax_wait(long max_wait) {
this.max_wait = max_wait; this.max_wait = max_wait;
} }
// 重写toString方法用于将PoolConfigBean类的实例以特定的字符串格式进行表示方便在调试、日志输出等场景下直观地查看连接池配置信息的具体内容。
@Override @Override
public String toString() { public String toString() {
return "PoolConfig [max_active=" + max_active + ", max_idle=" + max_idle + ", max_wait=" + max_wait + "]"; return "PoolConfig [max_active=" + max_active + ", max_idle=" + max_idle + ", max_wait=" + max_wait + "]";
} }
} }

@ -1,11 +1,18 @@
package com.tamguo.config.redis; package com.tamguo.config.redis;
// RedisServerNodeBean类用于封装Redis服务器节点的相关信息通过定义相应的属性、构造方法以及对应的访问器getter和setter方法方便对这些信息进行设置、获取以及以字符串形式展示等操作。
public class RedisServerNodeBean { public class RedisServerNodeBean {
// 用于存储Redis服务器的IP地址通过该IP地址可以定位到对应的Redis服务器所在的网络位置以便建立连接。
private String ip; private String ip;
// 用于存储Redis服务器监听的端口号客户端通过指定的IP地址和对应的端口号来与Redis服务器进行通信交互。
private int port; private int port;
// 表示是否需要进行身份验证例如密码验证才能连接到该Redis服务器true表示需要验证false表示不需要验证。
private boolean needAuth; private boolean needAuth;
// 如果needAuth为true即需要进行身份验证时此属性用于存储连接Redis服务器所需的验证密码或其他认证凭据以确保连接的合法性。
private String auth; private String auth;
// 构造方法用于创建RedisServerNodeBean类的实例并在实例化时初始化各个属性的值传入的参数分别对应Redis服务器节点的IP地址、端口号、是否需要认证以及认证凭据密码
public RedisServerNodeBean(String ip, int port, boolean needAuth, String auth) { public RedisServerNodeBean(String ip, int port, boolean needAuth, String auth) {
this.ip = ip; this.ip = ip;
this.port = port; this.port = port;
@ -13,41 +20,49 @@ public class RedisServerNodeBean {
this.auth = auth; this.auth = auth;
} }
// 获取ip属性值的方法外部代码可以通过调用这个方法获取Redis服务器节点的IP地址信息。
public String getIp() { public String getIp() {
return ip; return ip;
} }
// 设置ip属性值的方法外部代码可以通过调用这个方法来修改Redis服务器节点的IP地址信息。
public void setIp(String ip) { public void setIp(String ip) {
this.ip = ip; this.ip = ip;
} }
// 获取port属性值的方法外部代码可以通过调用这个方法获取Redis服务器节点的端口号信息。
public int getPort() { public int getPort() {
return port; return port;
} }
// 设置port属性值的方法外部代码可以通过调用这个方法来修改Redis服务器节点的端口号信息。
public void setPort(int port) { public void setPort(int port) {
this.port = port; this.port = port;
} }
// 获取needAuth属性值的方法外部代码可以通过调用这个方法获取表示是否需要对Redis服务器进行身份验证的布尔值。
public boolean isNeedAuth() { public boolean isNeedAuth() {
return needAuth; return needAuth;
} }
// 设置needAuth属性值的方法外部代码可以通过调用这个方法来修改表示是否需要对Redis服务器进行身份验证的布尔值。
public void setNeedAuth(boolean needAuth) { public void setNeedAuth(boolean needAuth) {
this.needAuth = needAuth; this.needAuth = needAuth;
} }
// 获取auth属性值的方法外部代码可以通过调用这个方法获取连接Redis服务器所需的认证凭据如密码信息。
public String getAuth() { public String getAuth() {
return auth; return auth;
} }
// 设置auth属性值的方法外部代码可以通过调用这个方法来修改连接Redis服务器所需的认证凭据如密码信息。
public void setAuth(String auth) { public void setAuth(String auth) {
this.auth = auth; this.auth = auth;
} }
// 重写toString方法用于将RedisServerNodeBean类的实例以特定的字符串格式进行表示方便在调试、日志输出等场景下直观地展示Redis服务器节点的相关信息内容。
@Override @Override
public String toString() { public String toString() {
return "RedisServer [ip=" + ip + ", port=" + port + ", needAuth=" + needAuth + ", auth=" + auth + "]"; return "RedisServer [ip=" + ip + ", port=" + port + ", needAuth=" + needAuth + ", auth=" + auth + "]";
} }
} }

@ -16,87 +16,124 @@ import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool; import redis.clients.jedis.ShardedJedisPool;
// 标识该类是一个Spring组件在Spring容器启动时会被扫描并实例化其Bean名称为"redisConfigure"用于配置和管理Redis相关的连接等操作。
@Component("redisConfigure") @Component("redisConfigure")
// 实现InitializingBean接口意味着该类在所有属性被设置后会执行afterPropertiesSet方法来进行一些初始化操作通常用于加载配置等前置准备工作。
public class RedisXMLConfigure implements InitializingBean { public class RedisXMLConfigure implements InitializingBean {
// 创建一个日志记录器实例用于记录与该类相关的操作日志方便在运行过程中排查问题以及查看关键信息记录的日志类别基于当前类RedisXMLConfigure。
private static final Logger logger = Logger.getLogger(RedisXMLConfigure.class); private static final Logger logger = Logger.getLogger(RedisXMLConfigure.class);
// 用于存储Redis键的前缀是一个静态变量在整个应用中可以统一为Redis中的键添加特定的前缀方便管理和区分不同用途的键。
private static String preKey; private static String preKey;
// 用于存储解析后的XML配置文档对象后续通过操作这个对象来获取各种Redis配置相关的元素和属性信息初始化为null后续在初始化方法中进行赋值。
private static Document document = null; private static Document document = null;
// 定义一个ShardedJedisPool对象用于管理多个Redis节点的连接池通过它可以获取到ShardedJedis连接实现对Redis集群等多节点环境下的数据访问。
private ShardedJedisPool shardedJedisPool; private ShardedJedisPool shardedJedisPool;
// 实现InitializingBean接口的方法在Spring容器完成属性注入后自动调用用于进行Redis相关配置的初始化工作比如加载XML配置文件、解析配置信息、创建连接池等操作。
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// 创建一个XMLConfiguration对象用于读取和解析XML配置文件它可能封装了一些底层的XML解析相关的逻辑。
XMLConfiguration xmlConfiguration = new XMLConfiguration(); XMLConfiguration xmlConfiguration = new XMLConfiguration();
// 定义要加载的Redis配置文件的路径和文件名这里指定为"redis.xml"表示从类路径下查找该文件来获取Redis配置信息。
String REDIS_PATH = "redis.xml"; String REDIS_PATH = "redis.xml";
InputStream stream = null; InputStream stream = null;
try { try {
// 通过类加载器获取指定路径下的配置文件输入流,如果获取不到(即配置文件不存在或路径错误),则记录错误日志并抛出运行时异常,表示加载配置文件失败。
stream = this.getClass().getClassLoader().getResourceAsStream(REDIS_PATH); stream = this.getClass().getClassLoader().getResourceAsStream(REDIS_PATH);
if (stream == null) { if (stream == null) {
logger.error("load redis.xml failed!!!" + REDIS_PATH); logger.error("load redis.xml failed!!!" + REDIS_PATH);
throw new RuntimeException("load redis.xml failed"); throw new RuntimeException("load redis.xml failed");
} }
logger.info("Redis XML config path:" + REDIS_PATH); logger.info("Redis XML config path:" + REDIS_PATH);
// 使用xmlConfiguration对象读取配置文件输入流中的内容如果读取成功返回true则将解析后的文档对象赋值给document变量以便后续使用若读取失败则记录错误日志。
if (xmlConfiguration.readConfigFile(stream)) { if (xmlConfiguration.readConfigFile(stream)) {
document = xmlConfiguration.getDocument(); document = xmlConfiguration.getDocument();
} else { } else {
logger.error("load redis.xml failed!!!"); logger.error("load redis.xml failed!!!");
} }
} finally { } finally {
// 无论是否成功读取配置文件都要关闭输入流释放相关资源避免资源泄漏通过判断输入流是否为null来进行关闭操作。
if (null!= stream) if (null!= stream)
stream.close(); stream.close();
} }
//初始化参数
// 调用初始化方法用于初始化Redis键的前缀信息从解析后的XML配置中获取相应的值进行设置。
initPreKey(); initPreKey();
// 调用方法初始化连接池的配置参数从XML配置中读取相关属性值创建并返回一个PoolConfigBean对象该对象封装了如最大空闲连接数、最大等待时间等连接池配置信息。
PoolConfigBean pcb = initPoolConfigBean(); PoolConfigBean pcb = initPoolConfigBean();
// 调用方法解析配置文件中关于Redis服务器节点的信息读取每个服务器节点的IP、端口、是否需要认证以及认证密码等信息返回一个包含多个RedisServerNodeBean对象的列表。
List<RedisServerNodeBean> rsnbs = initRedisServerNodeBeans(); List<RedisServerNodeBean> rsnbs = initRedisServerNodeBeans();
//实现shardedJedisPool
// 创建一个JedisPoolConfig对象用于配置Jedis连接池的相关参数后续会基于这个配置对象来创建ShardedJedisPool连接池。
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 注意这里没有设置maxActive可能在当前配置逻辑中有其他考虑比如依赖默认值或者后续有特殊处理而是设置了最大空闲连接数和最大等待时间从之前初始化得到的PoolConfigBean对象中获取相应的参数值进行设置。
//no maxActive config //no maxActive config
jedisPoolConfig.setMaxIdle(pcb.getMax_idle()); jedisPoolConfig.setMaxIdle(pcb.getMax_idle());
jedisPoolConfig.setMaxWaitMillis(pcb.getMax_wait()); jedisPoolConfig.setMaxWaitMillis(pcb.getMax_wait());
// 创建ShardedJedisPool连接池对象传入配置好的JedisPoolConfig对象以及根据解析得到的Redis服务器节点信息转换而来的JedisShardInfo列表用于管理多个Redis节点的连接池方便后续获取连接进行数据操作。
shardedJedisPool = new ShardedJedisPool(jedisPoolConfig, getJedisShardInfo(rsnbs)); shardedJedisPool = new ShardedJedisPool(jedisPoolConfig, getJedisShardInfo(rsnbs));
if (shardedJedisPool == null) { if (shardedJedisPool == null) {
// 如果创建连接池失败返回值为null则抛出运行时异常表示Redis配置文件存在错误导致无法正确创建连接池。
throw new RuntimeException("config redis.xml error"); throw new RuntimeException("config redis.xml error");
} }
} }
/** /**
* jedis * jedis
* XMLPoolConfigBean
*/ */
private PoolConfigBean initPoolConfigBean() { private PoolConfigBean initPoolConfigBean() {
PoolConfigBean poolConfigBean = new PoolConfigBean(); PoolConfigBean poolConfigBean = new PoolConfigBean();
// 通过文档对象查找名为"pool"的XML元素获取配置文件中关于连接池的配置节点假设配置文件中以特定的XML结构来定义连接池相关属性。
Element poolElement = (Element) document.getElementsByTagName("pool").item(0); Element poolElement = (Element) document.getElementsByTagName("pool").item(0);
// 判断"pool"元素是否有"maxActive"属性如果有则将其解析为整数并赋值给max_active变量否则将其设置为 -1表示可能使用默认值或者后续有其他处理逻辑来确定该参数
int max_active = poolElement.hasAttribute("maxActive")? Integer.parseInt(poolElement.getAttribute("maxActive")) : -1; int max_active = poolElement.hasAttribute("maxActive")? Integer.parseInt(poolElement.getAttribute("maxActive")) : -1;
// 类似地,获取"maxIdle"属性的值如果存在则解析为整数赋值给max_idle变量否则设置为 -1。
int max_idle = poolElement.hasAttribute("maxIdle")? Integer.parseInt(poolElement.getAttribute("maxIdle")) : -1; int max_idle = poolElement.hasAttribute("maxIdle")? Integer.parseInt(poolElement.getAttribute("maxIdle")) : -1;
// 获取"maxWait"属性的值存在则解析为长整型赋值给max_wait变量否则设置为 -1。
long max_wait = poolElement.hasAttribute("maxWait")? Long.parseLong(poolElement.getAttribute("maxWait")) : -1; long max_wait = poolElement.hasAttribute("maxWait")? Long.parseLong(poolElement.getAttribute("maxWait")) : -1;
// 通过PoolConfigBean对象的setter方法将获取到的各个参数值设置到对象中以便后续返回并用于创建JedisPoolConfig对象时设置相应的连接池参数。
poolConfigBean.setMax_active(max_active); poolConfigBean.setMax_active(max_active);
poolConfigBean.setMax_idle(max_idle); poolConfigBean.setMax_idle(max_idle);
poolConfigBean.setMax_wait(max_wait); poolConfigBean.setMax_wait(max_wait);
return poolConfigBean; return poolConfigBean;
} }
/** /**
* redisserver * redisserver
* XMLRedisIPRedisServerNodeBeanRedis
*/ */
private List<RedisServerNodeBean> initRedisServerNodeBeans() { private List<RedisServerNodeBean> initRedisServerNodeBeans() {
List<RedisServerNodeBean> redisServers = new ArrayList<RedisServerNodeBean>(); List<RedisServerNodeBean> redisServers = new ArrayList<RedisServerNodeBean>();
// 通过文档对象查找所有名为"server"的XML元素获取配置文件中定义的所有Redis服务器节点的配置节点列表后续遍历该列表来解析每个服务器节点的详细信息。
NodeList serverElements = document.getElementsByTagName("server"); NodeList serverElements = document.getElementsByTagName("server");
int serverLen = serverElements.getLength(); int serverLen = serverElements.getLength();
if (serverLen < 1) { if (serverLen < 1) {
// 如果没有找到任何"server"元素即没有配置Redis服务器节点信息记录错误日志并返回null表示配置不合法。
logger.error("redis.servers.server must have one!"); logger.error("redis.servers.server must have one!");
return null; return null;
} }
for (int i = 0; i < serverLen; i++) { for (int i = 0; i < serverLen; i++) {
// 遍历每个"server"元素获取对应的Element对象用于解析该服务器节点的具体属性信息。
Element serverElement = (Element) serverElements.item(i); Element serverElement = (Element) serverElements.item(i);
// 获取"server"元素中"ip"属性的值如果存在则赋值给temp_ip变量否则设置为null表示IP地址未配置这是不符合要求的情况后续会进行相应的错误处理
String temp_ip = serverElement.hasAttribute("ip")? serverElement.getAttribute("ip") : null; String temp_ip = serverElement.hasAttribute("ip")? serverElement.getAttribute("ip") : null;
if (temp_ip == null) { if (temp_ip == null) {
// 如果IP地址为空记录错误日志并返回null表示配置不合法因为IP地址是连接Redis服务器必需的信息。
logger.error("redis.servers.server.ip must be supplied!"); logger.error("redis.servers.server.ip must be supplied!");
return null; return null;
} }
// 获取"server"元素中"port"属性的值如果存在则赋值给temp_port变量否则默认设置为"6379"Redis默认端口号确保端口号有一个合理的值。
String temp_port = serverElement.hasAttribute("port")? serverElement.getAttribute("port") : "6379"; String temp_port = serverElement.hasAttribute("port")? serverElement.getAttribute("port") : "6379";
// 获取"server"元素中"needAuth"属性的值如果存在则赋值给temp_needAuth变量否则默认设置为"false",表示默认不需要进行身份验证。
String temp_needAuth = serverElement.hasAttribute("needAuth")? serverElement.getAttribute("needAuth") : "false"; String temp_needAuth = serverElement.hasAttribute("needAuth")? serverElement.getAttribute("needAuth") : "false";
String temp_auth = null; String temp_auth = null;
// need auth // 如果"needAuth"属性的值为"true",即表示需要进行身份验证,那么获取"auth"属性的值认证密码如果不存在则记录错误日志并返回null表示配置不合法因为需要认证时密码是必需的。
if ("true".equals(temp_needAuth)) { if ("true".equals(temp_needAuth)) {
temp_auth = serverElement.hasAttribute("auth")? serverElement.getAttribute("auth") : null; temp_auth = serverElement.hasAttribute("auth")? serverElement.getAttribute("auth") : null;
if (null == temp_auth) { if (null == temp_auth) {
@ -107,11 +144,14 @@ public class RedisXMLConfigure implements InitializingBean {
RedisServerNodeBean rs = null; RedisServerNodeBean rs = null;
try { try {
// 尝试创建一个RedisServerNodeBean对象传入解析得到的IP地址、端口号、是否需要认证的布尔值以及认证密码如果需要认证等信息将创建的对象赋值给rs变量。
// 如果端口号解析为整数失败即不是合法的数字格式会捕获NumberFormatException异常记录错误日志并返回null表示配置不合法。
rs = new RedisServerNodeBean(temp_ip, Integer.parseInt(temp_port), Boolean.parseBoolean(temp_needAuth), temp_auth); rs = new RedisServerNodeBean(temp_ip, Integer.parseInt(temp_port), Boolean.parseBoolean(temp_needAuth), temp_auth);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
logger.error("port must be a number!\n" + e.getMessage()); logger.error("port must be a number!\n" + e.getMessage());
return null; return null;
} }
// 将创建好的代表Redis服务器节点配置信息的对象添加到列表中最终返回包含所有服务器节点配置信息的列表。
redisServers.add(rs); redisServers.add(rs);
} }
return redisServers; return redisServers;
@ -119,26 +159,35 @@ public class RedisXMLConfigure implements InitializingBean {
/** /**
* JedisShardInfo * JedisShardInfo
* @param redisServers * RedisList<RedisServerNodeBean>ShardedJedisPoolJedisShardInfo
* @return * JedisShardInfoRedisIP便使
*
* @param redisServers RedisinitRedisServerNodeBeans
* @return JedisShardInfoShardedJedisPoolRedis
*/ */
private List<JedisShardInfo> getJedisShardInfo(List<RedisServerNodeBean> redisServers) { private List<JedisShardInfo> getJedisShardInfo(List<RedisServerNodeBean> redisServers) {
if (redisServers == null) { if (redisServers == null) {
// 如果传入的Redis服务器节点列表为null记录错误日志并返回null表示参数不合法无法进行后续的转换操作。
logger.error("redisServers must not be empty null"); logger.error("redisServers must not be empty null");
return null; return null;
} }
int serverLen = redisServers.size(); int serverLen = redisServers.size();
if (serverLen < 1) { if (serverLen < 1) {
// 如果列表中没有任何元素即没有配置有效的Redis服务器节点记录错误日志并返回null表示不符合要求因为连接池至少需要一个有效的节点信息来创建。
logger.error("redisServers must not be empty "); logger.error("redisServers must not be empty ");
return null; return null;
} }
List<JedisShardInfo> servers = new ArrayList<JedisShardInfo>(serverLen); List<JedisShardInfo> servers = new ArrayList<JedisShardInfo>(serverLen);
for (int i = 0; i < serverLen; i++) { for (int i = 0; i < serverLen; i++) {
// 遍历传入的Redis服务器节点列表获取每个RedisServerNodeBean对象代表一个服务器节点的配置信息。
RedisServerNodeBean redisServer = redisServers.get(i); RedisServerNodeBean redisServer = redisServers.get(i);
// 创建一个JedisShardInfo对象传入该服务器节点的IP地址和端口号信息用于构建与该节点的连接相关信息初始状态下不包含密码信息如果需要认证后续再单独设置
JedisShardInfo jedisShardInfo = new JedisShardInfo(redisServer.getIp(), redisServer.getPort()); JedisShardInfo jedisShardInfo = new JedisShardInfo(redisServer.getIp(), redisServer.getPort());
if (redisServer.isNeedAuth()) { if (redisServer.isNeedAuth()) {
// 如果该服务器节点需要进行身份验证通过RedisServerNodeBean对象的isNeedAuth方法判断则设置对应的认证密码从RedisServerNodeBean对象中获取密码信息并设置到JedisShardInfo对象中。
jedisShardInfo.setPassword(redisServer.getAuth()); jedisShardInfo.setPassword(redisServer.getAuth());
} }
// 将配置好的JedisShardInfo对象添加到列表中最终返回包含所有服务器节点连接信息的JedisShardInfo列表用于创建ShardedJedisPool连接池。
servers.add(jedisShardInfo); servers.add(jedisShardInfo);
} }
return servers; return servers;
@ -146,28 +195,35 @@ public class RedisXMLConfigure implements InitializingBean {
/* /*
* rediskey * rediskey
* XMLRedispreKey便Redis
*/ */
private void initPreKey() { private void initPreKey() {
Element preKeyElement = (Element) document.getElementsByTagName("preKey").item(0); Element preKeyElement = (Element) document.getElementsByTagName("preKey").item(0);
preKey = preKeyElement.hasAttribute("value")? preKeyElement.getAttribute("value") : ""; preKey = preKeyElement.hasAttribute("value")? preKeyElement.getAttribute("value") : "";
} }
// 获取Redis键前缀的方法外部代码可以通过调用该方法获取当前配置的Redis键前缀信息用于在操作Redis时为键添加合适的前缀。
public String getPreKey() { public String getPreKey() {
return preKey; return preKey;
} }
/** /**
* jedis * jedis
* @return * ShardedJedisPoolShardedJedis便Redis
*
* @return ShardedJedisRedis
*/ */
public ShardedJedis getConnection() { public ShardedJedis getConnection() {
return shardedJedisPool.getResource(); return shardedJedisPool.getResource();
} }
/** /**
* jedis * jedis
* @param resource * 使ShardedJedisShardedJedisPool便
*
* @param resource ShardedJedisgetConnection使
*/ */
public void closeConnection(ShardedJedis resource) { public void closeConnection(ShardedJedis resource) {
resource.close(); resource.close();
} }
} }

@ -2,12 +2,22 @@ package com.tamguo.config.redis;
import java.io.Closeable; import java.io.Closeable;
// SerializeTranscoder是一个抽象类用于定义对象序列化和反序列化相关的操作规范同时提供了一个用于关闭可关闭资源实现了Closeable接口的对象的通用方法
// 具体的序列化和反序列化逻辑需要由继承它的子类去实现。
public abstract class SerializeTranscoder { public abstract class SerializeTranscoder {
// 抽象方法serialize用于将给定的对象进行序列化操作将对象转换为字节数组的形式。
// 具体的序列化实现细节由继承该抽象类的子类来定义不同的子类可以根据实际需求采用不同的序列化策略如Java原生序列化、JSON序列化等
// 参数value表示要进行序列化的对象返回值为序列化后的字节数组。
public abstract byte[] serialize(Object value); public abstract byte[] serialize(Object value);
// 抽象方法deserialize用于将给定的字节数组进行反序列化操作将字节数组还原为原始的对象形式。
// 同样,具体的反序列化实现由子类负责,要根据序列化时采用的策略来正确还原对象。
// 参数in表示要进行反序列化的字节数组返回值为反序列化后得到的对象。
public abstract Object deserialize(byte[] in); public abstract Object deserialize(byte[] in);
// 定义一个方法close用于关闭实现了Closeable接口的资源对象如输入输出流等以释放相关的系统资源避免资源泄漏等问题。
// 参数closeable表示要关闭的可关闭资源对象如果传入的对象不为null则尝试调用其close方法进行关闭操作若关闭过程中出现异常则打印异常堆栈信息以便排查问题。
public void close(Closeable closeable) { public void close(Closeable closeable) {
if (closeable!= null) { if (closeable!= null) {
try { try {

@ -8,25 +8,37 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
// XMLConfiguration类主要用于读取和解析XML配置文件并提供获取解析后文档对象Document的方法支持通过文件名和输入流InputStream两种方式来加载配置文件进行解析。
public class XMLConfiguration { public class XMLConfiguration {
// 用于存储解析后的XML文档对象初始化为null在成功读取并解析配置文件后会将对应的Document对象赋值给该变量方便后续获取和使用解析结果。
private Document document = null; private Document document = null;
// 通过指定的配置文件名称字符串形式的文件名及路径来读取并解析XML配置文件若解析成功则返回true若出现异常导致解析失败document仍为null则返回false。
public boolean readConfigFile(String configFilename) { public boolean readConfigFile(String configFilename) {
// 创建一个DocumentBuilderFactory实例它是用于创建DocumentBuilder对象的工厂类通过它可以按照默认配置创建用于解析XML文档的DocumentBuilder。
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try { try {
// 使用DocumentBuilderFactory创建一个DocumentBuilder对象该对象用于实际解析XML文档将其解析为内存中的Document对象表示形式。
DocumentBuilder db = dbf.newDocumentBuilder(); DocumentBuilder db = dbf.newDocumentBuilder();
// 调用DocumentBuilder的parse方法传入配置文件的名称路径作为参数尝试解析该XML配置文件并将解析后的Document对象赋值给document变量。
document = db.parse(configFilename); document = db.parse(configFilename);
} catch (IOException e) { } catch (IOException e) {
// 如果在解析过程中出现IO异常例如文件不存在、无法读取文件等情况打印异常堆栈信息方便排查问题但不中断程序执行继续执行后续的返回值判断逻辑。
e.printStackTrace(); e.printStackTrace();
} catch (Exception e) { } catch (Exception e) {
// 捕获其他可能出现的异常除了IO异常之外的比如XML格式错误等导致解析失败的异常同样打印异常堆栈信息以便查找问题所在然后继续执行返回值判断逻辑。
e.printStackTrace(); e.printStackTrace();
} }
// 判断解析后的Document对象是否为null如果为null说明解析过程出现问题导致没有成功获取到有效的文档对象返回false表示读取配置文件失败否则返回true表示成功。
if (document == null) { if (document == null) {
return false; return false;
} }
return true; return true;
} }
// 通过给定的输入流InputStream来读取并解析XML配置文件逻辑与readConfigFile(String configFilename)方法类似若解析成功则返回true失败则返回false。
// 常用于从类路径下获取资源流或者其他来源的输入流来解析配置文件的场景。
public boolean readConfigFile(InputStream stream) { public boolean readConfigFile(InputStream stream) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try { try {
@ -43,10 +55,12 @@ public class XMLConfiguration {
return true; return true;
} }
// 获取解析后的XML文档对象的方法外部代码可以通过调用该方法获取之前成功解析配置文件后得到的Document对象以便进一步操作文档中的元素、属性等内容。
public Document getDocument() { public Document getDocument() {
return document; return document;
} }
// 受保护的方法用于设置解析后的XML文档对象一般在类内部或者子类中可以根据需要调用该方法来更新document变量的值通常不是由外部直接调用而是在特定的内部逻辑中使用。
protected void setDocument(Document document) { protected void setDocument(Document document) {
this.document = document; this.document = document;
} }

Loading…
Cancel
Save